Browse code

- missing "goto error" added in parse_to() - function for parsing content-disposition added; function available for searching & parsing the header and alos only for parsing a string that's a disposition; parser supports quoted values for params (along with escaped chars inside quoted strings)

Bogdan-Andrei Iancu authored on 10/09/2003 12:07:43
Showing 4 changed files
... ...
@@ -44,6 +44,7 @@
44 44
 #include "parse_expires.h"
45 45
 #include "parse_rr.h"
46 46
 #include "contact/parse_contact.h"
47
+#include "parse_disposition.h"
47 48
 #include "../ut.h"
48 49
 
49 50
 
... ...
@@ -145,6 +146,7 @@ void clean_hdr_field(struct hdr_field* hf)
145 146
 			break;
146 147
 
147 148
 		case HDR_CONTENTDISPOSITION:
149
+			free_disposition( ((struct disposition**)(&hf->parsed)) );
148 150
 			break;
149 151
 
150 152
 		default:
151 153
new file mode 100644
... ...
@@ -0,0 +1,431 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ *
5
+ * Copyright (C) 2001-2003 Fhg Fokus
6
+ *
7
+ * This file is part of ser, a free SIP server.
8
+ *
9
+ * ser is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * For a license to use the ser software under conditions
15
+ * other than those described here, or to purchase support for this
16
+ * software, please contact iptel.org by e-mail at the following addresses:
17
+ *    info@iptel.org
18
+ *
19
+ * ser is distributed in the hope that it will be useful,
20
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
+ * GNU General Public License for more details.
23
+ *
24
+ * You should have received a copy of the GNU General Public License 
25
+ * along with this program; if not, write to the Free Software 
26
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
+ *
28
+ * History:
29
+ * 2003-09-09 created (bogdan)
30
+ */
31
+
32
+
33
+#include <stdio.h>
34
+#include <stdlib.h>
35
+#include <sys/types.h>
36
+#include <unistd.h>
37
+#include "../mem/mem.h"
38
+#include "../dprint.h"
39
+#include "../ut.h"
40
+#include "parse_disposition.h"
41
+
42
+
43
+
44
+/* parse a string that supposed to be a disposition and fills up the structure
45
+ * Returns: -1 : error
46
+ *           o : sucess */
47
+int parse_disposition( str *s, struct disposition *disp)
48
+{
49
+	enum { FIND_TYPE, TYPE, END_TYPE, FIND_PARAM, PARAM, END_PARAM, FIND_VAL,
50
+	       FIND_QUOTED_VAL, QUOTED_VAL, SKIP_QUOTED_VAL, VAL, END_VAL,
51
+	       F_LF, F_CR, F_CRLF};
52
+	struct disposition_param *disp_p;
53
+	struct disposition_param *new_p;
54
+	int  state;
55
+	int  saved_state;
56
+	char *tmp;
57
+	char *end;
58
+
59
+	state = saved_state = FIND_TYPE;
60
+	end = s->s + s->len;
61
+	disp_p = 0;
62
+
63
+	for( tmp=s->s; tmp<end; tmp++) {
64
+		switch(*tmp) {
65
+			case ' ':
66
+			case '\t':
67
+				switch (state) {
68
+					case FIND_QUOTED_VAL:
69
+						disp_p->body.s = tmp;
70
+						state = QUOTED_VAL;
71
+						break;
72
+					case SKIP_QUOTED_VAL:
73
+						state = QUOTED_VAL;
74
+						break;
75
+					case TYPE:
76
+						disp->type.len = tmp - disp->type.s;
77
+						state = END_TYPE;
78
+						break;
79
+					case PARAM:
80
+						disp_p->name.len = tmp - disp_p->name.s;
81
+						state = END_PARAM;
82
+						break;
83
+					case VAL:
84
+						disp_p->body.len = tmp - disp_p->body.s;
85
+						state = END_VAL;
86
+						break;
87
+					case F_CRLF:
88
+					case F_LF:
89
+					case F_CR:
90
+						/*previous=crlf and now =' '*/
91
+						state=saved_state;
92
+						break;
93
+				}
94
+				break;
95
+			case '\n':
96
+				switch (state) {
97
+					case TYPE:
98
+						disp->type.len = tmp - disp->type.s;
99
+						saved_state = END_TYPE;
100
+						state = F_LF;
101
+						break;
102
+					case PARAM:
103
+						disp_p->name.len = tmp - disp_p->name.s;
104
+						saved_state = END_PARAM;
105
+						state = F_LF;
106
+						break;
107
+					case VAL:
108
+						disp_p->body.len = tmp - disp_p->body.s;
109
+						saved_state = END_VAL;
110
+						state = F_CR;
111
+						break;
112
+					case FIND_TYPE:
113
+					case FIND_PARAM:
114
+						saved_state=state;
115
+						state=F_LF;
116
+						break;
117
+					case F_CR:
118
+						state=F_CRLF;
119
+						break;
120
+					default:
121
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
122
+							"char [%c] in status %d: <<%.*s>> .\n",
123
+							*tmp,state, (int)(tmp-s->s), s->s);
124
+						goto error;
125
+				}
126
+				break;
127
+			case '\r':
128
+				switch (state) {
129
+					case TYPE:
130
+						disp->type.len = tmp - disp->type.s;
131
+						saved_state = END_TYPE;
132
+						state = F_CR;
133
+						break;
134
+					case PARAM:
135
+						disp_p->name.len = tmp - disp_p->name.s;
136
+						saved_state = END_PARAM;
137
+						state = F_CR;
138
+						break;
139
+					case VAL:
140
+						disp_p->body.len = tmp - disp_p->body.s;
141
+						saved_state = END_VAL;
142
+						state = F_CR;
143
+						break;
144
+					case FIND_TYPE:
145
+					case FIND_PARAM:
146
+						saved_state=state;
147
+						state=F_CR;
148
+						break;
149
+					default:
150
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
151
+							"char [%c] in status %d: <<%.*s>> .\n",
152
+							*tmp,state, (int)(tmp-s->s), ZSW(s->s));
153
+						goto error;
154
+				}
155
+				break;
156
+			case 0:
157
+				LOG(L_ERR,"ERROR:parse_disposition: unexpected "
158
+					"char [%c] in status %d: <<%.*s>> .\n",
159
+					*tmp,state, (int)(tmp-s->s), ZSW(s->s));
160
+				goto error;
161
+				break;
162
+			case ';':
163
+				switch (state) {
164
+					case FIND_QUOTED_VAL:
165
+						disp_p->body.s = tmp;
166
+						state = QUOTED_VAL;
167
+						break;
168
+					case SKIP_QUOTED_VAL:
169
+						state = QUOTED_VAL;
170
+					case QUOTED_VAL:
171
+						break;
172
+					case VAL:
173
+						disp_p->body.len = tmp - disp_p->body.s;
174
+						state = FIND_PARAM;
175
+						break;
176
+					case PARAM:
177
+						disp_p->name.len = tmp - disp_p->name.s;
178
+						state = FIND_PARAM;
179
+						break;
180
+					case TYPE:
181
+						disp->type.len = tmp - disp->type.s;
182
+					case END_TYPE:
183
+					case END_VAL:
184
+						state = FIND_PARAM;
185
+						break;
186
+					default:
187
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
188
+							"char [%c] in status %d: <<%.*s>> .\n",
189
+							*tmp,state, (int)(tmp-s->s), ZSW(s->s));
190
+						goto error;
191
+				}
192
+				break;
193
+			case '=':
194
+				switch (state) {
195
+					case FIND_QUOTED_VAL:
196
+						disp_p->body.s = tmp;
197
+						state = QUOTED_VAL;
198
+						break;
199
+					case SKIP_QUOTED_VAL:
200
+						state = QUOTED_VAL;
201
+					case QUOTED_VAL:
202
+						break;
203
+					case PARAM:
204
+						disp_p->name.len = tmp - disp_p->name.s;
205
+					case END_PARAM:
206
+						state = FIND_VAL;
207
+						break;
208
+					default:
209
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
210
+							"char [%c] in status %d: <<%.*s>> .\n",
211
+							*tmp,state, (int)(tmp-s->s), ZSW(s->s));
212
+						goto error;
213
+				}
214
+				break;
215
+			case '\"':
216
+				switch (state) {
217
+					case SKIP_QUOTED_VAL:
218
+						state = QUOTED_VAL;
219
+						break;
220
+					case FIND_VAL:
221
+						state = FIND_QUOTED_VAL;
222
+						break;
223
+					case QUOTED_VAL:
224
+						disp_p->body.len = tmp - disp_p->body.s;
225
+						disp_p->is_quoted = 1;
226
+						state = END_VAL;
227
+						break;
228
+					default:
229
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
230
+							"char [%c] in status %d: <<%.*s>> .\n",
231
+							*tmp,state, (int)(tmp-s->s), ZSW(s->s));
232
+						goto error;
233
+				}
234
+				break;
235
+			case '\\':
236
+				switch (state) {
237
+					case FIND_QUOTED_VAL:
238
+						disp_p->body.s = tmp;
239
+						state = SKIP_QUOTED_VAL;
240
+						break;
241
+					case SKIP_QUOTED_VAL:
242
+						state = QUOTED_VAL;
243
+						break;
244
+					case QUOTED_VAL:
245
+						state = SKIP_QUOTED_VAL;
246
+						break;
247
+					default:
248
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
249
+							"char [%c] in status %d: <<%.*s>> .\n",
250
+							*tmp,state, (int)(tmp-s->s), ZSW(s->s));
251
+						goto error;
252
+				}
253
+				break;
254
+			case '(':
255
+			case ')':
256
+			case '<':
257
+			case '>':
258
+			case '@':
259
+			case ',':
260
+			case ':':
261
+			case '/':
262
+			case '[':
263
+			case ']':
264
+			case '?':
265
+			case '{':
266
+			case '}':
267
+				switch (state) {
268
+					case FIND_QUOTED_VAL:
269
+						disp_p->body.s = tmp;
270
+						state = QUOTED_VAL;
271
+						break;
272
+					case SKIP_QUOTED_VAL:
273
+						state = QUOTED_VAL;
274
+					case QUOTED_VAL:
275
+						break;
276
+					default:
277
+						LOG(L_ERR,"ERROR:parse_disposition: unexpected "
278
+							"char [%c] in status %d: <<%.*s>> .\n",
279
+							*tmp,state, (int)(tmp-s->s), ZSW(s->s));
280
+						goto error;
281
+				}
282
+				break;
283
+			default:
284
+				switch (state) {
285
+					case SKIP_QUOTED_VAL:
286
+						state = QUOTED_VAL;
287
+					case QUOTED_VAL:
288
+						break;
289
+					case FIND_TYPE:
290
+						disp->type.s = tmp;
291
+						state = TYPE;
292
+						break;
293
+					case FIND_PARAM:
294
+						new_p=(struct disposition_param*)pkg_malloc
295
+							(sizeof(struct disposition_param));
296
+						if (new_p==0) {
297
+							LOG(L_ERR,"ERROR:parse_disposition: no more "
298
+								"pkg mem\n");
299
+							goto error;
300
+						}
301
+						memset(new_p,0,sizeof(struct disposition_param));
302
+						if (disp_p==0)
303
+							disp->params = new_p;
304
+						else
305
+							disp_p->next = new_p;
306
+						disp_p = new_p;
307
+						disp_p->name.s = tmp;
308
+						state = PARAM;
309
+						break;
310
+					case FIND_VAL:
311
+						disp_p->body.s = tmp;
312
+						state = VAL;
313
+						break;
314
+					case FIND_QUOTED_VAL:
315
+						disp_p->body.s = tmp;
316
+						state = QUOTED_VAL;
317
+						break;
318
+				}
319
+		}/*switch*/
320
+	}/*for*/
321
+
322
+	/* check which was the last parser state */
323
+	switch (state) {
324
+		case END_PARAM:
325
+		case END_TYPE:
326
+		case END_VAL:
327
+			break;
328
+		case TYPE:
329
+			disp->type.len = tmp - disp->type.s;
330
+			break;
331
+		case PARAM:
332
+			disp_p->name.len = tmp - disp_p->name.s;
333
+			break;
334
+		case VAL:
335
+			disp_p->body.len = tmp - disp_p->body.s;
336
+			break;
337
+		default:
338
+			LOG(L_ERR,"ERROR:parse_disposition: wrong final state (%d)\n",
339
+				state);
340
+			goto error;
341
+	}
342
+	return 0;
343
+error:
344
+	return -1;
345
+}
346
+
347
+
348
+
349
+/* Frees the entire disposition structure (params + itself) */
350
+void free_disposition( struct disposition **disp)
351
+{
352
+	struct disposition_param *param;
353
+
354
+	/* free the params */
355
+	while((*disp)->params) {
356
+		param = (*disp)->params->next;
357
+		pkg_free( (*disp)->params);
358
+		(*disp)->params = param;
359
+	}
360
+	pkg_free( *disp );
361
+	*disp = 0;
362
+}
363
+
364
+
365
+
366
+/* looks inside the message, gets the Content-Disposition hdr, parse it, builds
367
+ * and fills a disposition strucure for it what will be attached to hdr as
368
+ * parsed link.
369
+ * Returns:  -1 : error
370
+ *            0 : success
371
+ *            1 : hdr not found
372
+ */
373
+int parse_content_disposition( struct sip_msg *msg )
374
+{
375
+	struct disposition *disp;
376
+
377
+	/* look for Content-Disposition header */
378
+	if (msg->content_disposition==0) {
379
+		if (parse_headers(msg,HDR_CONTENTDISPOSITION,0)==-1)
380
+			goto error;
381
+		if (msg->content_disposition==0) {
382
+			DBG("DEBUG:parse_content_disposition: hdr not found\n");
383
+			return 1;
384
+		}
385
+	}
386
+
387
+	/* now, we have the headr -> look if it isn't already parsed */
388
+	if (msg->content_disposition->parsed!=0) {
389
+		/* already parsed, nothing more to be done */
390
+		return 0;
391
+	}
392
+
393
+	/* parse the body */
394
+	disp = (struct disposition*)pkg_malloc(sizeof(struct disposition));
395
+	if (disp==0) {
396
+		LOG(L_ERR,"ERROR:parse_content_disposition: no more pkg memory\n");
397
+		goto error;
398
+	}
399
+	memset(disp,0,sizeof(struct disposition));
400
+
401
+	if (parse_disposition( &(msg->content_disposition->body), disp)==-1) {
402
+		/* error when parsing the body */
403
+		free_disposition( &disp );
404
+		goto error;
405
+	}
406
+
407
+	/* attach the parsed form to the header */
408
+	msg->content_disposition->parsed = (void*)disp;
409
+
410
+	return 0;
411
+error:
412
+	return -1;
413
+}
414
+
415
+
416
+/* Prints recursiv a disposition structure */
417
+void print_disposition( struct disposition *disp)
418
+{
419
+	struct disposition_param *param;
420
+
421
+	DBG("*** Disposition type=<%.*s>[%d]\n",
422
+		disp->type.len,disp->type.s,disp->type.len);
423
+	for( param=disp->params; param; param=param->next) {
424
+		DBG("*** DIsposition param: <%.*s>[%d]=<%.*s>[%d] is_quoted=%d\n",
425
+			param->name.len,param->name.s, param->name.len,
426
+			param->body.len,param->body.s, param->body.len,
427
+			param->is_quoted);
428
+	}
429
+}
430
+
431
+
0 432
new file mode 100644
... ...
@@ -0,0 +1,80 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ *
5
+ * Copyright (C) 2001-2003 Fhg Fokus
6
+ *
7
+ * This file is part of ser, a free SIP server.
8
+ *
9
+ * ser is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * For a license to use the ser software under conditions
15
+ * other than those described here, or to purchase support for this
16
+ * software, please contact iptel.org by e-mail at the following addresses:
17
+ *    info@iptel.org
18
+ *
19
+ * ser is distributed in the hope that it will be useful,
20
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
+ * GNU General Public License for more details.
23
+ *
24
+ * You should have received a copy of the GNU General Public License 
25
+ * along with this program; if not, write to the Free Software 
26
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
+ *
28
+ * History:
29
+ * 2003-09-09 created (bogdan)
30
+ */
31
+
32
+#ifndef _PARSE_DISPOSITION_H_
33
+#define _PARSE_DISPOSITION_H_
34
+
35
+#include "../str.h"
36
+#include "msg_parser.h"
37
+
38
+
39
+#define get_content_disposition(_msg_) \
40
+	((struct content_disposition*)((_msg_)->content_disposition->parsed))
41
+
42
+
43
+struct disposition_param {
44
+	str name;
45
+	str body;
46
+	int is_quoted;
47
+	struct disposition_param *next;
48
+};
49
+
50
+
51
+struct disposition {
52
+	str type;
53
+	struct disposition_param *params;
54
+};
55
+
56
+
57
+/* looks inside the message, gets the Content-Disposition hdr, parse it, builds
58
+ * and fills a disposition strucure for it what will be attached to hdr as
59
+ * parsed link.
60
+ * Returns:  -1 : error
61
+ *            0 : success
62
+ *            1 : hdr not found
63
+ */
64
+int parse_content_disposition( struct sip_msg *msg );
65
+
66
+
67
+/* parse a string that supposed to be a disposition and fills up the structure
68
+ * Returns: -1 : error
69
+ *           o : sucess */
70
+int parse_disposition( str *s, struct disposition *disp);
71
+
72
+
73
+/* Frees the entire disposition structure (params + itself) */
74
+void free_disposition( struct disposition **disp);
75
+
76
+/* Prints recursiv a disposition structure */
77
+void print_disposition( struct disposition *disp);
78
+
79
+#endif
80
+
... ...
@@ -145,6 +145,7 @@ static /*inline*/ char* parse_to_param(char *buffer, char *end,
145 145
 						LOG( L_ERR , "ERROR: parse_to_param : "
146 146
 							"unexpected char [%c] in status %d: <<%.*s>> .\n",
147 147
 							*tmp,status, (int)(tmp-buffer), ZSW(buffer));
148
+						goto error;
148 149
 				}
149 150
 				break;
150 151
 			case '\r':
... ...
@@ -459,8 +460,8 @@ static /*inline*/ char* parse_to_param(char *buffer, char *end,
459 460
 						/*previous=crlf and now !=' '*/
460 461
 						goto endofheader;
461 462
 					default:
462
-						DBG("DEBUG: parse_to_param: "
463
-						"spitting out [%c] in status %d\n",*tmp,status );
463
+						LOG(L_ERR, "ERROR: parse_to_param: "
464
+							"spitting out [%c] in status %d\n",*tmp,status );
464 465
 						goto error;
465 466
 				}
466 467
 		}/*switch*/
... ...
@@ -550,6 +551,7 @@ char* parse_to(char* buffer, char *end, struct to_body *to_b)
550 551
 						LOG( L_ERR , "ERROR: parse_to : unexpected char [%c] "
551 552
 							"in status %d: <<%.*s>> .\n",
552 553
 							*tmp,status, (int)(tmp-buffer), ZSW(buffer));
554
+						goto error;
553 555
 				}
554 556
 				break;
555 557
 			case '\r':