summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/mime/mailmime_disposition.c
Unidiff
Diffstat (limited to 'libetpan/src/low-level/mime/mailmime_disposition.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/mime/mailmime_disposition.c595
1 files changed, 595 insertions, 0 deletions
diff --git a/libetpan/src/low-level/mime/mailmime_disposition.c b/libetpan/src/low-level/mime/mailmime_disposition.c
new file mode 100644
index 0000000..eb1d846
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_disposition.c
@@ -0,0 +1,595 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailmime_disposition.h"
37#include "mailmime.h"
38
39#include <ctype.h>
40#include <stdlib.h>
41
42static int
43mailmime_disposition_parm_parse(const char * message, size_t length,
44 size_t * index,
45 struct mailmime_disposition_parm **
46 result);
47
48static int
49mailmime_creation_date_parm_parse(const char * message, size_t length,
50 size_t * index, char ** result);
51
52static int
53mailmime_filename_parm_parse(const char * message, size_t length,
54 size_t * index, char ** result);
55
56static int
57mailmime_modification_date_parm_parse(const char * message, size_t length,
58 size_t * index, char ** result);
59
60static int
61mailmime_read_date_parm_parse(const char * message, size_t length,
62 size_t * index, char ** result);
63
64static int
65mailmime_size_parm_parse(const char * message, size_t length,
66 size_t * index, size_t * result);
67
68static int
69mailmime_quoted_date_time_parse(const char * message, size_t length,
70 size_t * index, char ** result);
71
72/*
73 disposition := "Content-Disposition" ":"
74 disposition-type
75 *(";" disposition-parm)
76
77*/
78
79
80int mailmime_disposition_parse(const char * message, size_t length,
81 size_t * index,
82 struct mailmime_disposition ** result)
83{
84 size_t final_token;
85 size_t cur_token;
86 struct mailmime_disposition_type * dsp_type;
87 clist * list;
88 struct mailmime_disposition * dsp;
89 int r;
90 int res;
91
92 cur_token = * index;
93
94 r = mailmime_disposition_type_parse(message, length, &cur_token,
95 &dsp_type);
96 if (r != MAILIMF_NO_ERROR) {
97 res = r;
98 goto err;
99 }
100
101 list = clist_new();
102 if (list == NULL) {
103 res = MAILIMF_ERROR_MEMORY;
104 goto free_type;
105 }
106
107 while (1) {
108 struct mailmime_disposition_parm * param;
109
110 final_token = cur_token;
111 r = mailimf_unstrict_char_parse(message, length, &cur_token, ';');
112 if (r == MAILIMF_NO_ERROR) {
113 /* do nothing */
114 }
115 else if (r == MAILIMF_ERROR_PARSE) {
116 break;
117 }
118 else {
119 res = r;
120 goto free_list;
121 }
122
123 r = mailmime_disposition_parm_parse(message, length, &cur_token, &param);
124 if (r == MAILIMF_NO_ERROR) {
125 /* do nothing */
126 }
127 else if (r == MAILIMF_ERROR_PARSE) {
128 cur_token = final_token;
129 break;
130 }
131 else {
132 res = r;
133 goto free_list;
134 }
135
136 r = clist_append(list, param);
137 if (r < 0) {
138 res = MAILIMF_ERROR_MEMORY;
139 goto free_list;
140 }
141 }
142
143 dsp = mailmime_disposition_new(dsp_type, list);
144 if (dsp == NULL) {
145 res = MAILIMF_ERROR_MEMORY;
146 goto free_list;
147 }
148
149 * result = dsp;
150 * index = cur_token;
151
152 return MAILIMF_NO_ERROR;
153
154 free_list:
155 clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL);
156 clist_free(list);
157 free_type:
158 mailmime_disposition_type_free(dsp_type);
159 err:
160 return res;
161}
162
163 /*
164 disposition-type := "inline"
165 / "attachment"
166 / extension-token
167 ; values are not case-sensitive
168
169*/
170
171
172
173int
174mailmime_disposition_type_parse(const char * message, size_t length,
175 size_t * index,
176 struct mailmime_disposition_type ** result)
177{
178 size_t cur_token;
179 int type;
180 char * extension;
181 struct mailmime_disposition_type * dsp_type;
182 int r;
183 int res;
184
185 cur_token = * index;
186
187 r = mailimf_cfws_parse(message, length, &cur_token);
188 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
189 res = r;
190 goto err;
191 }
192
193 type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */
194
195 extension = NULL;
196 r = mailimf_token_case_insensitive_parse(message, length,
197 &cur_token, "inline");
198 if (r == MAILIMF_NO_ERROR)
199 type = MAILMIME_DISPOSITION_TYPE_INLINE;
200
201 if (r == MAILIMF_ERROR_PARSE) {
202 r = mailimf_token_case_insensitive_parse(message, length,
203 &cur_token, "attachment");
204 if (r == MAILIMF_NO_ERROR)
205 type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT;
206 }
207
208 if (r == MAILIMF_ERROR_PARSE) {
209 r = mailmime_extension_token_parse(message, length, &cur_token,
210 &extension);
211 if (r == MAILIMF_NO_ERROR)
212 type = MAILMIME_DISPOSITION_TYPE_EXTENSION;
213 }
214
215 if (r != MAILIMF_NO_ERROR) {
216 res = r;
217 goto err;
218 }
219
220 dsp_type = mailmime_disposition_type_new(type, extension);
221 if (dsp_type == NULL) {
222 res = MAILIMF_ERROR_MEMORY;
223 goto free;
224 }
225
226 * result = dsp_type;
227 * index = cur_token;
228
229 return MAILIMF_NO_ERROR;
230
231 free:
232 if (extension != NULL)
233 free(extension);
234 err:
235 return res;
236}
237
238/*
239 disposition-parm := filename-parm
240 / creation-date-parm
241 / modification-date-parm
242 / read-date-parm
243 / size-parm
244 / parameter
245*/
246
247
248int mailmime_disposition_guess_type(const char * message, size_t length,
249 size_t index)
250{
251 if (index >= length)
252 return MAILMIME_DISPOSITION_PARM_PARAMETER;
253
254 switch ((char) toupper((unsigned char) message[index])) {
255 case 'F':
256 return MAILMIME_DISPOSITION_PARM_FILENAME;
257 case 'C':
258 return MAILMIME_DISPOSITION_PARM_CREATION_DATE;
259 case 'M':
260 return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE;
261 case 'R':
262 return MAILMIME_DISPOSITION_PARM_READ_DATE;
263 case 'S':
264 return MAILMIME_DISPOSITION_PARM_SIZE;
265 default:
266 return MAILMIME_DISPOSITION_PARM_PARAMETER;
267 }
268}
269
270static int
271mailmime_disposition_parm_parse(const char * message, size_t length,
272 size_t * index,
273 struct mailmime_disposition_parm **
274 result)
275{
276 char * filename;
277 char * creation_date;
278 char * modification_date;
279 char * read_date;
280 size_t size;
281 struct mailmime_parameter * parameter;
282 size_t cur_token;
283 struct mailmime_disposition_parm * dsp_parm;
284 int type;
285 int guessed_type;
286 int r;
287 int res;
288
289 cur_token = * index;
290
291 filename = NULL;
292 creation_date = NULL;
293 modification_date = NULL;
294 read_date = NULL;
295 size = 0;
296 parameter = NULL;
297
298 r = mailimf_cfws_parse(message, length, &cur_token);
299 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
300 res = r;
301 goto err;
302 }
303
304 guessed_type = mailmime_disposition_guess_type(message, length, cur_token);
305
306 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
307
308 switch (guessed_type) {
309 case MAILMIME_DISPOSITION_PARM_FILENAME:
310 r = mailmime_filename_parm_parse(message, length, &cur_token,
311 &filename);
312 if (r == MAILIMF_NO_ERROR)
313 type = guessed_type;
314 else if (r == MAILIMF_ERROR_PARSE) {
315 /* do nothing */
316 }
317 else {
318 res = r;
319 goto err;
320 }
321 break;
322
323 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
324 r = mailmime_creation_date_parm_parse(message, length, &cur_token,
325 &creation_date);
326 if (r == MAILIMF_NO_ERROR)
327 type = guessed_type;
328 else if (r == MAILIMF_ERROR_PARSE) {
329 /* do nothing */
330 }
331 else {
332 res = r;
333 goto err;
334 }
335 break;
336
337 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
338 r = mailmime_modification_date_parm_parse(message, length, &cur_token,
339 &modification_date);
340 if (r == MAILIMF_NO_ERROR)
341 type = guessed_type;
342 else if (r == MAILIMF_ERROR_PARSE) {
343 /* do nothing */
344 }
345 else {
346 res = r;
347 goto err;
348 }
349 break;
350
351 case MAILMIME_DISPOSITION_PARM_READ_DATE:
352 r = mailmime_read_date_parm_parse(message, length, &cur_token,
353 &read_date);
354 if (r == MAILIMF_NO_ERROR)
355 type = guessed_type;
356 else if (r == MAILIMF_ERROR_PARSE) {
357 /* do nothing */
358 }
359 else {
360 res = r;
361 goto err;
362 }
363 break;
364
365 case MAILMIME_DISPOSITION_PARM_SIZE:
366 r = mailmime_size_parm_parse(message, length, &cur_token,
367 &size);
368 if (r == MAILIMF_NO_ERROR)
369 type = guessed_type;
370 else if (r == MAILIMF_ERROR_PARSE) {
371 /* do nothing */
372 }
373 else {
374 res = r;
375 goto err;
376 }
377 break;
378 }
379
380 if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) {
381 r = mailmime_parameter_parse(message, length, &cur_token,
382 &parameter);
383 if (r != MAILIMF_NO_ERROR) {
384 type = guessed_type;
385 res = r;
386 goto err;
387 }
388 }
389
390 dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date,
391 modification_date, read_date,
392 size, parameter);
393
394 if (dsp_parm == NULL) {
395 res = MAILIMF_ERROR_MEMORY;
396 goto free;
397 }
398
399 * result = dsp_parm;
400 * index = cur_token;
401
402 return MAILIMF_NO_ERROR;
403
404 free:
405 if (filename != NULL)
406 mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename);
407 if (creation_date != NULL)
408 mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date);
409 if (modification_date != NULL)
410 mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date);
411 if (read_date != NULL)
412 mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date);
413 if (parameter != NULL)
414 mailmime_parameter_free(dsp_parm->pa_data.pa_parameter);
415 err:
416 return res;
417}
418
419/*
420 filename-parm := "filename" "=" value
421*/
422
423static int
424mailmime_filename_parm_parse(const char * message, size_t length,
425 size_t * index, char ** result)
426{
427 char * value;
428 int r;
429 size_t cur_token;
430
431 cur_token = * index;
432
433 r = mailimf_token_case_insensitive_parse(message, length,
434 &cur_token, "filename");
435 if (r != MAILIMF_NO_ERROR)
436 return r;
437
438 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
439 if (r != MAILIMF_NO_ERROR)
440 return r;
441
442 r = mailmime_value_parse(message, length, &cur_token, &value);
443 if (r != MAILIMF_NO_ERROR)
444 return r;
445
446 * index = cur_token;
447 * result = value;
448
449 return MAILIMF_NO_ERROR;
450}
451
452/*
453 creation-date-parm := "creation-date" "=" quoted-date-time
454*/
455
456static int
457mailmime_creation_date_parm_parse(const char * message, size_t length,
458 size_t * index, char ** result)
459{
460 char * value;
461 int r;
462 size_t cur_token;
463
464 cur_token = * index;
465
466 r = mailimf_token_case_insensitive_parse(message, length,
467 &cur_token, "creation-date");
468 if (r != MAILIMF_NO_ERROR)
469 return r;
470
471 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474
475 r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value);
476 if (r != MAILIMF_NO_ERROR)
477 return r;
478
479 * index = cur_token;
480 * result = value;
481
482 return MAILIMF_NO_ERROR;
483}
484
485/*
486 modification-date-parm := "modification-date" "=" quoted-date-time
487*/
488
489static int
490mailmime_modification_date_parm_parse(const char * message, size_t length,
491 size_t * index, char ** result)
492{
493 char * value;
494 size_t cur_token;
495 int r;
496
497 cur_token = * index;
498
499 r = mailimf_token_case_insensitive_parse(message, length,
500 &cur_token, "modification-date");
501 if (r != MAILIMF_NO_ERROR)
502 return r;
503
504 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
505 if (r != MAILIMF_NO_ERROR)
506 return r;
507
508 r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value);
509 if (r != MAILIMF_NO_ERROR)
510 return r;
511
512 * index = cur_token;
513 * result = value;
514
515 return MAILIMF_NO_ERROR;
516}
517
518/*
519 read-date-parm := "read-date" "=" quoted-date-time
520*/
521
522static int
523mailmime_read_date_parm_parse(const char * message, size_t length,
524 size_t * index, char ** result)
525{
526 char * value;
527 size_t cur_token;
528 int r;
529
530 cur_token = * index;
531
532 r = mailimf_token_case_insensitive_parse(message, length,
533 &cur_token, "read-date");
534 if (r != MAILIMF_NO_ERROR)
535 return r;
536
537 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
538 if (r != MAILIMF_NO_ERROR)
539 return r;
540
541 r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value);
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544
545 * index = cur_token;
546 * result = value;
547
548 return MAILIMF_NO_ERROR;
549}
550
551/*
552 size-parm := "size" "=" 1*DIGIT
553*/
554
555static int
556mailmime_size_parm_parse(const char * message, size_t length,
557 size_t * index, size_t * result)
558{
559 uint32_t value;
560 size_t cur_token;
561 int r;
562
563 cur_token = * index;
564
565 r = mailimf_token_case_insensitive_parse(message, length,
566 &cur_token, "size");
567 if (r != MAILIMF_NO_ERROR)
568 return r;
569
570 r = mailimf_unstrict_char_parse(message, length, &cur_token, '=');
571 if (r != MAILIMF_NO_ERROR)
572 return r;
573
574 r = mailimf_number_parse(message, length, &cur_token, &value);
575 if (r != MAILIMF_NO_ERROR)
576 return r;
577
578 * index = cur_token;
579 * result = value;
580
581 return MAILIMF_NO_ERROR;
582}
583
584/*
585 quoted-date-time := quoted-string
586 ; contents MUST be an RFC 822 `date-time'
587 ; numeric timezones (+HHMM or -HHMM) MUST be used
588*/
589
590static int
591mailmime_quoted_date_time_parse(const char * message, size_t length,
592 size_t * index, char ** result)
593{
594 return mailimf_quoted_string_parse(message, length, index, result);
595}