~ubuntu-branches/ubuntu/vivid/altermime/vivid

« back to all changes in this revision

Viewing changes to .pc/20_fix-unused-but-set-variables.diff/MIME_headers.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Valroff
  • Date: 2011-05-03 20:05:16 UTC
  • Revision ID: james.westby@ubuntu.com-20110503200516-65pvhk1wlozfickl
Tags: 0.3.10-7
* Update VCS fields
* Add lintian override for false positive spelling error 
* Add patch to Fix compiler warnings for 'unused-but-set-variable' causing
  FTBFS with -Werror and GCC 4.6 (Closes: #625307)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-----------------------------------------------------------------------
 
2
 **
 
3
 **
 
4
 ** MIME_headers
 
5
 **
 
6
 ** Written by Paul L Daniels, originally for the Xamime project
 
7
 ** (http://www.xamime.com) but since spawned off to the ripMIME/alterMIME
 
8
 ** family of email parsing tools.
 
9
 **
 
10
 ** Copyright PLD, 1999,2000,2001,2002,2003
 
11
 ** Licence: BSD
 
12
 ** For more information on the licence and copyrights of this code, please
 
13
 **     email copyright@pldaniels.com
 
14
 
 
15
 ** CHANGES
 
16
 ** 2003-Jun-24: PLD: Added subject parsing
 
17
 **
 
18
 
 
19
 */
 
20
 
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
#include <syslog.h>
 
25
#include <ctype.h>
 
26
#include <errno.h>
 
27
#include <ctype.h>
 
28
#include <sys/types.h>
 
29
#include <sys/stat.h>
 
30
#include <unistd.h>
 
31
 
 
32
 
 
33
#include "ffget.h"
 
34
#include "pldstr.h"
 
35
#include "libmime-decoders.h"
 
36
#include "logger.h"
 
37
#include "strstack.h"
 
38
#include "boundary-stack.h"
 
39
#include "filename-filters.h"
 
40
#include "MIME_headers.h"
 
41
 
 
42
 
 
43
#ifndef FL
 
44
#define FL __FILE__, __LINE__
 
45
#endif
 
46
 
 
47
// Debug precodes
 
48
#define MIMEH_DPEDANTIC ((glb.debug >= _MIMEH_DEBUG_PEDANTIC))
 
49
#define MIMEH_DNORMAL   ((glb.debug >= _MIMEH_DEBUG_NORMAL  ))
 
50
 
 
51
#define DMIMEH if ((glb.debug >= _MIMEH_DEBUG_NORMAL))
 
52
 
 
53
 
 
54
char *MIMEH_defect_description_array[_MIMEH_DEFECT_ARRAY_SIZE];
 
55
 
 
56
 
 
57
 
 
58
struct MIMEH_globals {
 
59
 
 
60
        int doubleCR;
 
61
        int doubleCR_save;
 
62
        char doubleCRname[_MIMEH_STRLEN_MAX +1];
 
63
 
 
64
        char appledouble_filename[_MIMEH_STRLEN_MAX +1];
 
65
 
 
66
        char subject[_MIMEH_STRLEN_MAX +1];
 
67
 
 
68
        char *headerline;
 
69
        char *headerline_original;      // Holds the original header-form without decoding.
 
70
        int save_headers;
 
71
        int save_headers_original;
 
72
        int test_mailbox;
 
73
        int debug;
 
74
        int webform;
 
75
        int doubleCR_count;
 
76
        int header_fix;
 
77
        int verbose;
 
78
        int verbose_contenttype;
 
79
 
 
80
        int header_longsearch; // keep searching until valid headers are found - this is used to filter out qmail bounced emails - breaks RFC's but people are wanting it :-(
 
81
        int longsearch_limit;   // how many segments do we attempt to look ahead...
 
82
 
 
83
        char output_dir[_MIMEH_STRLEN_MAX +1];
 
84
 
 
85
        FILE *header_file;
 
86
 
 
87
        FILE *original_header_file;
 
88
        int original_header_save_to_file;
 
89
};
 
90
 
 
91
static struct MIMEH_globals glb;
 
92
 
 
93
 
 
94
 
 
95
/*-----------------------------------------------------------------\
 
96
  Function Name : MIMEH_version
 
97
  Returns Type  : int
 
98
  ----Parameter List
 
99
  1. void, 
 
100
  ------------------
 
101
  Exit Codes    : 
 
102
  Side Effects  : 
 
103
  --------------------------------------------------------------------
 
104
Comments:
 
105
 
 
106
--------------------------------------------------------------------
 
107
Changes:
 
108
 
 
109
\------------------------------------------------------------------*/
 
110
int MIMEH_version(void)
 
111
{
 
112
        fprintf(stdout,"mimeheaders: %s\n", MIMEH_VERSION);
 
113
 
 
114
        return 0;
 
115
}
 
116
 
 
117
/*-----------------------------------------------------------------\
 
118
  Function Name : MIMEH_init
 
119
  Returns Type  : int
 
120
  ----Parameter List
 
121
  1. void , 
 
122
  ------------------
 
123
  Exit Codes    : 
 
124
  Side Effects  : 
 
125
  --------------------------------------------------------------------
 
126
Comments:
 
127
 
 
128
--------------------------------------------------------------------
 
129
Changes:
 
130
 
 
131
\------------------------------------------------------------------*/
 
132
int MIMEH_init( void )
 
133
{
 
134
 
 
135
        glb.doubleCR = 0;
 
136
        glb.headerline = NULL;
 
137
        glb.headerline_original = NULL;
 
138
        glb.header_file = NULL;
 
139
        glb.original_header_file = NULL;
 
140
        glb.original_header_save_to_file = 0;
 
141
 
 
142
        glb.save_headers = 0;
 
143
        glb.save_headers_original = 0;
 
144
        glb.test_mailbox = 0;
 
145
        glb.debug = 0;
 
146
        glb.webform = 0;
 
147
        glb.doubleCR_count = 0;
 
148
        glb.doubleCR_save = 1;
 
149
        glb.header_fix = 1;
 
150
        glb.verbose = 0;
 
151
        glb.verbose_contenttype = 0;
 
152
        glb.output_dir[0]='\0';
 
153
        glb.doubleCRname[0]='\0';
 
154
        glb.appledouble_filename[0]='\0';
 
155
        glb.header_longsearch=0;
 
156
        glb.longsearch_limit=1;
 
157
 
 
158
        return 0;
 
159
}
 
160
 
 
161
/*-----------------------------------------------------------------\
 
162
  Function Name : MIMEH_get_doubleCR
 
163
  Returns Type  : int
 
164
  ----Parameter List
 
165
  1. void , 
 
166
  ------------------
 
167
  Exit Codes    : 
 
168
  Side Effects  : 
 
169
  --------------------------------------------------------------------
 
170
Comments:
 
171
 
 
172
--------------------------------------------------------------------
 
173
Changes:
 
174
 
 
175
\------------------------------------------------------------------*/
 
176
int MIMEH_get_doubleCR( void )
 
177
{
 
178
        return glb.doubleCR;
 
179
}
 
180
 
 
181
/*-----------------------------------------------------------------\
 
182
  Function Name : MIMEH_set_doubleCR
 
183
  Returns Type  : int
 
184
  ----Parameter List
 
185
  1. int level , 
 
186
  ------------------
 
187
  Exit Codes    : 
 
188
  Side Effects  : 
 
189
  --------------------------------------------------------------------
 
190
Comments:
 
191
 
 
192
--------------------------------------------------------------------
 
193
Changes:
 
194
 
 
195
\------------------------------------------------------------------*/
 
196
int MIMEH_set_doubleCR( int level )
 
197
{
 
198
        glb.doubleCR = level;
 
199
 
 
200
        return glb.doubleCR;
 
201
}
 
202
 
 
203
 
 
204
/*-----------------------------------------------------------------\
 
205
 Function Name  : MIMEH_set_headerfix
 
206
 Returns Type   : int
 
207
        ----Parameter List
 
208
        1. int level , 
 
209
        ------------------
 
210
 Exit Codes     : 
 
211
 Side Effects   : 
 
212
--------------------------------------------------------------------
 
213
 Comments:
 
214
 
 
215
--------------------------------------------------------------------
 
216
 Changes:
 
217
 
 
218
\------------------------------------------------------------------*/
 
219
int MIMEH_set_headerfix( int level )
 
220
{
 
221
        glb.header_fix = level;
 
222
        return glb.header_fix;
 
223
}
 
224
 
 
225
/*-----------------------------------------------------------------\
 
226
  Function Name : MIMEH_set_doubleCR_save
 
227
  Returns Type  : int
 
228
  ----Parameter List
 
229
  1. int level , 
 
230
  ------------------
 
231
  Exit Codes    : 
 
232
  Side Effects  : 
 
233
  --------------------------------------------------------------------
 
234
Comments:
 
235
 
 
236
--------------------------------------------------------------------
 
237
Changes:
 
238
 
 
239
\------------------------------------------------------------------*/
 
240
int MIMEH_set_doubleCR_save( int level )
 
241
{
 
242
        glb.doubleCR_save = level;
 
243
 
 
244
        return glb.doubleCR_save;
 
245
}
 
246
 
 
247
/*-----------------------------------------------------------------\
 
248
  Function Name : MIMEH_get_doubleCR_save
 
249
  Returns Type  : int
 
250
  ----Parameter List
 
251
  1. void , 
 
252
  ------------------
 
253
  Exit Codes    : 
 
254
  Side Effects  : 
 
255
  --------------------------------------------------------------------
 
256
Comments:
 
257
 
 
258
--------------------------------------------------------------------
 
259
Changes:
 
260
 
 
261
\------------------------------------------------------------------*/
 
262
int MIMEH_get_doubleCR_save( void )
 
263
{
 
264
        return glb.doubleCR_save;
 
265
}
 
266
 
 
267
 
 
268
/*-----------------------------------------------------------------\
 
269
  Function Name : *MIMEH_get_doubleCR_name
 
270
  Returns Type  : char
 
271
  ----Parameter List
 
272
  1. void , 
 
273
  ------------------
 
274
  Exit Codes    : 
 
275
  Side Effects  : 
 
276
  --------------------------------------------------------------------
 
277
Comments:
 
278
 
 
279
--------------------------------------------------------------------
 
280
Changes:
 
281
 
 
282
\------------------------------------------------------------------*/
 
283
char *MIMEH_get_doubleCR_name( void )
 
284
{
 
285
        return glb.doubleCRname;
 
286
}
 
287
 
 
288
 
 
289
/*-----------------------------------------------------------------\
 
290
  Function Name : MIMEH_set_debug
 
291
  Returns Type  : int
 
292
  ----Parameter List
 
293
  1. int level , 
 
294
  ------------------
 
295
  Exit Codes    : 
 
296
  Side Effects  : 
 
297
  --------------------------------------------------------------------
 
298
Comments:
 
299
 
 
300
--------------------------------------------------------------------
 
301
Changes:
 
302
 
 
303
\------------------------------------------------------------------*/
 
304
int MIMEH_set_debug( int level )
 
305
{
 
306
        glb.debug = level;
 
307
        return glb.debug;
 
308
}
 
309
 
 
310
/*-----------------------------------------------------------------\
 
311
  Function Name : MIMEH_set_outputdir
 
312
  Returns Type  : int
 
313
  ----Parameter List
 
314
  1. char *dir , 
 
315
  ------------------
 
316
  Exit Codes    : 
 
317
  Side Effects  : 
 
318
  --------------------------------------------------------------------
 
319
Comments:
 
320
 
 
321
--------------------------------------------------------------------
 
322
Changes:
 
323
 
 
324
\------------------------------------------------------------------*/
 
325
int MIMEH_set_outputdir( char *dir )
 
326
{
 
327
        if (dir) snprintf(glb.output_dir,_MIMEH_STRLEN_MAX,"%s",dir);
 
328
        return 0;
 
329
}
 
330
 
 
331
/*-----------------------------------------------------------------\
 
332
  Function Name : MIMEH_set_webform
 
333
  Returns Type  : int
 
334
  ----Parameter List
 
335
  1. int level , 
 
336
  ------------------
 
337
  Exit Codes    : 
 
338
  Side Effects  : 
 
339
  --------------------------------------------------------------------
 
340
Comments:
 
341
 
 
342
--------------------------------------------------------------------
 
343
Changes:
 
344
 
 
345
\------------------------------------------------------------------*/
 
346
int MIMEH_set_webform( int level )
 
347
{
 
348
        glb.webform = level;
 
349
        return glb.webform;
 
350
}
 
351
 
 
352
 
 
353
/*-----------------------------------------------------------------\
 
354
  Function Name : MIMEH_set_mailbox
 
355
  Returns Type  : int
 
356
  ----Parameter List
 
357
  1. int level , 
 
358
  ------------------
 
359
  Exit Codes    : 
 
360
  Side Effects  : 
 
361
  --------------------------------------------------------------------
 
362
Comments:
 
363
 
 
364
--------------------------------------------------------------------
 
365
Changes:
 
366
 
 
367
\------------------------------------------------------------------*/
 
368
int MIMEH_set_mailbox( int level )
 
369
{
 
370
        glb.test_mailbox = level;
 
371
        return level;
 
372
}
 
373
 
 
374
/*-----------------------------------------------------------------\
 
375
  Function Name : MIMEH_set_verbosity
 
376
  Returns Type  : int
 
377
  ----Parameter List
 
378
  1. int level , 
 
379
  ------------------
 
380
  Exit Codes    : 
 
381
  Side Effects  : 
 
382
  --------------------------------------------------------------------
 
383
Comments:
 
384
 
 
385
--------------------------------------------------------------------
 
386
Changes:
 
387
 
 
388
\------------------------------------------------------------------*/
 
389
int MIMEH_set_verbosity( int level )
 
390
{
 
391
        glb.verbose = level;
 
392
        return level;
 
393
}
 
394
 
 
395
/*-----------------------------------------------------------------\
 
396
  Function Name : MIMEH_set_verbosity_contenttype
 
397
  Returns Type  : int
 
398
  ----Parameter List
 
399
  1. int level , 
 
400
  ------------------
 
401
  Exit Codes    : 
 
402
  Side Effects  : 
 
403
  --------------------------------------------------------------------
 
404
Comments:
 
405
 
 
406
--------------------------------------------------------------------
 
407
Changes:
 
408
 
 
409
\------------------------------------------------------------------*/
 
410
int MIMEH_set_verbosity_contenttype( int level )
 
411
{
 
412
        glb.verbose_contenttype = level;
 
413
        return level;
 
414
}
 
415
 
 
416
/*-----------------------------------------------------------------\
 
417
  Function Name : MIMEH_get_verbosity_contenttype
 
418
  Returns Type  : int
 
419
  ----Parameter List
 
420
  1. void , 
 
421
  ------------------
 
422
  Exit Codes    : 
 
423
  Side Effects  : 
 
424
  --------------------------------------------------------------------
 
425
Comments:
 
426
 
 
427
--------------------------------------------------------------------
 
428
Changes:
 
429
 
 
430
\------------------------------------------------------------------*/
 
431
int MIMEH_get_verbosity_contenttype( void )
 
432
{
 
433
        return glb.verbose_contenttype;
 
434
}
 
435
 
 
436
 
 
437
 
 
438
/*------------------------------------------------------------------------
 
439
Procedure:     MIMEH_set_headers_save ID:1
 
440
Purpose:       Sets MIMEH's headers save file (where MIMEH will save the
 
441
headers it reads in from the mailpack)
 
442
Input:
 
443
Output:
 
444
Errors:
 
445
------------------------------------------------------------------------*/
 
446
int MIMEH_set_headers_save( FILE *f )
 
447
{
 
448
        glb.header_file = f;
 
449
        glb.save_headers = 1;
 
450
        return 0;
 
451
}
 
452
 
 
453
 
 
454
/*-----------------------------------------------------------------\
 
455
  Function Name : MIMEH_set_headers_original_save_to_file
 
456
  Returns Type  : int
 
457
  ----Parameter List
 
458
  1. FILE *f , 
 
459
  ------------------
 
460
  Exit Codes    : 
 
461
  Side Effects  : 
 
462
  --------------------------------------------------------------------
 
463
Comments:
 
464
 
 
465
--------------------------------------------------------------------
 
466
Changes:
 
467
 
 
468
\------------------------------------------------------------------*/
 
469
int MIMEH_set_headers_original_save_to_file( FILE *f )
 
470
{
 
471
        if (f == NULL) glb.original_header_save_to_file = 0;
 
472
        else glb.original_header_save_to_file = 1;
 
473
        glb.original_header_file = f;
 
474
 
 
475
        return glb.original_header_save_to_file;
 
476
}
 
477
 
 
478
/*-----------------------------------------------------------------\
 
479
  Function Name : MIMEH_set_headers_nosave
 
480
  Returns Type  : int
 
481
  ----Parameter List
 
482
  1. void , 
 
483
  ------------------
 
484
  Exit Codes    : 
 
485
  Side Effects  : 
 
486
  --------------------------------------------------------------------
 
487
Comments:
 
488
 
 
489
--------------------------------------------------------------------
 
490
Changes:
 
491
 
 
492
\------------------------------------------------------------------*/
 
493
int MIMEH_set_headers_nosave( void )
 
494
{
 
495
        glb.header_file = NULL;
 
496
        glb.save_headers = 0;
 
497
        return 0;
 
498
}
 
499
 
 
500
/*-----------------------------------------------------------------\
 
501
  Function Name : MIMEH_get_headers_save
 
502
  Returns Type  : int
 
503
  ----Parameter List
 
504
  1. void , 
 
505
  ------------------
 
506
  Exit Codes    : 
 
507
  Side Effects  : 
 
508
  --------------------------------------------------------------------
 
509
Comments:
 
510
 
 
511
--------------------------------------------------------------------
 
512
Changes:
 
513
 
 
514
\------------------------------------------------------------------*/
 
515
int MIMEH_get_headers_save( void )
 
516
{
 
517
        return glb.save_headers;
 
518
}
 
519
 
 
520
 
 
521
/*-----------------------------------------------------------------\
 
522
  Function Name : MIMEH_set_headers_save_original
 
523
  Returns Type  : int
 
524
  ----Parameter List
 
525
  1. int level , 
 
526
  ------------------
 
527
  Exit Codes    : 
 
528
  Side Effects  : 
 
529
  --------------------------------------------------------------------
 
530
Comments:
 
531
 
 
532
--------------------------------------------------------------------
 
533
Changes:
 
534
 
 
535
\------------------------------------------------------------------*/
 
536
int MIMEH_set_headers_save_original( int level )
 
537
{
 
538
        glb.save_headers_original = level;
 
539
 
 
540
        return glb.save_headers_original;
 
541
}
 
542
 
 
543
 
 
544
/*-----------------------------------------------------------------\
 
545
  Function Name : MIMEH_get_headers_ptr
 
546
  Returns Type  : int
 
547
  ----Parameter List
 
548
  1. void , 
 
549
  ------------------
 
550
  Exit Codes    : 
 
551
  Side Effects  : 
 
552
  --------------------------------------------------------------------
 
553
Comments:
 
554
 
 
555
--------------------------------------------------------------------
 
556
Changes:
 
557
 
 
558
\------------------------------------------------------------------*/
 
559
char *MIMEH_get_headers_ptr( void )
 
560
{
 
561
        return glb.headerline;
 
562
}
 
563
 
 
564
 
 
565
/*-----------------------------------------------------------------\
 
566
  Function Name : *MIMEH_get_headers_original_ptr
 
567
  Returns Type  : char
 
568
  ----Parameter List
 
569
  1. void , 
 
570
  ------------------
 
571
  Exit Codes    : 
 
572
  Side Effects  : 
 
573
  --------------------------------------------------------------------
 
574
Comments:
 
575
 
 
576
--------------------------------------------------------------------
 
577
Changes:
 
578
 
 
579
\------------------------------------------------------------------*/
 
580
char *MIMEH_get_headers_original_ptr( void )
 
581
{
 
582
        return glb.headerline_original;
 
583
}
 
584
 
 
585
 
 
586
/*-----------------------------------------------------------------\
 
587
  Function Name : MIMEH_set_header_longsearch
 
588
  Returns Type  : int
 
589
  ----Parameter List
 
590
  1. int level , 
 
591
  ------------------
 
592
  Exit Codes    : 
 
593
  Side Effects  : 
 
594
  --------------------------------------------------------------------
 
595
Comments:
 
596
The header long-search is a facility switch that will make the
 
597
header searching to continue on until it either reaches the end of
 
598
the file or it finds valid (??) headers to work on.
 
599
 
 
600
 
 
601
--------------------------------------------------------------------
 
602
Changes:
 
603
 
 
604
\------------------------------------------------------------------*/
 
605
int MIMEH_set_header_longsearch( int level )
 
606
{
 
607
        glb.header_longsearch = level;
 
608
 
 
609
        return glb.header_longsearch;
 
610
}
 
611
 
 
612
/*-----------------------------------------------------------------\
 
613
  Function Name : MIMEH_set_defect
 
614
  Returns Type  : int
 
615
  ----Parameter List
 
616
  1. struct MIMEH_header_info *hinfo, 
 
617
  2.  int defect ,  The defect code to set
 
618
  ------------------
 
619
  Exit Codes    : 
 
620
  Side Effects  : 
 
621
  --------------------------------------------------------------------
 
622
Comments:
 
623
 
 
624
--------------------------------------------------------------------
 
625
Changes:
 
626
 
 
627
\------------------------------------------------------------------*/
 
628
int MIMEH_set_defect( struct MIMEH_header_info *hinfo, int defect )
 
629
{
 
630
        if ((defect >= 0)&&(defect < _MIMEH_DEFECT_ARRAY_SIZE))
 
631
        {
 
632
                hinfo->defects[defect]++;
 
633
                hinfo->header_defect_count++;
 
634
                DMIMEH LOGGER_log("%s:%d:MIMEH_set_defect:DEBUG: Setting defect index '%d' to '%d'",FL, defect, hinfo->defects[defect]); 
 
635
        }
 
636
        return 0;
 
637
}
 
638
 
 
639
/*-----------------------------------------------------------------\
 
640
  Function Name : MIMEH_is_contenttype
 
641
  Returns Type  : int
 
642
  ----Parameter List
 
643
  1. int range_type, 
 
644
  2.  int content_type , 
 
645
  ------------------
 
646
  Exit Codes    : 
 
647
  Side Effects  : 
 
648
  --------------------------------------------------------------------
 
649
Comments:
 
650
 
 
651
--------------------------------------------------------------------
 
652
Changes:
 
653
 
 
654
\------------------------------------------------------------------*/
 
655
int MIMEH_is_contenttype( int range_type, int content_type )
 
656
{
 
657
        int diff;
 
658
 
 
659
        diff = content_type -range_type;
 
660
 
 
661
        if ((diff < _CTYPE_RANGE)&&(diff > 0)) return 1;
 
662
        else return 0;
 
663
}
 
664
 
 
665
 
 
666
/*-----------------------------------------------------------------\
 
667
  Function Name : MIMEH_is_binary
 
668
  Returns Type  : int
 
669
  ----Parameter List
 
670
  1. struct FFGET_FILE *f , 
 
671
  ------------------
 
672
  Exit Codes    : 1 = yes, it's binary, 0 = no.
 
673
  Side Effects  : 
 
674
  --------------------------------------------------------------------
 
675
Comments:
 
676
 
 
677
--------------------------------------------------------------------
 
678
Changes:
 
679
 
 
680
\------------------------------------------------------------------*/
 
681
int MIMEH_is_binary( char *fname )
 
682
{
 
683
        char buffer[1024];
 
684
        int read_count;
 
685
        FILE *f;
 
686
 
 
687
        f = fopen(fname,"r");
 
688
        if (!f) return 1;
 
689
        read_count = fread(buffer, 1, 1024, f);
 
690
        fclose(f);
 
691
 
 
692
        while (read_count)
 
693
        {
 
694
                read_count--;
 
695
                if (buffer[read_count] == 0) return 1;
 
696
        }
 
697
 
 
698
        return 0;
 
699
}
 
700
 
 
701
/*-----------------------------------------------------------------\
 
702
  Function Name : MIMEH_are_headers_RFC822
 
703
  Returns Type  : int
 
704
  ----Parameter List
 
705
  1. char *fname , 
 
706
  ------------------
 
707
  Exit Codes    : 
 
708
  Side Effects  : 
 
709
  --------------------------------------------------------------------
 
710
Comments:
 
711
 
 
712
--------------------------------------------------------------------
 
713
Changes:
 
714
 
 
715
\------------------------------------------------------------------*/
 
716
int MIMEH_are_headers_RFC822( char *headers )
 
717
{
 
718
        char conditions[7][16] = { "received", "from", "subject", "date", "content",  "boundary" };
 
719
        int hitcount = 0;
 
720
        int condition_item;
 
721
        char *lc_headers = NULL;
 
722
 
 
723
        if (headers == NULL)
 
724
        {
 
725
                DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG: Headers are NULL");
 
726
                return 0;
 
727
        }
 
728
 
 
729
        DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG:----\n%s\n----",FL,headers);
 
730
 
 
731
        lc_headers = strdup(headers);
 
732
        if (lc_headers == NULL) return 0;
 
733
 
 
734
        //PLD_strlower((unsigned char *)lc_headers);
 
735
        PLD_strlower(lc_headers);
 
736
 
 
737
        DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG:----(lowercase)----\n%s\n----",FL,lc_headers);
 
738
 
 
739
        for (condition_item=0; condition_item < 6; condition_item++)
 
740
        {
 
741
                char *p;
 
742
 
 
743
                DMIMEH LOGGER_log("%s:%d:MIMEH_are_headers_RFC822:DEBUG: Condition test item[%d] = '%s'",FL,condition_item,conditions[condition_item]);
 
744
                p = strstr(lc_headers, conditions[condition_item]);
 
745
                if (p != NULL)
 
746
                {
 
747
                        if (p > lc_headers)
 
748
                        {
 
749
                                if ((*(p-1) == '\n')||(*(p-1) == '\r'))
 
750
                                hitcount++;
 
751
                        } else if (p == lc_headers) hitcount++;
 
752
                }
 
753
        }
 
754
        
 
755
        if (lc_headers != NULL) free(lc_headers);
 
756
 
 
757
        return hitcount;
 
758
}
 
759
 
 
760
 
 
761
/*-----------------------------------------------------------------\
 
762
  Function Name : MIMEH_save_doubleCR
 
763
  Returns Type  : int
 
764
  ----Parameter List
 
765
  1. FFGET_FILE *f , 
 
766
  ------------------
 
767
  Exit Codes    : 
 
768
  Side Effects  : 
 
769
  --------------------------------------------------------------------
 
770
Comments:
 
771
 
 
772
--------------------------------------------------------------------
 
773
Changes:
 
774
 
 
775
\------------------------------------------------------------------*/
 
776
int MIMEH_save_doubleCR( FFGET_FILE *f )
 
777
{
 
778
        //char c;
 
779
        int c;
 
780
        FILE *fo;
 
781
        struct stat st;
 
782
 
 
783
 
 
784
        // Determine a file name we can use.
 
785
 
 
786
        do {
 
787
                glb.doubleCR_count++;
 
788
                snprintf(glb.doubleCRname,_MIMEH_STRLEN_MAX,"%s/doubleCR.%d",glb.output_dir,glb.doubleCR_count);
 
789
        }
 
790
        while (stat(glb.doubleCRname, &st) == 0);
 
791
 
 
792
 
 
793
        fo = fopen(glb.doubleCRname,"w");
 
794
        if (!fo)
 
795
        {
 
796
                LOGGER_log("%s:%d:MIMEH_save_doubleCR:ERROR: unable to open '%s' to write (%s)", FL,glb.doubleCRname,strerror(errno));
 
797
                return -1;
 
798
        }
 
799
 
 
800
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_save_doubleCR:DEBUG: Saving DoubleCR header: %s\n", FL,glb.doubleCRname);
 
801
 
 
802
        while (1)
 
803
        {
 
804
                c = FFGET_fgetc(f);
 
805
                fprintf(fo,"%c",c);
 
806
 
 
807
                if ((c == EOF)||(c == '\n'))
 
808
                {
 
809
                        break;
 
810
                }
 
811
        }
 
812
 
 
813
        fclose(fo);
 
814
 
 
815
        return 0;
 
816
}
 
817
 
 
818
 
 
819
/*-----------------------------------------------------------------\
 
820
  Function Name : *
 
821
  Returns Type  : char
 
822
  ----Parameter List
 
823
  1. MIMEH_absorb_whitespace( char *p , 
 
824
  ------------------
 
825
  Exit Codes    : 
 
826
  Side Effects  : 
 
827
  --------------------------------------------------------------------
 
828
Comments:
 
829
 
 
830
--------------------------------------------------------------------
 
831
Changes:
 
832
 
 
833
\------------------------------------------------------------------*/
 
834
char * MIMEH_absorb_whitespace( char *p )
 
835
{
 
836
        if (p)
 
837
        {
 
838
                while ((*p != '\0')&&((*p == ' ')||(*p == '\t'))) p++;
 
839
        }
 
840
 
 
841
        return p;
 
842
}
 
843
 
 
844
/*-----------------------------------------------------------------\
 
845
  Function Name : MIMEH_strip_comments
 
846
  Returns Type  : int
 
847
  ----Parameter List
 
848
  1. char *input , 
 
849
  ------------------
 
850
  Exit Codes    : 
 
851
  Side Effects  : 
 
852
  --------------------------------------------------------------------
 
853
Comments:
 
854
Removes comments from RFC[2]822 headers
 
855
 
 
856
--------------------------------------------------------------------
 
857
Changes:
 
858
 
 
859
\------------------------------------------------------------------*/
 
860
int MIMEH_strip_comments( char *input )
 
861
{
 
862
        char *p,*p_org;
 
863
        int in_quote=0;
 
864
 
 
865
        if (input == NULL) return 0;
 
866
 
 
867
        p = p_org = input;
 
868
 
 
869
        do {
 
870
                char *q = NULL;
 
871
 
 
872
                // Locate (if any) the first occurance of the (
 
873
                while ((p_org != NULL)&&((*p_org != '(')||(in_quote==1)))
 
874
                {
 
875
                        switch (*p_org) {
 
876
                                case '"':
 
877
                                        in_quote ^= 1;
 
878
                                        break;
 
879
                                case '\n':
 
880
                                case '\r':
 
881
                                        in_quote = 0;
 
882
                                        break;
 
883
                                case '\0':
 
884
                                        p_org = NULL;
 
885
                                        break;
 
886
                        }
 
887
 
 
888
                        if (p_org) p_org++;
 
889
                }
 
890
 
 
891
                p = p_org;
 
892
 
 
893
 
 
894
                if ((p != NULL)&&(in_quote == 0))
 
895
                {
 
896
                        int stop_searching = 0;
 
897
 
 
898
                        DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: Located open ( at %s",FL,p);
 
899
                        // If we did locate an opening parenthesis, look for the closing one
 
900
                        //              NOTE - we cannot have a breaking \n or \r inbetween
 
901
                        //              q = strpbrk(p, ")\n\r");
 
902
                        q = p;
 
903
                        while ( (q != NULL) && (stop_searching == 0) )
 
904
                        {
 
905
                                switch (*q) {
 
906
                                        case '\0':
 
907
                                                stop_searching = 1;
 
908
                                                q = NULL;
 
909
                                                break;
 
910
 
 
911
                                        case '\n':
 
912
                                        case '\r':
 
913
                                                stop_searching = 1;
 
914
                                                in_quote = 0;
 
915
                                                break;
 
916
 
 
917
                                        case '"':
 
918
                                                in_quote ^= 1;
 
919
                                                break;
 
920
 
 
921
                                        case ')':
 
922
                                                DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: Located closing ) at %s",FL,q);
 
923
                                                if (in_quote == 0) stop_searching = 1;
 
924
                                                break;
 
925
                                }
 
926
                                if ((q != NULL)&&(stop_searching == 0)) q++;
 
927
                        }
 
928
 
 
929
                        // If we've got both opening and closing, then we need to remove
 
930
                        //              the contents of the comment, including the parenthesis
 
931
                        if (q != NULL)
 
932
                        {
 
933
                                if (*q != ')')
 
934
                                {
 
935
                                        // if we found a \n or \r between the two (), then jump out
 
936
                                        // and move p to the next position.
 
937
                                        p_org++;
 
938
                                        continue;
 
939
 
 
940
                                } else {
 
941
                                        // Move q to the first char after the closing parenthesis
 
942
                                        q++;
 
943
 
 
944
                                        DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: located closing ) at %s ",FL, q);
 
945
                                        // While there's more chars in string, copy them to where 
 
946
                                        //              the opening parenthesis is
 
947
                                        while (*q != '\0')
 
948
                                        {
 
949
                                                *p = *q;        
 
950
                                                p++;
 
951
                                                q++;
 
952
                                        } // While q != '\0'
 
953
                                        DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: char copy done",FL);
 
954
 
 
955
                                        // Terminate the string
 
956
                                        *p = '\0';
 
957
                                } // if q !=/= ')'
 
958
 
 
959
                        } else break; // if q == NULL
 
960
 
 
961
                } // if p == NULL
 
962
 
 
963
        } while ((p != NULL)&&(p_org != NULL)); // do-while more comments to remove
 
964
 
 
965
        DMIMEH LOGGER_log("%s:%d:MIMEH_strip_comments:DEBUG: Final string = '%s'",FL,input);
 
966
 
 
967
        return 0;
 
968
}
 
969
 
 
970
 
 
971
/*-----------------------------------------------------------------\
 
972
 Function Name  : MIMEH_fix_header_mistakes
 
973
 Returns Type   : int
 
974
        ----Parameter List
 
975
        1. char *data , 
 
976
        ------------------
 
977
 Exit Codes     : 
 
978
 Side Effects   : 
 
979
--------------------------------------------------------------------
 
980
 Comments:
 
981
 
 
982
        Some headers are broken in their wrapping, ie, they fail to
 
983
        put a leading space at the start of the next wrapped data line; ie
 
984
 
 
985
Content-Transfer-Encoding: quoted-printable
 
986
Content-Disposition: attachment;
 
987
filename="yxnjjhyk.xml"
 
988
        
 
989
        Which causes normal header processing to not locate the filename.
 
990
 
 
991
        This function will see if there are any lines with a trailing ; that
 
992
        do not have a leading space on the next line and subsequently replace
 
993
        the \r\n chars after the ; with blanks, effectively pulling the line up
 
994
 
 
995
--------------------------------------------------------------------
 
996
 Changes:
 
997
 
 
998
\------------------------------------------------------------------*/
 
999
int MIMEH_fix_header_mistakes( char *data )
 
1000
{
 
1001
        int result = 0;
 
1002
        char *p;
 
1003
 
 
1004
        DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Checking and fixing headers in '%s'",FL,data);
 
1005
 
 
1006
        if (glb.header_fix == 0) return result;
 
1007
 
 
1008
        p = data;
 
1009
        while (p) {
 
1010
                int nonblank_detected = 0;
 
1011
                char *q;
 
1012
 
 
1013
                p = strchr(p, ';');
 
1014
                if (p == NULL) break;
 
1015
 
 
1016
 
 
1017
                q = p+1;
 
1018
 
 
1019
                DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Located ';' at offset %d '%20s",FL, p -data, p);
 
1020
 
 
1021
                if ((*q == '\n')||(*q == '\r')) {
 
1022
                        nonblank_detected = 0;
 
1023
                } else {
 
1024
                        /** If the ; isn't immediately followed by a \n or \r, then search till
 
1025
                          ** the end of the line to see if all the chars are blank **/
 
1026
 
 
1027
                        while ((*q != '\0')||(*q != '\r')||(*q != '\n')) {
 
1028
                                switch (*q) {
 
1029
                                        case '\t':
 
1030
                                        case '\n':
 
1031
                                        case '\r':
 
1032
                                        case ' ':
 
1033
                                                nonblank_detected = 0;
 
1034
                                                break;
 
1035
                                        default:
 
1036
                                                nonblank_detected = 1;
 
1037
                                } /*switch*/
 
1038
 
 
1039
                                if (nonblank_detected == 1) break;
 
1040
 
 
1041
                                q++;
 
1042
                        } /** while looking for the end of the line **/
 
1043
                } /** ELSE - if *q wasn't a line break char **/
 
1044
 
 
1045
                if (nonblank_detected == 1) {
 
1046
                        DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Line was normal/safe, continue...",FL);
 
1047
                        p++;
 
1048
                        continue;
 
1049
                } /** if nonblank_detected == 1 **/
 
1050
 
 
1051
                /** if we had nothing but blanks till the end of the 
 
1052
                  ** line, then we need to pull up the next line **/
 
1053
                if (*q != '\0') {
 
1054
                        DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Line needs fixing",FL);
 
1055
                        *q = ' ';
 
1056
                        q++;
 
1057
                        if ((*q == '\n')||(*q == '\r')) *q = ' ';
 
1058
                        DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Line fixed",FL);
 
1059
                        p = q;
 
1060
                } /** If q wasn't the end of data **/
 
1061
 
 
1062
        } /** while looking for more ';' chars **/
 
1063
 
 
1064
        DMIMEH LOGGER_log("%s:%d:MIMEH_fix_header_mistakes:DEBUG: Done",FL);
 
1065
                
 
1066
        return result;
 
1067
}
 
1068
 
 
1069
/*------------------------------------------------------------------------
 
1070
Procedure:     MIMEH_read_headers ID:1
 
1071
Purpose:       Reads from the stream F until it detects a From line, or a blank line
 
1072
(end of headers)
 
1073
Input:
 
1074
Output:
 
1075
Errors:
 
1076
------------------------------------------------------------------------*/
 
1077
int MIMEH_read_headers( struct MIMEH_header_info *hinfo, FFGET_FILE *f )
 
1078
{
 
1079
        char buffer[_MIMEH_STRLEN_MAX+1];
 
1080
        int totalsize=0;
 
1081
        int linesize=0;
 
1082
        int totalsize_original=0;
 
1083
        int result = 0;
 
1084
        int firstline = 1;
 
1085
        int search_count=0;
 
1086
        char *tmp;
 
1087
        char *tmp_original;
 
1088
        char *fget_result = NULL;
 
1089
        char *headerline_end;
 
1090
        char *p;
 
1091
        char *linestart;
 
1092
        char *lineend;
 
1093
 
 
1094
        int is_RFC822_headers=0;        // 20040208-1335:PLD: Added to give an indication if the headers are RFC822 like; used in conjunction with the header_longsearch for pulling apart qmail bouncebacks.
 
1095
 
 
1096
        /**
 
1097
                        Lets start the ugly big fat DO loop here so that we can, if needed
 
1098
                        search until we find headers which are actually valid.  Personally
 
1099
                        I hate this - but people want it in order to detect malformed 
 
1100
                        (deliberate or otherwise) emails.  It'd be nice if for once in the
 
1101
                        software world someone actually enforced standards rather than trying
 
1102
                        to be overly intelligent about interpreting data.  
 
1103
        **/
 
1104
 
 
1105
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: File position = %ld [0x%0X]"
 
1106
                        ,FL
 
1107
                        ,FFGET_ftell(f)
 
1108
                        ,FFGET_ftell(f)
 
1109
                        );
 
1110
        
 
1111
        do {
 
1112
 
 
1113
                search_count++;
 
1114
                glb.headerline = NULL;
 
1115
                glb.headerline_original = NULL;
 
1116
                tmp_original = NULL;
 
1117
 
 
1118
 
 
1119
                while ((fget_result=FFGET_fgets(buffer,_MIMEH_STRLEN_MAX, f)))
 
1120
                {
 
1121
 
 
1122
                        linestart = buffer;
 
1123
                        linesize = strlen(linestart);
 
1124
                        lineend = linestart +linesize;
 
1125
 
 
1126
                        if (strstr(linestart,"\r\n")) hinfo->crlf_count++;
 
1127
                        else if (strstr(linestart,"\r\r")) hinfo->crcr_count++;
 
1128
                        else if (strchr(linestart,'\n')) hinfo->lf_count++;
 
1129
 
 
1130
                        if (MIMEH_DNORMAL)LOGGER_log("%s:%d:MIMEH_read_headers: Data In=[sz=%d:tb=%d:mem=%p]'%s'",FL, linesize, f->trueblank, glb.headerline, buffer);
 
1131
 
 
1132
                        // If we are being told to copy the input data to an output file
 
1133
                        //              then do so here (this is for the originals)
 
1134
                        if ((glb.original_header_save_to_file > 0)&&(glb.original_header_file != NULL))
 
1135
                        {
 
1136
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: saving to file...",FL);
 
1137
                                fprintf(glb.original_header_file,"%s",linestart);
 
1138
                        }
 
1139
 
 
1140
                        // if we are being told to keep a copy of the original data
 
1141
                        //      as it comes in from ffget, then do the storage here
 
1142
                        if (glb.save_headers_original > 0)
 
1143
                        {
 
1144
                                if (MIMEH_DNORMAL) LOGGER_log("MIMEH_read_headers:DEBUG:Data-In:[%d:%d] '%s'", strlen(linestart), linesize, linestart);
 
1145
                                tmp_original = realloc(glb.headerline_original, totalsize_original+linesize+1);
 
1146
                                if (tmp_original == NULL)
 
1147
                                {
 
1148
                                        LOGGER_log("%s:%d:MIMEH_read_headers:ERROR: Cannot allocate %d bytes to contain new headers_original ", FL,totalsize_original +linesize +1);
 
1149
                                        if (glb.headerline_original != NULL) free(glb.headerline_original);
 
1150
                                        glb.headerline_original = NULL;
 
1151
                                        return -1;
 
1152
                                }
 
1153
 
 
1154
                                if (glb.headerline_original == NULL)
 
1155
                                {
 
1156
                                        glb.headerline_original = tmp_original;
 
1157
                                        totalsize_original = linesize +1;
 
1158
                                        PLD_strncpy( glb.headerline_original, linestart, (linesize+1));
 
1159
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: '%s'", FL, glb.headerline_original);
 
1160
                                } else {
 
1161
                                        glb.headerline_original = tmp_original;
 
1162
                                        PLD_strncpy( (glb.headerline_original +totalsize_original -1), linestart, (linesize +1));
 
1163
                                        totalsize_original += linesize;
 
1164
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: HO =  '%s'", FL, glb.headerline_original);
 
1165
                                }
 
1166
                                //LOGGER_log("DEBUG:linesize=%d data='%s'",linesize, linestart);
 
1167
                        }
 
1168
 
 
1169
 
 
1170
                        /** Normal processing of the headers now starts. **/
 
1171
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: realloc'ing dataspace",FL); 
 
1172
                        tmp = realloc(glb.headerline, totalsize+linesize+1);
 
1173
                        if (tmp == NULL)
 
1174
                        {
 
1175
                                LOGGER_log("%s:%d:MIMEH_read_headers:ERROR: Cannot allocate %d bytes to contain new headers ", FL,totalsize +linesize +1);
 
1176
                                if (glb.headerline != NULL) free(glb.headerline);
 
1177
                                glb.headerline = NULL;
 
1178
                                return -1;
 
1179
                        }
 
1180
 
 
1181
                        if (glb.headerline == NULL)
 
1182
                        {
 
1183
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Initial appending of head to dataspace headerline = NULL  realloc block = %p linestart = %p linesize = %d",FL, tmp, linestart, linesize); 
 
1184
                                glb.headerline = tmp;
 
1185
                                totalsize = linesize;
 
1186
                                PLD_strncpy(glb.headerline, linestart, (linesize +1));
 
1187
                                headerline_end = glb.headerline +totalsize;
 
1188
                        } // If the global headerline is currently NULL
 
1189
                        else
 
1190
                        {
 
1191
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Appending of new data to existing header  existing-headerline = %p  new realloc block = %p linestart = %p linesize = %d",FL, glb.headerline, tmp, linestart, linesize); 
 
1192
 
 
1193
                                // Perform header unfolding by removing any CRLF's
 
1194
                                //      of the last line if the first characters of the
 
1195
                                //      newline are blank/space
 
1196
 
 
1197
                                glb.headerline = tmp;
 
1198
 
 
1199
                                if ((linestart < lineend)&&((*linestart == '\t')||(*linestart == ' ')))
 
1200
                                {
 
1201
 
 
1202
                                        // Here we start at the last character of the previous line
 
1203
                                        // and check to see if it's a 'space' type charcter, if it is
 
1204
                                        // we will then reduce the total size of the headers thus far and
 
1205
                                        // move the pointer where we're going to append this new line back
 
1206
                                        //      one more character - Ultimately what we wish to achieve is that
 
1207
                                        //      the new line will tacked on [sans leading spaces] to the end of
 
1208
                                        //      the previous line.
 
1209
                                        //
 
1210
                                        // 'p' holds the location at the -end- of the current headers where
 
1211
                                        //              we are going to append the newly read line
 
1212
 
 
1213
 
 
1214
                                        p = glb.headerline +totalsize -1;
 
1215
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: unwrapping headers headers=%p, p = %p",FL,glb.headerline, p);
 
1216
                                        while ((p >= glb.headerline)&&(( *p == '\n' )||( *p == '\r' )))
 
1217
                                        {
 
1218
                                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Removing trailing space p=[%p]%c",FL, p, *p);
 
1219
                                                *p = '\0';
 
1220
                                                p--;
 
1221
                                                totalsize--;
 
1222
                                        }
 
1223
 
 
1224
 
 
1225
                                        p = glb.headerline +totalsize -1;
 
1226
 
 
1227
                                } 
 
1228
 
 
1229
 
 
1230
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Memcopying line, source = %p, dest = %p, size = %d", FL, linestart, glb.headerline +totalsize, linesize);
 
1231
                                memcpy((glb.headerline +totalsize), linestart, (linesize));
 
1232
                                totalsize += linesize;
 
1233
                                *(glb.headerline +totalsize) = '\0';
 
1234
 
 
1235
 
 
1236
                        }       // If the glb.headerline already is allocated and we're appending to it.
 
1237
 
 
1238
 
 
1239
                        if (f->trueblank)
 
1240
                        {
 
1241
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Trueblank line detected in header reading",FL);
 
1242
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Headers /before/ decoding\n-------\n%s\n-------------------",FL, glb.headerline);
 
1243
 
 
1244
                                MIMEH_fix_header_mistakes( glb.headerline );
 
1245
                                MDECODE_decode_ISO( glb.headerline, totalsize  );
 
1246
 
 
1247
                                if ((glb.save_headers)&&(glb.headerline))
 
1248
                                {
 
1249
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Saving header line.",FL);
 
1250
                                        fprintf(glb.header_file,"%s",glb.headerline);
 
1251
                                }
 
1252
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Final Headers\n------------------\n%s---------------", FL,glb.headerline);
 
1253
                                //result = 1;
 
1254
                                //result = 0;
 
1255
                                break;
 
1256
                        } // If the last line was in fact a true blank line
 
1257
 
 
1258
 
 
1259
                        // If there was a doubleCR at the end of the line,
 
1260
                        //      then we need to save the next set of data until there
 
1261
                        //      is a \n
 
1262
 
 
1263
                        if (FFGET_doubleCR)
 
1264
                        {
 
1265
                                if (glb.doubleCR_save != 0)
 
1266
                                {
 
1267
                                        MIMEH_save_doubleCR(f);
 
1268
                                        glb.doubleCR = 1;
 
1269
                                }
 
1270
                                FFGET_doubleCR = 0;
 
1271
                                FFGET_SDL_MODE = 0;
 
1272
                        } // FFGET_doubleCR test
 
1273
 
 
1274
                        firstline = 0;
 
1275
                } // While reading more headers from the source file.
 
1276
 
 
1277
 
 
1278
                // If FFGET ran out of data whilst processing the headers, then acknowledge this
 
1279
                // by returning a -1.
 
1280
                //
 
1281
                // NOTE - This does not mean we do not have any data!
 
1282
                //  it just means that our input ran out.
 
1283
 
 
1284
                if (!fget_result)
 
1285
                {
 
1286
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:ERROR: FFGET module ran out of input while reading headers",FL);
 
1287
                        /** If we're meant to be saving the headers, we better do that now, even though we couldn't
 
1288
                          ** read everything we wanted to **/
 
1289
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: save_headers=%d totalsize=%d headerline=%s", FL, glb.save_headers, totalsize, glb.headerline);
 
1290
 
 
1291
                                if ((glb.save_headers)&&(glb.headerline))
 
1292
                                {
 
1293
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_read_headers:DEBUG: Saving header line.",FL);
 
1294
                                        MIMEH_fix_header_mistakes( glb.headerline );
 
1295
                                        MDECODE_decode_ISO( glb.headerline, totalsize  );
 
1296
                                        fprintf(glb.header_file,"%s",glb.headerline);
 
1297
                                }
 
1298
 
 
1299
                        result = -1;
 
1300
                } else {
 
1301
 
 
1302
                        if (glb.header_longsearch > 0) {
 
1303
                                /** Test the headers for RFC compliance... **/
 
1304
                                is_RFC822_headers =  MIMEH_are_headers_RFC822(glb.headerline);
 
1305
                                if (is_RFC822_headers == 0)
 
1306
                                {
 
1307
                                        /** If not RFC822 headers, then clean up everything we allocated in here **/
 
1308
                                        DMIMEH LOGGER_log("%s:%d:MIME_read_headers:DEBUG: No RFC822 headers detected, cleanup.");
 
1309
                                        MIMEH_headers_cleanup();
 
1310
                                }
 
1311
                        }
 
1312
                }
 
1313
        } while ((is_RFC822_headers==0)&&(glb.header_longsearch>0)&&(result==0)&&(search_count<glb.longsearch_limit));
 
1314
 
 
1315
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_read_headers:DEBUG: Finished.",FL);
 
1316
        return result;
 
1317
}
 
1318
 
 
1319
 
 
1320
 
 
1321
/*------------------------------------------------------------------------
 
1322
Procedure:     MIMEH_display_info ID:1
 
1323
Purpose:       DEBUGGING - Displays the values of the hinfo structure to
 
1324
stderr
 
1325
Input:
 
1326
Output:
 
1327
Errors:
 
1328
------------------------------------------------------------------------*/
 
1329
int MIMEH_display_info( struct MIMEH_header_info *hinfo )
 
1330
{
 
1331
        if (hinfo)
 
1332
        {
 
1333
                LOGGER_log("%s:%d:MIMEH_display_info:\
 
1334
                                Content Type = %d\n\
 
1335
                                Boundary = %s\n\
 
1336
                                Filename = %s\n\
 
1337
                                name = %s\n\
 
1338
                                Encoding = %d\n\
 
1339
                                Disposit = %d\n\
 
1340
                                "\
 
1341
                                ,FL\
 
1342
                                ,hinfo->content_type\
 
1343
                                ,hinfo->boundary\
 
1344
                                ,hinfo->filename\
 
1345
                                ,hinfo->name\
 
1346
                                ,hinfo->content_transfer_encoding\
 
1347
                                ,hinfo->content_disposition);
 
1348
                fflush(stdout);
 
1349
        }
 
1350
        return 0; 
 
1351
 
 
1352
}
 
1353
 
 
1354
/*-----------------------------------------------------------------\
 
1355
  Function Name : MIMEH_decode_multivalue_language_string
 
1356
  Returns Type  : int
 
1357
  ----Parameter List
 
1358
  1. char *input , 
 
1359
  ------------------
 
1360
  Exit Codes    : 
 
1361
  Side Effects  : 
 
1362
  --------------------------------------------------------------------
 
1363
Comments:
 
1364
 
 
1365
--------------------------------------------------------------------
 
1366
Changes:
 
1367
 
 
1368
\------------------------------------------------------------------*/
 
1369
int MIMEH_decode_multivalue_language_string( char *input )
 
1370
{
 
1371
        int sq_count = 0;
 
1372
        int language_set = 0;
 
1373
        char *q = input;
 
1374
 
 
1375
        DMIMEH LOGGER_log("%s:%d:MIMEH_decode_multivalue_language_string:DEBUG: Decoding '%s'",FL,input);
 
1376
        // Count the single-quotes
 
1377
        while ((*q != '\0')&&(sq_count != 2)) if (*q++ == '\'') sq_count++;
 
1378
        if (sq_count < 2)
 
1379
        {
 
1380
                //              LOGGER_log("%s:%d:MIMEH_decode_multivalue_language_string:WARNING: Insufficient single quotes for valid language-charset string",FL);
 
1381
                q = input;
 
1382
        } else {
 
1383
                language_set = 1;
 
1384
        }
 
1385
 
 
1386
        // q will be pointing at the 2nd single-quote, which is the end of
 
1387
        // the language encoding set, so we just jump over that and start
 
1388
        // reading off the data and decoding it.
 
1389
        MDECODE_decode_multipart( q );
 
1390
 
 
1391
        // If the language was set, we need to move down our decoded data to the 
 
1392
        //              start of the input buffer
 
1393
        if (language_set == 1)
 
1394
        {
 
1395
                while (*q != '\0') { *input = *q; input++; q++; }
 
1396
                *input = '\0';
 
1397
        }
 
1398
 
 
1399
        DMIMEH LOGGER_log("%s:%d:MIMEH_decode_multivalue_language_string:DEBUG: Output = '%s'",FL,q);
 
1400
 
 
1401
 
 
1402
        return 0;
 
1403
 
 
1404
}
 
1405
 
 
1406
/*-----------------------------------------------------------------\
 
1407
  Function Name : MIMEH_recompose_multivalue
 
1408
  Returns Type  : int
 
1409
  ----Parameter List
 
1410
  1. struct MIMEH_header_info *hinfo,  Global header information, can be NULL
 
1411
  2.  char *header_name_prefix, Prefix we're looking for (ie, filename)
 
1412
  3.  char *header_value, String which the prefix should exist in 
 
1413
  4.  char *buffer, Output buffer
 
1414
  5.  size_t buffer_size , Output buffer size
 
1415
  ------------------
 
1416
  Exit Codes    : 
 
1417
  Side Effects  : 
 
1418
  --------------------------------------------------------------------
 
1419
Comments:
 
1420
Multivalue strings are ones which appear like:
 
1421
 
 
1422
filename*0*=us-ascii'en-us'attachment%2E%65
 
1423
filename*1*="xe"
 
1424
 
 
1425
which should duly be recoded as:
 
1426
 
 
1427
filename=attachment.exe
 
1428
 
 
1429
Another example: (extracted from the RFC2231 document)
 
1430
 
 
1431
Content-Type: application/x-stuff
 
1432
title*0*=us-ascii'en'This%20is%20even%20more%20
 
1433
title*1*=%2A%2A%2Afun%2A%2A%2A%20
 
1434
title*2="isn't it!"
 
1435
 
 
1436
--------------------------------------------------------------------
 
1437
Changes:
 
1438
 
 
1439
\------------------------------------------------------------------*/
 
1440
int MIMEH_recompose_multivalue( struct MIMEH_header_info *hinfo, char *header_name_prefix, char *header_value, char *buffer, size_t buffer_size, char **data_end_point )
 
1441
{
 
1442
        int result = 0;
 
1443
        char *start_position = header_value;
 
1444
 
 
1445
 
 
1446
        DMIMEH LOGGER_log("%s:%d:MIMEH_recompose_multivalue:DEBUG: seeking for %s in %s and appending to '%s'. Buffer size=%d", FL, header_name_prefix, header_value,buffer, buffer_size );
 
1447
 
 
1448
 
 
1449
        // Locate the first part of the multipart string
 
1450
        start_position = strstr(header_value, header_name_prefix);
 
1451
        if (start_position != NULL)
 
1452
        {
 
1453
                char *q;
 
1454
                char *buffer_start;
 
1455
 
 
1456
                // Setup our buffer insertion point for what ever new data we extract
 
1457
                buffer_start = buffer +strlen(buffer);
 
1458
                buffer_size -= strlen(buffer);
 
1459
 
 
1460
                q = start_position;
 
1461
 
 
1462
                // If the string we're looking for exists, then continue...
 
1463
                do {
 
1464
                        char *p;
 
1465
                        char *end_point;
 
1466
                        char end_point_char='\0';
 
1467
                        int decode_data=0;
 
1468
                        int q_len;
 
1469
 
 
1470
                        p = strstr(q, header_name_prefix);
 
1471
                        if (p == NULL) break;
 
1472
 
 
1473
                        DMIMEH LOGGER_log("%s:%d:MIMEH_recompose_multivalue:DEBUG: prefix = %s", FL, p);
 
1474
 
 
1475
                        q = strchr(p,'=');
 
1476
                        if (q == NULL) break;
 
1477
 
 
1478
                        // Test to see if we have to look for a language encoding specification *sigh*
 
1479
                        if (*(q-1) == '*')
 
1480
                        {
 
1481
                                decode_data=1;
 
1482
                        }
 
1483
 
 
1484
                        // Move the pointer past the '=' separator
 
1485
                        q++;
 
1486
 
 
1487
                        DMIMEH LOGGER_log("%s:%d:MIMEH_recompose_multivalue:DEBUG: data = %s", FL, q);
 
1488
 
 
1489
                        // Find where this multipart string ends
 
1490
                        end_point = strpbrk(q, ";\t\n\r ");
 
1491
                        if (end_point != NULL)
 
1492
                        {
 
1493
                                *end_point = '\0';
 
1494
                                end_point_char = *end_point;
 
1495
                                *data_end_point = end_point; // Set this so we know where to start decoding the next time we call this fn
 
1496
                        } else {
 
1497
                                char *ep;
 
1498
 
 
1499
                                // If strpbrk comes up with nothing, then we set the data_end_point to the end of the string
 
1500
                                ep = q;
 
1501
                                while (*ep != '\0') ep++;
 
1502
                                *data_end_point = ep;
 
1503
                        }
 
1504
 
 
1505
                        // Trim off quotes.
 
1506
                        if (*q == '"') 
 
1507
                        { 
 
1508
                                int bl;
 
1509
 
 
1510
                                //      LOGGER_log("%s:%d:DEBUG: Trimming '%s'", FL, q);
 
1511
                                q++;
 
1512
                                bl = strlen(q);
 
1513
                                if (*(q +bl -1) == '"') *(q +bl -1) = '\0';
 
1514
                                //LOGGER_log("%s:%d:DEBUG: Trim done, '%s'", FL, q);
 
1515
                        }
 
1516
 
 
1517
                        if (decode_data == 1)
 
1518
                        {
 
1519
                                MIMEH_decode_multivalue_language_string(q);
 
1520
                        }
 
1521
 
 
1522
                        DMIMEH LOGGER_log("%s:%d:MIMEH_recompose_multivalue:DEBUG: segment value = '%s', appending to '%s'", FL, q, buffer);
 
1523
                        snprintf(buffer_start,buffer_size,"%s",q);
 
1524
                        q_len = strlen(q);
 
1525
                        buffer_size -= q_len;
 
1526
                        buffer_start += q_len;
 
1527
                        DMIMEH LOGGER_log("%s:%d:MIMEH_recompose_multivalue:DEBUG: Buffer[remaining=%d]= '%s'", FL, buffer_size,buffer);
 
1528
 
 
1529
                        if (end_point != NULL)
 
1530
                        {
 
1531
                                *end_point = end_point_char; 
 
1532
                                q = end_point +1; 
 
1533
                        }
 
1534
                        else q = NULL;
 
1535
 
 
1536
                } while ((q != NULL)&&(buffer_size > 0));
 
1537
 
 
1538
        }
 
1539
 
 
1540
        DMIMEH LOGGER_log("%s:%d:MIMEH_recompose_multivalue:DEBUG: End point set to: [%d] '%s'",FL, (*data_end_point -header_value), *data_end_point);
 
1541
        return result;
 
1542
}
 
1543
 
 
1544
 
 
1545
/*-----------------------------------------------------------------\
 
1546
  Function Name : MIMEH_parse_header_parameter
 
1547
  Returns Type  : int
 
1548
  ----Parameter List
 
1549
  1. char *data, 
 
1550
  2.  char *searchstr, 
 
1551
  3.  char *output_value, 
 
1552
  4.  int output_value_size , 
 
1553
  5.  char *data_end_point, used to keep track of the last point of
 
1554
  successful data decoding is.
 
1555
  ------------------
 
1556
  Exit Codes    : 
 
1557
  0 = Success, found the required parameter
 
1558
  1 = No luck, didn't find the required parameter
 
1559
 
 
1560
  Side Effects  : 
 
1561
  --------------------------------------------------------------------
 
1562
Comments:
 
1563
 
 
1564
--------------------------------------------------------------------
 
1565
Changes:
 
1566
11-Aug-2004: Added new variable, data_end_point.  This variable
 
1567
was required because without it, there was no way of telling
 
1568
where to continue on the search for more valid data, this is
 
1569
due to having to no longer rely on fixed atom separators like
 
1570
: and ; in the MIME text (thankyou MUA's which incorrectly
 
1571
interpreted the RFC's *sigh*)
 
1572
 
 
1573
\------------------------------------------------------------------*/
 
1574
int MIMEH_parse_header_parameter( struct MIMEH_header_info *hinfo,  char *data, char *searchstr, char *output_value, int output_value_size, char **data_end_point  )
 
1575
{
 
1576
        int return_value = 0;
 
1577
        char *p;
 
1578
        char *hl;
 
1579
 
 
1580
        // Set the data end point to be the beginning of the data, as we
 
1581
        //              have not yet searched through any of the header data
 
1582
        *data_end_point = data;
 
1583
 
 
1584
        // Duplicate and convert to lowercase the header data
 
1585
        //              that we have been provided with.
 
1586
        hl = strdup(data);
 
1587
        //PLD_strlower((unsigned char *)hl);
 
1588
        PLD_strlower(hl);
 
1589
 
 
1590
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Seeking '%s' in '%s'", FL, searchstr, hl);
 
1591
 
 
1592
        // Look for the search string we're after (ie, filename, name, location etc)
 
1593
        if (strncmp(hl,searchstr,strlen(searchstr))==0) p = hl; else p = NULL;
 
1594
//      p = strstr (hl, searchstr); //TESTING 
 
1595
        if (p != NULL)
 
1596
        {
 
1597
                char *string = NULL;
 
1598
 
 
1599
                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: found %s in %s", FL, searchstr, p);
 
1600
 
 
1601
                // Work out where in the -original- string the located parameter is.
 
1602
                //              We need to work from the original string because we need to 
 
1603
                //              preserve case and our searching string is in _lower-case_.
 
1604
                //      
 
1605
                //      After we've located it, we offset the pointer past the string we
 
1606
                //              searched for.  At this position, we should see a separator of
 
1607
                //              some type in the set [*;:=\t ].
 
1608
 
 
1609
                string = p -hl +data +strlen(searchstr);
 
1610
 
 
1611
                /**
 
1612
                 ** After searching for our parameter, if we've got a
 
1613
                 ** basic match via strstr, we should then proceed to
 
1614
                 ** check that the characters either side of it are
 
1615
                 ** relevant to a typical parameter specification
 
1616
                 **
 
1617
                 ** the characters *, =, <space> and tab can succeed a
 
1618
                 ** parameter name.
 
1619
                 **/
 
1620
                switch (*string) {
 
1621
                        case '*':
 
1622
                        case '=':
 
1623
                        case ' ':
 
1624
                        case '\t':
 
1625
                                /**
 
1626
                                 ** Permitted characters were found after the parameter name
 
1627
                                 ** so continue on...
 
1628
                                 **/
 
1629
                                break;
 
1630
                        default:
 
1631
                                /**
 
1632
                                 ** Something other than the permitted characters was found, 
 
1633
                                 ** this implies (assumed) that the string match was actually
 
1634
                                 ** just a bit of good luck, return to caller 
 
1635
                                 **/
 
1636
                                if (hl) free(hl);
 
1637
                                return 1;
 
1638
                } /** Switch **/
 
1639
 
 
1640
                /**
 
1641
                 ** Don't forget to also test the character _BEFORE_ the search string
 
1642
                 **/
 
1643
                if (1)
 
1644
                {
 
1645
                        char *before_string;
 
1646
 
 
1647
                        before_string = string -1 -strlen(searchstr);
 
1648
                        if (before_string >= data)
 
1649
                        {
 
1650
                                /**
 
1651
                                 ** The characters, <space>, <tab>, ;, : may preceed a parameter name
 
1652
                                 **/
 
1653
                                switch (*(before_string)) {
 
1654
                                        case ';':
 
1655
                                        case ':':
 
1656
                                        case ' ':
 
1657
                                        case '\t':
 
1658
                                                /**
 
1659
                                                 ** Permitted characters were found after the parameter name
 
1660
                                                 ** so continue on...
 
1661
                                                 **/
 
1662
                                                break;
 
1663
                                        default:
 
1664
                                                /**
 
1665
                                                 ** Something other than the permitted characters was found, 
 
1666
                                                 ** this implies (assumed) that the string match was actually
 
1667
                                                 ** just a bit of good luck, return to caller 
 
1668
                                                 **/
 
1669
                                                if (hl) free(hl);
 
1670
                                                return 1;
 
1671
                                } /** Switch before_string **/
 
1672
                        } /** if before_string > data **/
 
1673
                } /** 1 **/
 
1674
 
 
1675
 
 
1676
                // If the char is a '*', this means we've got a multivalue parameter
 
1677
                //              which needs to be decoded (ie, name*1*=foo name*2*=bar )
 
1678
                if (*string == '*')
 
1679
                {
 
1680
                        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Found a '*' after the name, so attempting multipart value decode",FL);
 
1681
 
 
1682
                        // PLD:DEV:11/08/2004-18H30
 
1683
                        //      Issue: RFC2231 handling
 
1684
                        return_value = MIMEH_recompose_multivalue( hinfo, searchstr, data, output_value, output_value_size, data_end_point);
 
1685
 
 
1686
 
 
1687
                } else {
 
1688
 
 
1689
                        // skip any spaces
 
1690
                        while (isspace((int) *string )) string++;
 
1691
 
 
1692
                        //if ( *string != '=' )
 
1693
                        if ( *string == '\0' )
 
1694
                        {
 
1695
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: In '%s' parsing, was expecting a '=' in the start of '%s'\n", FL, searchstr, string );
 
1696
 
 
1697
                        }
 
1698
                        else {
 
1699
                                char *endchar;
 
1700
 
 
1701
                                // Eliminate multiple = separators.
 
1702
                                // Reference: c030804-006a
 
1703
                                //      PLD:DEV: 11/08/2004-15H15
 
1704
                                while ((*(string +1) == '=')&&(*(string+1) != '\0')) { string++; MIMEH_set_defect(hinfo,MIMEH_DEFECT_MULTIPLE_EQUALS_SEPARATORS); }
 
1705
 
 
1706
 
 
1707
                                // Get the end of our string
 
1708
                                endchar = string +strlen(string) -1;
 
1709
                                *data_end_point = endchar;
 
1710
 
 
1711
                                // Strip off trailing whitespace
 
1712
                                while ((endchar > string)&&(isspace((int)*endchar)))
 
1713
                                {
 
1714
                                        *endchar = '\0';
 
1715
                                        endchar--;
 
1716
                                }
 
1717
 
 
1718
                                // we are at the '=' in the header, so skip it
 
1719
                                if (*string == '=') string++;
 
1720
                                else {
 
1721
                                        MIMEH_set_defect(hinfo,MIMEH_DEFECT_MISSING_SEPARATORS);
 
1722
                                }
 
1723
 
 
1724
                                // skip any spaces... again
 
1725
                                while ( isspace((int) *string ) ) string++;
 
1726
 
 
1727
                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Extracting value out of '%s'",FL,string);
 
1728
 
 
1729
                                // Because of all the potential exploits and bad behaviour
 
1730
                                //              we have to be really careful about how we determine
 
1731
                                //              what the enclosed string is for our parameter.
 
1732
                                //
 
1733
                                //      Previously we could _assume_ that we just get the last 
 
1734
                                //              quote (") on the line and copy out what was between,
 
1735
                                //              unfortunately that doesn't work anymore. Instead now
 
1736
                                //              we have to step along the data stream one char at a
 
1737
                                //              time and make decisions along the way.
 
1738
 
 
1739
                                switch (*string) {
 
1740
                                        case '\"':
 
1741
                                        {
 
1742
                                                // If our first char is a quote, then we'll then try and find
 
1743
                                                //              the second quote which closes the string, alas, this is
 
1744
                                                //              not always present in the header data, either due to a
 
1745
                                                //              broken MUA or due to an exploit attempt.
 
1746
                                                char *string_end;
 
1747
 
 
1748
                                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Using quoted-string tests",FL);
 
1749
 
 
1750
                                                // Remove multiple-sequential quotes
 
1751
                                                string++;
 
1752
                                                while ((*string != '\0')&&(*string == '\"')){ string++; MIMEH_set_defect(hinfo,MIMEH_DEFECT_MULTIPLE_QUOTES); }
 
1753
 
 
1754
                                                if (*string == '\0') break; // 20071030-0958: Added by Claudio Jeker - prevents overflow.
 
1755
 
 
1756
                                                // Find the next quote which isn't sequential to the above
 
1757
                                                //              quotes that we just skipped over
 
1758
                                                string_end = strchr(string+1, '\"');
 
1759
                                                if (string_end != NULL)
 
1760
                                                {
 
1761
                                                        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: End of value found",FL);
 
1762
                                                        *string_end = '\0';
 
1763
                                                        *data_end_point = string_end +1;
 
1764
                                                } else {
 
1765
                                                        // If string_end == NULL
 
1766
                                                        //
 
1767
                                                        // If we didn't find any more quotes, that 
 
1768
                                                        //              means we've probably got an unbalanced string (oh joy)
 
1769
                                                        //              so then we convert to looking for other items such as
 
1770
                                                        //              ;\n\r\t and space.
 
1771
                                                        //      
 
1772
                                                        if (hinfo) MIMEH_set_defect(hinfo,MIMEH_DEFECT_UNBALANCED_QUOTES);
 
1773
                                                        string_end = strpbrk(string,"; \n\r\t");
 
1774
                                                        if (string_end != NULL)
 
1775
                                                        {
 
1776
                                                                *string_end = '\0';
 
1777
                                                                *data_end_point = string_end +1;
 
1778
                                                        } else {
 
1779
                                                                // There is no termination to the string, instead the
 
1780
                                                                //              end of the string is \0.
 
1781
                                                        }
 
1782
                                                }
 
1783
                                        }
 
1784
                                        break;
 
1785
 
 
1786
                                        default:
 
1787
                                        {
 
1788
                                                char *string_end;
 
1789
 
 
1790
                                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Using NON-quoted-string tests",FL);
 
1791
                                                string_end = strpbrk(string,"; \n\r\t");
 
1792
                                                if (string_end != NULL)
 
1793
                                                {
 
1794
                                                        *string_end = '\0';
 
1795
                                                        *data_end_point = string_end +1;
 
1796
                                                } else {
 
1797
                                                        // There is no termination to the string, instead the
 
1798
                                                        //              end of the string is \0.
 
1799
                                                }
 
1800
                                        }
 
1801
                                        break;
 
1802
                                } /** end of switch **/
 
1803
 
 
1804
                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Extracting value out of '%s'",FL,string);
 
1805
                                // Trim up and leading/trailing quotes
 
1806
                                if (((*string == '\"')&&(*(string +strlen(string)-1) == '\"'))
 
1807
                                                || ((*string == '\'')&&(*(string +strlen(string)-1) == '\'')) )
 
1808
                                {
 
1809
                                        int slen = strlen(string) -2;
 
1810
                                        char *s = string;
 
1811
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse-header_parameter:DEBUG: Stripping quotes from '%s'",FL,string);
 
1812
                                        while (slen > 0)
 
1813
                                        {
 
1814
                                                *s = *(s+1);
 
1815
                                                s++;
 
1816
                                                slen--;
 
1817
                                        }
 
1818
                                        *s = '\0';
 
1819
 
 
1820
                                }
 
1821
 
 
1822
                                // Now that our string is all cleaned up, save it to our output value
 
1823
                                snprintf( output_value, output_value_size, "%s", string );
 
1824
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: Final value = '%s'",FL, output_value);
 
1825
                        } // If the first non-whitespace char wasn't a '='
 
1826
                } // If the first char after the search-string wasn't a '*'
 
1827
 
 
1828
        }
 
1829
        else {
 
1830
                return_value = 1;
 
1831
        }
 
1832
 
 
1833
        if (hl != NULL) free(hl);
 
1834
 
 
1835
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_header_parameter:DEBUG: [return=%d] Done seeking for '%s' data_end_point=%p (from %p)",FL, return_value, searchstr, *data_end_point, data);
 
1836
 
 
1837
        return return_value;
 
1838
 
 
1839
}
 
1840
 
 
1841
 
 
1842
 
 
1843
 
 
1844
 
 
1845
 
 
1846
 
 
1847
/*-----------------------------------------------------------------\
 
1848
  Function Name : MIMEH_is_valid_header_prefix
 
1849
  Returns Type  : int
 
1850
  ----Parameter List
 
1851
  1. char *data, 
 
1852
  2.  char *prefix_name , 
 
1853
  ------------------
 
1854
  Exit Codes    : 
 
1855
  0 = no, not valid
 
1856
  1 = yes, valid.
 
1857
  Side Effects  : 
 
1858
  --------------------------------------------------------------------
 
1859
Comments:
 
1860
 
 
1861
--------------------------------------------------------------------
 
1862
Changes:
 
1863
 
 
1864
\------------------------------------------------------------------*/
 
1865
 
 
1866
int MIMEH_is_valid_header_prefix( char *data, char *prefix_name )
 
1867
{
 
1868
        int plen = strlen(prefix_name);
 
1869
 
 
1870
        /** If our string doesn't start with content-type, then exit **/
 
1871
        if (strncasecmp(data, prefix_name, plen)!=0)
 
1872
        {
 
1873
                return 0;
 
1874
        } else {
 
1875
                char end_char;
 
1876
 
 
1877
                /** Test to see that the terminating char after the content-type
 
1878
                 ** string is suitable to indicating that the content-type is 
 
1879
                 ** infact a header name
 
1880
                 **/
 
1881
                end_char = *(data +plen);
 
1882
                switch (end_char){
 
1883
                        case ':':
 
1884
                        case ' ':
 
1885
                        case '\t':
 
1886
                        case '\0':
 
1887
                                /** Valid terminating characters found **/
 
1888
                                break;
 
1889
                        default:
 
1890
                                /** Otherwise, return 0 **/
 
1891
                                return 0;
 
1892
                } /** switch end_char **/
 
1893
        } /** if-else **/
 
1894
 
 
1895
        return 1;
 
1896
}
 
1897
 
 
1898
 
 
1899
 
 
1900
/*-----------------------------------------------------------------\
 
1901
  Function Name : MIMEH_parse_contenttype_linear
 
1902
  Returns Type  : int
 
1903
  ----Parameter List
 
1904
  1. char *header_name, 
 
1905
  2.  char *header_value, 
 
1906
  3.  struct MIMEH_header_info *hinfo , 
 
1907
  ------------------
 
1908
  Exit Codes    : 
 
1909
  Side Effects  : 
 
1910
  --------------------------------------------------------------------
 
1911
Comments:
 
1912
 
 
1913
--------------------------------------------------------------------
 
1914
Changes:
 
1915
 
 
1916
\------------------------------------------------------------------*/
 
1917
int MIMEH_parse_contenttype_linear_EXPERIMENT( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
1918
{
 
1919
        char *chv = header_value;
 
1920
        char *chn = header_name;
 
1921
        int boundary_found = 0;
 
1922
        //      int name_found = 0;
 
1923
        //      int filename_found = 0;
 
1924
 
 
1925
        /** Absorb whitespace **/
 
1926
        while (isspace(*chn)) chn++;
 
1927
 
 
1928
        /** Test if the content-type string is valid **/
 
1929
        if (MIMEH_is_valid_header_prefix(chn, "content-type")==0) return 0;
 
1930
 
 
1931
        /** Now, let's try parse our content-type parameter/value string **/
 
1932
        while (*chv)
 
1933
        {
 
1934
                while (isspace(*chv)) chv++;
 
1935
                if ((boundary_found==0)&&(MIMEH_is_valid_header_prefix(chv,"boundary")==1))
 
1936
                {
 
1937
                }
 
1938
 
 
1939
                //              if (strncasecmp(chv, "boundary"
 
1940
 
 
1941
        }
 
1942
 
 
1943
 
 
1944
        return 0;
 
1945
 
 
1946
}
 
1947
 
 
1948
/*-----------------------------------------------------------------\
 
1949
  Function Name : MIMEH_parse_contenttype
 
1950
  Returns Type  : int
 
1951
  ----Parameter List
 
1952
  1. char *header_name, 
 
1953
  2.  char *header_value, 
 
1954
  3.  struct MIMEH_header_info *hinfo , 
 
1955
  ------------------
 
1956
  Exit Codes    : 
 
1957
  Side Effects  : 
 
1958
  --------------------------------------------------------------------
 
1959
Comments:
 
1960
 
 
1961
--------------------------------------------------------------------
 
1962
Changes:
 
1963
 
 
1964
\------------------------------------------------------------------*/
 
1965
int MIMEH_parse_contenttype( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
1966
{
 
1967
 
 
1968
        int return_value;
 
1969
        char *p, *q;
 
1970
        char *hv = strdup( header_value );
 
1971
 
 
1972
        // CONTENT TYPE -------------------------------
 
1973
        // CONTENT TYPE -------------------------------
 
1974
        // CONTENT TYPE -------------------------------
 
1975
 
 
1976
        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Start",FL);
 
1977
 
 
1978
        p = strstr(header_name,"content-type");
 
1979
        if (p != NULL)
 
1980
        {
 
1981
                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype: Content-type string found in header-name",FL);
 
1982
 
 
1983
/** 20041216-1106:PLD: Increase our sanity **/
 
1984
                hinfo->sanity++;
 
1985
                PLD_strlower(  header_value );
 
1986
                PLD_strlower(  header_value );
 
1987
                q = header_value;
 
1988
 
 
1989
                if (strstr(q,"multipart/appledouble")) hinfo->content_type = _CTYPE_MULTIPART_APPLEDOUBLE;
 
1990
                else if (strstr(q,"multipart/signed")) hinfo->content_type = _CTYPE_MULTIPART_SIGNED;
 
1991
                else if (strstr(q,"multipart/related")) hinfo->content_type = _CTYPE_MULTIPART_RELATED;
 
1992
                else if (strstr(q,"multipart/mixed")) hinfo->content_type = _CTYPE_MULTIPART_MIXED;
 
1993
                else if (strstr(q,"multipart/alternative")) hinfo->content_type = _CTYPE_MULTIPART_ALTERNATIVE;
 
1994
                else if (strstr(q,"multipart/report")) hinfo->content_type = _CTYPE_MULTIPART_REPORT;
 
1995
                else if (strstr(q,"multipart/")) hinfo->content_type = _CTYPE_MULTIPART;
 
1996
                else if (strstr(q,"text/calendar")) hinfo->content_type = _CTYPE_TEXT_CALENDAR;
 
1997
                else if (strstr(q,"text/plain")) hinfo->content_type = _CTYPE_TEXT_PLAIN;
 
1998
                else if (strstr(q,"text/html")) hinfo->content_type = _CTYPE_TEXT_HTML;
 
1999
                else if (strstr(q,"text/")) hinfo->content_type = _CTYPE_TEXT;
 
2000
                else if (strstr(q,"image/gif")) hinfo->content_type = _CTYPE_IMAGE_GIF;
 
2001
                else if (strstr(q,"image/jpeg")) hinfo->content_type = _CTYPE_IMAGE_JPEG;
 
2002
                else if (strstr(q,"image/")) hinfo->content_type = _CTYPE_IMAGE;
 
2003
                else if (strstr(q,"audio/")) hinfo->content_type = _CTYPE_AUDIO;
 
2004
                else if (strstr(q,"message/rfc822")) hinfo->content_type = _CTYPE_RFC822;
 
2005
                else if (strstr(q,"/octet-stream")) hinfo->content_type = _CTYPE_OCTECT;
 
2006
                else if (strstr(q,"/ms-tnef")) hinfo->content_type = _CTYPE_TNEF;
 
2007
                else if (strstr(q,"application/applefile")) 
 
2008
                {
 
2009
                        hinfo->content_type = _CTYPE_APPLICATION_APPLEFILE;
 
2010
                        if ( hinfo->filename[0] == '\0' ) 
 
2011
                        {
 
2012
                                if (strlen(glb.appledouble_filename)>0)
 
2013
                                {
 
2014
                                        snprintf(hinfo->filename, sizeof(hinfo->filename), "%s.applemeta", glb.appledouble_filename );
 
2015
                                } else {
 
2016
                                        snprintf(hinfo->filename, sizeof(hinfo->filename), "applefile");
 
2017
                                }
 
2018
                        }
 
2019
                }
 
2020
                else hinfo->content_type = _CTYPE_UNKNOWN;
 
2021
 
 
2022
                /** Is there an x-mac-type|creator parameter? **/
 
2023
                if ((strstr(header_value,"x-mac-type="))&&(strstr(header_value,"x-mac-creator=")))
 
2024
                {
 
2025
                        /** By setting this flag to 1, we are saying that if the
 
2026
                         ** filename contains a forward slash '/' char, then it's
 
2027
                         ** to be treated as a normal char, not a directory 
 
2028
                         ** separator.  However, as we cannot generate a filename
 
2029
                         ** with that char normally, we'll convert it to something
 
2030
                         ** else
 
2031
                         **/
 
2032
                        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Located x-mac attachment",FL);
 
2033
                        hinfo->x_mac = 1;
 
2034
                        FNFILTER_set_mac(hinfo->x_mac);
 
2035
                }
 
2036
 
 
2037
 
 
2038
                // Copy the string to our content-type string storage field
 
2039
                p = header_value;
 
2040
                if (p != NULL)
 
2041
                {
 
2042
                        char *c = p;
 
2043
 
 
2044
                        // Step 1 - jump over any whitespace
 
2045
                        while ( *c == ' ' || *c == '\t') c++;
 
2046
 
 
2047
                        // Step 2 - Copy the string
 
2048
                        PLD_strncpy( hinfo->content_type_string, c, _MIMEH_CONTENT_TYPE_MAX);
 
2049
 
 
2050
                        // Step 3 - clean up the string
 
2051
                        c = hinfo->content_type_string;
 
2052
                        while (*c && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r' && *c != ';') c++;
 
2053
 
 
2054
                        // Step 4 - Terminate the string
 
2055
                        *c = '\0';
 
2056
                }
 
2057
 
 
2058
                // If we have an additional parameter at the end of our content-type, then we 
 
2059
                //      should search for a name="foobar" sequence.
 
2060
                //p = strchr( hv, ';' );
 
2061
                p = strpbrk( hv, ";\t\n\r " );
 
2062
                if (p != NULL)
 
2063
                {
 
2064
                        char *param = NULL;
 
2065
                        char *data_end_point = param;
 
2066
 
 
2067
                        p++;
 
2068
                        param = strpbrk( p, ";\n\r\t " );
 
2069
                        while ( param != NULL )
 
2070
                        {
 
2071
                                /**
 
2072
                                  **
 
2073
                                  ** The Process of decoding our line....
 
2074
                                  **    . While not end of the line...
 
2075
                                  **            . Remove whitespace
 
2076
                                  **            . test for 'name'
 
2077
                                  **            . test for 'boundary'
 
2078
                                  **            . Move to next char after parameter values
 
2079
                                  ** 
 
2080
                                 ** Go to the next character after the 'token separator' character
 
2081
                                 ** and then proceed to absorb any excess white space.
 
2082
                                 ** Once we've stopped at a new, non-white character, we can begin
 
2083
                                 ** to see if we've got a sensible parameter like name=, filename=
 
2084
                                 ** or boundary=
 
2085
                                 **/
 
2086
                                param++;
 
2087
                                param = MIMEH_absorb_whitespace(param);
 
2088
 
 
2089
                                /** 
 
2090
                                 ** If we get to the end of the line, just break out of the token
 
2091
                                 ** parsing while loop
 
2092
                                 **/
 
2093
                                if (*param == '\0') break;
 
2094
 
 
2095
                                /**
 
2096
                                 ** Look for name or filename specifications in the headers
 
2097
                                 ** Look for name or filename specifications in the headers
 
2098
                                 ** Look for name or filename specifications in the headers
 
2099
                                 **/
 
2100
 
 
2101
                                return_value = MIMEH_parse_header_parameter( hinfo, param, "name", hinfo->name, sizeof(hinfo->name), &data_end_point);
 
2102
                                /** Update param to point where data_end_point is
 
2103
                                 ** this is so when we come around here again due 
 
2104
                                 ** to the while loop, we'll know where to pick up
 
2105
                                 ** the search for more parameters
 
2106
                                 **/
 
2107
                                if (data_end_point > param) param = data_end_point;
 
2108
 
 
2109
                                // If we finally had success, then copy the name into filename for hinfo
 
2110
                                if ( return_value == 0 )
 
2111
                                {
 
2112
                                        // Move the parameter search point up to where we stopped 
 
2113
                                        //              processing the data in the MIMEH_parse_header_parameter() call
 
2114
 
 
2115
                                        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Pushing new filename to stack '%s'",FL, hinfo->name);
 
2116
                                        /** Step 1:  Check to see if this filename already
 
2117
                                         ** exists in the stack.  We do this so that we don't
 
2118
                                         ** duplicate entries and also to prevent false 
 
2119
                                         ** bad-header reports. **/
 
2120
                                        if (SS_cmp(&(hinfo->ss_names), hinfo->name, strlen(hinfo->name))==NULL) 
 
2121
                                        {
 
2122
                                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Filtering '%s'",FL, hinfo->name);
 
2123
                                                FNFILTER_filter(hinfo->name, _MIMEH_FILENAMELEN_MAX);
 
2124
                                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Pushing '%s'",FL, hinfo->name);
 
2125
                                                SS_push(&(hinfo->ss_names),hinfo->name,strlen(hinfo->name));
 
2126
                                                if (SS_count(&(hinfo->ss_names)) > 1)
 
2127
                                                {
 
2128
                                                        MIMEH_set_defect(hinfo, MIMEH_DEFECT_MULTIPLE_NAMES);
 
2129
                                                }
 
2130
 
 
2131
                                                if ( hinfo->filename[0] == '\0' ) {
 
2132
                                                        snprintf( hinfo->filename, sizeof(hinfo->filename), "%s", hinfo->name );
 
2133
                                                }
 
2134
                                        } /* If the file name doesn't already exist in the stack */
 
2135
 
 
2136
                                } /* If a filename was located in the headers */
 
2137
 
 
2138
 
 
2139
 
 
2140
 
 
2141
                                /** 
 
2142
                                 ** Look for the MIME Boundary specification in the headers 
 
2143
                                 ** Look for the MIME Boundary specification in the headers 
 
2144
                                 ** Look for the MIME Boundary specification in the headers 
 
2145
                                 **/
 
2146
                                return_value = MIMEH_parse_header_parameter(hinfo, param, "boundary", hinfo->boundary, sizeof(hinfo->boundary), &data_end_point);
 
2147
                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Param<=>data_end gap = %d", FL,data_end_point -param);
 
2148
                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param);
 
2149
                                if (data_end_point > param) param = data_end_point;
 
2150
                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param);
 
2151
 
 
2152
                                if ( return_value == 0 ) {
 
2153
                                        // Move the parameter search point up to where we stopped 
 
2154
                                        //              processing the data in the MIMEH_parse_header_parameter() call
 
2155
 
 
2156
                                        //hinfo->boundary_located = 1;
 
2157
                                        hinfo->boundary_located++;
 
2158
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Pushed boundary to stack (%s)",FL, hinfo->boundary);
 
2159
                                        BS_push(hinfo->boundary);
 
2160
                                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: Setting hinfo->boundary_located to %d",FL, hinfo->boundary_located );
 
2161
 
 
2162
                                        if (hinfo->boundary_located > 1)
 
2163
                                        {
 
2164
                                                // Register the defect
 
2165
                                                MIMEH_set_defect(hinfo, MIMEH_DEFECT_MULTIPLE_BOUNDARIES);
 
2166
 
 
2167
                                                //Reset the counter back to 1.
 
2168
                                                hinfo->boundary_located=1;
 
2169
                                        }
 
2170
                                }
 
2171
 
 
2172
                                //param = PLD_strtok( &tx, NULL, ";\n\r" );
 
2173
                                // * PLD:20040831-22H15: Added 'if (param != NULL)' prefix to debugging lines
 
2174
                                // * In response to bug #32, submitted by ICL ZA
 
2175
                                if (param != NULL) DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param);
 
2176
                                param = strpbrk( param, ";\n\r " ); 
 
2177
                                if (param != NULL) DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: param start pos = '%s'",FL, param);
 
2178
 
 
2179
                        } // While
 
2180
                }
 
2181
        }
 
2182
 
 
2183
        if (hv != NULL) free(hv);
 
2184
 
 
2185
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttype:DEBUG: end.",FL);
 
2186
 
 
2187
        return 0;
 
2188
 
 
2189
}
 
2190
 
 
2191
 
 
2192
 
 
2193
 
 
2194
 
 
2195
 
 
2196
 
 
2197
 
 
2198
 
 
2199
 
 
2200
/*-----------------------------------------------------------------\
 
2201
  Function Name : MIMEH_parse_contentlocation
 
2202
  Returns Type  : int
 
2203
  ----Parameter List
 
2204
  1. char *header_name, 
 
2205
  2.  char *header_value, 
 
2206
  3.  struct MIMEH_header_info *hinfo , 
 
2207
  ------------------
 
2208
  Exit Codes    : 
 
2209
  Side Effects  : 
 
2210
  --------------------------------------------------------------------
 
2211
Comments:
 
2212
 
 
2213
--------------------------------------------------------------------
 
2214
Changes:
 
2215
 
 
2216
\------------------------------------------------------------------*/
 
2217
int MIMEH_parse_contentlocation( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2218
{
 
2219
        char *p, *q;
 
2220
 
 
2221
        // CONTENT LOCATION -------------------------------
 
2222
        // CONTENT LOCATION -------------------------------
 
2223
        // CONTENT LOCATION -------------------------------
 
2224
 
 
2225
        PLD_strlower( header_name );
 
2226
        p = strstr(header_name,"content-location");
 
2227
        if (p)
 
2228
        {
 
2229
/** 20041216-1108:PLD: Increase our sanity **/
 
2230
                hinfo->sanity++;
 
2231
 
 
2232
                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_contentlocation:DEBUG: Content Location line found - '%s'\n", FL, header_value);
 
2233
 
 
2234
 
 
2235
                p = q = header_value;
 
2236
                while (q)
 
2237
                {
 
2238
                        q = strpbrk(p, "\\/");
 
2239
                        if (q != NULL) p = q+1;
 
2240
                }
 
2241
 
 
2242
                if (p)
 
2243
                {
 
2244
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_contentlocation:DEBUG: filename = %s\n", FL, p);
 
2245
                        snprintf(hinfo->name, sizeof(hinfo->name),"%s",p);
 
2246
                        snprintf(hinfo->filename, sizeof(hinfo->filename),"%s",p); //PLD:20100611 - fixed name mismatch,Cristian Rodríguez 
 
2247
                        FNFILTER_filter(hinfo->filename, _MIMEH_FILENAMELEN_MAX);
 
2248
                        SS_push(&(hinfo->ss_filenames), hinfo->filename, strlen(hinfo->filename));
 
2249
 
 
2250
                }
 
2251
        }
 
2252
 
 
2253
        return 0;
 
2254
 
 
2255
}
 
2256
 
 
2257
 
 
2258
 
 
2259
 
 
2260
 
 
2261
 
 
2262
 
 
2263
 
 
2264
 
 
2265
 
 
2266
 
 
2267
 
 
2268
 
 
2269
 
 
2270
/*-----------------------------------------------------------------\
 
2271
  Function Name : MIMEH_parse_contenttransferencoding
 
2272
  Returns Type  : int
 
2273
  ----Parameter List
 
2274
  1. char *header_name, 
 
2275
  2.  char *header_value, 
 
2276
  3.  struct MIMEH_header_info *hinfo , 
 
2277
  ------------------
 
2278
  Exit Codes    : 
 
2279
  Side Effects  : 
 
2280
  --------------------------------------------------------------------
 
2281
Comments:
 
2282
 
 
2283
--------------------------------------------------------------------
 
2284
Changes:
 
2285
 
 
2286
\------------------------------------------------------------------*/
 
2287
int MIMEH_parse_contenttransferencoding( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2288
{
 
2289
        char *p, *q;
 
2290
        char c = '\n';
 
2291
 
 
2292
        // CONTENT TRANSFER ENCODING ---------------------
 
2293
        // CONTENT TRANSFER ENCODING ---------------------
 
2294
        // CONTENT TRANSFER ENCODING ---------------------
 
2295
 
 
2296
 
 
2297
        p = strstr(header_name,"content-transfer-encoding");
 
2298
        if (p)
 
2299
        {
 
2300
 /** 20041216-1107:PLD: Increase our sanity **/
 
2301
                hinfo->sanity++;
 
2302
 
 
2303
                q = strpbrk(header_value,"\n\r;");
 
2304
                if (q != NULL)
 
2305
                {
 
2306
                        c = *q;
 
2307
                        *q = '\0';
 
2308
                }
 
2309
 
 
2310
                p = header_value;
 
2311
 
 
2312
                PLD_strlower( p );
 
2313
 
 
2314
                if (strstr(p,"base64"))
 
2315
                {
 
2316
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_B64;
 
2317
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to BASE64", FL);
 
2318
                }
 
2319
                else if (strstr(p,"7bit"))
 
2320
                {
 
2321
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_7BIT;
 
2322
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to 7-BIT ", FL);
 
2323
                }
 
2324
                else if (strstr(p,"8bit"))
 
2325
                {
 
2326
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_8BIT;
 
2327
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to 8-BIT", FL);
 
2328
                }
 
2329
                else if (strstr(p,"quoted-printable"))
 
2330
                {
 
2331
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_QP;
 
2332
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to Quoted-Printable", FL);
 
2333
                }
 
2334
                else if (strstr(p,"binary"))
 
2335
                {
 
2336
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_BINARY;
 
2337
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to Binary", FL);
 
2338
                }
 
2339
                else if (
 
2340
                                (strstr(p,"uu"))
 
2341
                                ||(strstr(p,"x-u"))
 
2342
                                ||(strcmp(p,"u") == 0)
 
2343
                                )
 
2344
                {
 
2345
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_UUENCODE;
 
2346
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contenttransferencoding: Encoding set to UUENCODE", FL);
 
2347
                }
 
2348
                else hinfo->content_transfer_encoding = _CTRANS_ENCODING_RAW;
 
2349
 
 
2350
 
 
2351
                // Copy the string to our content-transfer string storage field
 
2352
                p = header_value;
 
2353
                if (p != NULL)
 
2354
                {
 
2355
                        char *cp = p;
 
2356
 
 
2357
                        // Step 1 - jump over any whitespace
 
2358
                        while ( *cp == ' ' || *cp == '\t') cp++;
 
2359
 
 
2360
                        // Step 2 - Copy the string
 
2361
                        PLD_strncpy( hinfo->content_transfer_encoding_string, cp, _MIMEH_CONTENT_TRANSFER_ENCODING_MAX);
 
2362
 
 
2363
                        // Step 3 - clean up the string
 
2364
                        cp = hinfo->content_transfer_encoding_string;
 
2365
                        while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\r' && *cp != ';') cp++;
 
2366
 
 
2367
                        // Step 4 - Terminate the string
 
2368
                        *cp = '\0';
 
2369
                }
 
2370
 
 
2371
                // Set the character which we changed to a \0 back to its original form so that
 
2372
                //              we don't cause problems from tainted data for any further parsing calls
 
2373
                //              which use the data.
 
2374
                if (q != NULL) *q = c;
 
2375
        }
 
2376
 
 
2377
        return 0;
 
2378
 
 
2379
}
 
2380
 
 
2381
/*-----------------------------------------------------------------\
 
2382
  Function Name : MIMEH_parse_contentdisposition
 
2383
  Returns Type  : int
 
2384
  ----Parameter List
 
2385
  1. char *header_name, 
 
2386
  2.  char *header_value, 
 
2387
  3.  struct MIMEH_header_info *hinfo , 
 
2388
  ------------------
 
2389
  Exit Codes    : 
 
2390
  Side Effects  : 
 
2391
  --------------------------------------------------------------------
 
2392
Comments:
 
2393
 
 
2394
--------------------------------------------------------------------
 
2395
Changes:
 
2396
 
 
2397
\------------------------------------------------------------------*/
 
2398
int MIMEH_parse_contentdisposition( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2399
{
 
2400
        char  *p;
 
2401
        char *hv = strdup(header_value);
 
2402
 
 
2403
        // CONTENT DISPOSITION ------------------------------
 
2404
        // CONTENT DISPOSITION ------------------------------
 
2405
        // CONTENT DISPOSITION ------------------------------
 
2406
 
 
2407
        //LOGGER_log("%s:%d:DEBUG: Headers='%s'",FL,header_value);
 
2408
        p = strstr(header_name,"content-disposition");
 
2409
        if (p != NULL)
 
2410
        {
 
2411
/** 20041216-1107:PLD: Increase our sanity **/
 
2412
                hinfo->sanity++;
 
2413
 
 
2414
                // Change p to now point to the header VALUE, p no longer
 
2415
                //              points to the content-disposition start!
 
2416
 
 
2417
                p = header_value;
 
2418
                PLD_strlower( header_value );
 
2419
 
 
2420
                // Here we just check to find out what type of disposition we have.
 
2421
                if (strstr(p,"inline")) 
 
2422
                {
 
2423
                        hinfo->content_disposition = _CDISPOSITION_INLINE;
 
2424
                } 
 
2425
                else if (strstr(p,"form-data"))
 
2426
                {
 
2427
                        hinfo->content_disposition = _CDISPOSITION_FORMDATA;
 
2428
                }
 
2429
                else if (strstr(p,"attachment")) 
 
2430
                {
 
2431
                        hinfo->content_disposition = _CDISPOSITION_ATTACHMENT;
 
2432
                }
 
2433
                else
 
2434
                {
 
2435
                        hinfo->content_disposition = _CDISPOSITION_UNKNOWN;
 
2436
                }
 
2437
 
 
2438
                // Copy the string to our content-transfer string storage field
 
2439
                if (p != NULL)
 
2440
                {
 
2441
                        char *q = p;
 
2442
 
 
2443
                        // Step 1 - jump over any whitespace
 
2444
                        while ( *q == ' ' || *q == '\t') q++;
 
2445
 
 
2446
                        // Step 2 - Copy the string
 
2447
                        PLD_strncpy( hinfo->content_disposition_string, q, _MIMEH_CONTENT_DISPOSITION_MAX);
 
2448
 
 
2449
                        // Step 3 - clean up the string
 
2450
                        q = hinfo->content_disposition_string;
 
2451
                        while (*q && *q != ' ' && *q != '\t' && *q != '\n' && *q != '\r' && *q != ';') q++;
 
2452
 
 
2453
                        // Step 4 - Terminate the string
 
2454
                        *q = '\0';
 
2455
                }
 
2456
 
 
2457
                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_contentdisposition:DEBUG: Disposition string = '%s'",FL, hv);
 
2458
 
 
2459
                // Commence to decode the disposition string into its components.
 
2460
                p = strpbrk( hv, ";\t\n\r " );
 
2461
                if (p != NULL)
 
2462
                {
 
2463
                        //                      struct PLD_strtok tx;
 
2464
                        char *param;
 
2465
 
 
2466
                        hinfo->name[0]='\0';
 
2467
 
 
2468
                        p++;
 
2469
                        param = p;
 
2470
                        while ( param != NULL )
 
2471
                        {
 
2472
                                int parse_result;
 
2473
                                char *data_end_point;
 
2474
 
 
2475
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contentdisposition:DEBUG: Parsing '%s'",FL,param);
 
2476
 
 
2477
                                // Seek out possible 'filename' parameters 
 
2478
 
 
2479
                                parse_result = MIMEH_parse_header_parameter(hinfo, param, "filename", hinfo->name, sizeof(hinfo->name), &data_end_point);
 
2480
                                if (data_end_point > param) param = data_end_point;
 
2481
                                if (parse_result == 0) {
 
2482
                                        FNFILTER_filter(hinfo->name, _MIMEH_FILENAMELEN_MAX);
 
2483
                                        SS_push(&(hinfo->ss_filenames), hinfo->name, strlen(hinfo->name));
 
2484
                                        if (SS_count(&(hinfo->ss_filenames)) > 1)
 
2485
                                        {
 
2486
                                                MIMEH_set_defect(hinfo,MIMEH_DEFECT_MULTIPLE_FILENAMES);
 
2487
                                        }
 
2488
                                }
 
2489
 
 
2490
                                param = strpbrk( param , ";\n\r\t " );
 
2491
                                if (param) param++;
 
2492
 
 
2493
                                //param = PLD_strtok( &tx, NULL, ";\n\r\t " );
 
2494
                        } // While
 
2495
 
 
2496
                        if ( hinfo->filename[0] == '\0' ) 
 
2497
                        {
 
2498
                                snprintf( hinfo->filename, sizeof(hinfo->filename), "%s", hinfo->name );
 
2499
                        }
 
2500
 
 
2501
                        // Handle situations where we'll need the filename for the future.
 
2502
                        if ( hinfo->content_type == _CTYPE_MULTIPART_APPLEDOUBLE )
 
2503
                        {
 
2504
                                snprintf( glb.appledouble_filename, sizeof(glb.appledouble_filename), "%s", hinfo->filename );  
 
2505
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_contentdisposition:DEBUG: Setting appledouble filename to: '%s'",FL,glb.appledouble_filename);
 
2506
                        }
 
2507
 
 
2508
                } // If the header-value contained ;'s ( indicating parameters )
 
2509
 
 
2510
        } // If the header-name actually contained 'content-disposition'
 
2511
 
 
2512
        if (hv != NULL) free(hv);
 
2513
 
 
2514
        return 0;
 
2515
}
 
2516
 
 
2517
 
 
2518
 
 
2519
 
 
2520
/*-----------------------------------------------------------------\
 
2521
  Function Name : MIMEH_parse_subject
 
2522
  Returns Type  : int
 
2523
  ----Parameter List
 
2524
  1. char *header_name,  contains the full headers
 
2525
  2.  char *header_value, 
 
2526
  3.  struct MIMEH_header_info *hinfo , 
 
2527
  ------------------
 
2528
  Exit Codes    : 
 
2529
  Side Effects  : 
 
2530
  --------------------------------------------------------------------
 
2531
Comments:
 
2532
 
 
2533
--------------------------------------------------------------------
 
2534
Changes:
 
2535
 
 
2536
\------------------------------------------------------------------*/
 
2537
int MIMEH_parse_generic( char *header_name, char *header_value, struct MIMEH_header_info *hinfo, char *tokenstr, char *buffer, size_t bsize )
 
2538
{
 
2539
        int compare_result = 0;
 
2540
        int tlen;
 
2541
 
 
2542
        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_generic:DEBUG: Searching for %s in %s",FL,tokenstr,header_name);
 
2543
        /** Sanity check the parameters **/
 
2544
        if (hinfo == NULL) return -1;
 
2545
        if (tokenstr == NULL) return -1;
 
2546
        if (header_name == NULL) return -1;
 
2547
        if (header_value == NULL) return -1;
 
2548
        if (buffer == NULL) return -1;
 
2549
        if (bsize < 1) return -1;
 
2550
 
 
2551
        tlen = strlen(tokenstr);
 
2552
        compare_result = strncmp( header_name, tokenstr, tlen );
 
2553
        if (compare_result == 0)
 
2554
        {
 
2555
 
 
2556
                switch (*(header_name +tlen)) {
 
2557
                        case ':':
 
2558
                        case ' ':
 
2559
                        case '\t':
 
2560
                        case '\0':
 
2561
                                DMIMEH LOGGER_log("%s:%d:MIMEH_parse_generic:DEBUG: Located! Sanity up +1",FL);
 
2562
                                snprintf( buffer, bsize, "%s", header_value );
 
2563
                                hinfo->sanity++;
 
2564
                                break;
 
2565
                }
 
2566
                                
 
2567
        }
 
2568
 
 
2569
        return 0;
 
2570
}
 
2571
 
 
2572
/*-----------------------------------------------------------------\
 
2573
 Function Name  : MIMEH_parse_subject
 
2574
 Returns Type   : int
 
2575
        ----Parameter List
 
2576
        1. char *header_name, 
 
2577
        2.  char *header_value, 
 
2578
        3.  struct MIMEH_header_info *hinfo , 
 
2579
        ------------------
 
2580
 Exit Codes     : 
 
2581
 Side Effects   : 
 
2582
--------------------------------------------------------------------
 
2583
 Comments:
 
2584
 
 
2585
--------------------------------------------------------------------
 
2586
 Changes:
 
2587
 
 
2588
\------------------------------------------------------------------*/
 
2589
int MIMEH_parse_subject( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2590
{
 
2591
        int result = 0;
 
2592
        result = MIMEH_parse_generic( header_name, header_value, hinfo, "subject", hinfo->subject, sizeof(hinfo->subject)  );
 
2593
        snprintf(glb.subject, sizeof(glb.subject),"%s", hinfo->subject);
 
2594
 
 
2595
        return result;
 
2596
}
 
2597
 
 
2598
 
 
2599
 
 
2600
 
 
2601
/*-----------------------------------------------------------------\
 
2602
 Function Name  : MIMEH_parse_date
 
2603
 Returns Type   : int
 
2604
        ----Parameter List
 
2605
        1. char *header_name, 
 
2606
        2.  char *header_value, 
 
2607
        3.  struct MIMEH_header_info *hinfo , 
 
2608
        ------------------
 
2609
 Exit Codes     : 
 
2610
 Side Effects   : 
 
2611
--------------------------------------------------------------------
 
2612
 Comments:
 
2613
 
 
2614
--------------------------------------------------------------------
 
2615
 Changes:
 
2616
 
 
2617
\------------------------------------------------------------------*/
 
2618
int MIMEH_parse_date( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2619
{
 
2620
        return MIMEH_parse_generic( header_name, header_value, hinfo, "date", hinfo->date, sizeof(hinfo->date) );
 
2621
}
 
2622
/*-----------------------------------------------------------------\
 
2623
 Function Name  : MIMEH_parse_from
 
2624
 Returns Type   : int
 
2625
        ----Parameter List
 
2626
        1. char *header_name, 
 
2627
        2.  char *header_value, 
 
2628
        3.  struct MIMEH_header_info *hinfo , 
 
2629
        ------------------
 
2630
 Exit Codes     : 
 
2631
 Side Effects   : 
 
2632
--------------------------------------------------------------------
 
2633
 Comments:
 
2634
 
 
2635
--------------------------------------------------------------------
 
2636
 Changes:
 
2637
 
 
2638
\------------------------------------------------------------------*/
 
2639
int MIMEH_parse_from( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2640
{
 
2641
        return MIMEH_parse_generic( header_name, header_value, hinfo, "from", hinfo->from, sizeof(hinfo->from) );
 
2642
}
 
2643
/*-----------------------------------------------------------------\
 
2644
 Function Name  : MIMEH_parse_to
 
2645
 Returns Type   : int
 
2646
        ----Parameter List
 
2647
        1. char *header_name, 
 
2648
        2.  char *header_value, 
 
2649
        3.  struct MIMEH_header_info *hinfo , 
 
2650
        ------------------
 
2651
 Exit Codes     : 
 
2652
 Side Effects   : 
 
2653
--------------------------------------------------------------------
 
2654
 Comments:
 
2655
 
 
2656
--------------------------------------------------------------------
 
2657
 Changes:
 
2658
 
 
2659
\------------------------------------------------------------------*/
 
2660
int MIMEH_parse_to( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2661
{
 
2662
        return MIMEH_parse_generic( header_name, header_value, hinfo, "to", hinfo->to, sizeof(hinfo->to) );
 
2663
}
 
2664
/*-----------------------------------------------------------------\
 
2665
 Function Name  : MIMEH_parse_messageid
 
2666
 Returns Type   : int
 
2667
        ----Parameter List
 
2668
        1. char *header_name, 
 
2669
        2.  char *header_value, 
 
2670
        3.  struct MIMEH_header_info *hinfo , 
 
2671
        ------------------
 
2672
 Exit Codes     : 
 
2673
 Side Effects   : 
 
2674
--------------------------------------------------------------------
 
2675
 Comments:
 
2676
 
 
2677
--------------------------------------------------------------------
 
2678
 Changes:
 
2679
 
 
2680
\------------------------------------------------------------------*/
 
2681
int MIMEH_parse_messageid( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2682
{
 
2683
        return MIMEH_parse_generic( header_name, header_value, hinfo, "message-id", hinfo->messageid, sizeof(hinfo->messageid) );
 
2684
}
 
2685
/*-----------------------------------------------------------------\
 
2686
 Function Name  : MIMEH_parse_received
 
2687
 Returns Type   : int
 
2688
        ----Parameter List
 
2689
        1. char *header_name, 
 
2690
        2.  char *header_value, 
 
2691
        3.  struct MIMEH_header_info *hinfo , 
 
2692
        ------------------
 
2693
 Exit Codes     : 
 
2694
 Side Effects   : 
 
2695
--------------------------------------------------------------------
 
2696
 Comments:
 
2697
 
 
2698
--------------------------------------------------------------------
 
2699
 Changes:
 
2700
 
 
2701
\------------------------------------------------------------------*/
 
2702
int MIMEH_parse_received( char *header_name, char *header_value, struct MIMEH_header_info *hinfo )
 
2703
{
 
2704
        return MIMEH_parse_generic( header_name, header_value, hinfo, "received", hinfo->received, sizeof(hinfo->received) );
 
2705
}
 
2706
 
 
2707
/*-----------------------------------------------------------------\
 
2708
  Function Name : MIMEH_process_headers
 
2709
  Returns Type  : int
 
2710
  ----Parameter List
 
2711
  1. struct MIMEH_header_info *hinfo, 
 
2712
  2.  char *headers , 
 
2713
  ------------------
 
2714
  Exit Codes    : 
 
2715
  Side Effects  : 
 
2716
  --------------------------------------------------------------------
 
2717
Comments:
 
2718
 
 
2719
--------------------------------------------------------------------
 
2720
Changes:
 
2721
 
 
2722
\------------------------------------------------------------------*/
 
2723
int MIMEH_headers_process( struct MIMEH_header_info *hinfo, char *headers )
 
2724
{
 
2725
        /** scan through our headers string looking for information that is
 
2726
          ** valid **/
 
2727
        char *safeh, *h, *safehl;
 
2728
        char *current_header_position;
 
2729
        int headerlength;
 
2730
 
 
2731
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Start [hinfo=%p]\n",FL, hinfo);
 
2732
 
 
2733
        safeh = h = headers;
 
2734
 
 
2735
        /** Duplicate the headers for processing - this way we don't 'taint' the
 
2736
        ** original headers during our searching / altering. **/
 
2737
 
 
2738
        headerlength = strlen(h);
 
2739
        safehl = malloc(sizeof(char) *(headerlength+1));
 
2740
        PLD_strncpy(safehl, h, headerlength+1);
 
2741
 
 
2742
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_headers:DEBUG: Header length = %d\n", FL,headerlength);
 
2743
 
 
2744
        MIMEH_strip_comments(h);
 
2745
 
 
2746
        current_header_position = h;
 
2747
 
 
2748
        // Searching through the headers, we seek out header 'name:value;value;value' sets,
 
2749
        //              Each set is then cleaned up, seperated and parsed.
 
2750
 
 
2751
        while ((current_header_position != NULL)&&( current_header_position <= (h +headerlength) ))
 
2752
        {
 
2753
                char *header_name, *header_value;
 
2754
                char *header_name_end_position;
 
2755
                char *header_value_end_position;
 
2756
 
 
2757
                DMIMEH LOGGER_log("%s:%d:MIMEH_headers_process:DEBUG: Processing '%s'",FL,current_header_position);
 
2758
 
 
2759
                /** Tokenise for the header 'name', ie, content-type, subject etc **/
 
2760
                header_name = current_header_position;
 
2761
                header_name_end_position = strpbrk( header_name, ":\t " );
 
2762
                if (header_name_end_position == NULL)
 
2763
                {
 
2764
                        // We couldn't find a terminating :, so, instead we try to find
 
2765
                        //      the first whitespace
 
2766
                        //
 
2767
                        // PLD:DEV:11/08/2004-15H27
 
2768
                        //      Issue: c030804-006a
 
2769
                        //
 
2770
                        // NOTE: this may activate on the true-blank lines, hence why we
 
2771
                        //              dump the source string, just for confirmation
 
2772
 
 
2773
                        DMIMEH LOGGER_log("%s:%d:MIMEH_headers_process:DEBUG: Could not locate ':' separator, using whitespace (source='%s')",FL,header_name);
 
2774
                        header_name_end_position = strpbrk( header_name, "\t " );
 
2775
                        if (header_name_end_position == NULL)
 
2776
                        {
 
2777
                                DMIMEH LOGGER_log("%s:%d:MIMEH_headers_process:DEBUG: Cannot find a header name:value pair in '%s'",FL, header_name);
 
2778
                        }
 
2779
                }
 
2780
 
 
2781
                // Seek forward from the start of our header, looking for the first occurance
 
2782
                //              of the line end (implying the end of the current header name:value,
 
2783
                //              we can do this because we know that when the headers were read in, we
 
2784
                //              have already unfolded them, such that there should only be one header:value
 
2785
                //              pairing per 'line'.
 
2786
 
 
2787
                current_header_position = strpbrk( current_header_position, "\n\r");
 
2788
                if ( current_header_position == NULL )
 
2789
                {
 
2790
                        // Theoretically, this should not happen, as headers are always
 
2791
                        //              terminated with a \n\r\n\r finishing byte sequence, thus
 
2792
                        //              if this _does_ happen, then we will simply jump out of the 
 
2793
                        //              current iteration and let the loop try find another pairing
 
2794
                        //
 
2795
                        // There probably should be a logging entry here to indicate that
 
2796
                        //              "something strange happened"
 
2797
 
 
2798
                        continue;
 
2799
                } else {
 
2800
 
 
2801
                        // Shuffle our CHP (current-header-position) pointer along the header
 
2802
                        //              data until it is no longer pointing to a \r or \n, this is so
 
2803
                        //              that when the next iteration of this loop comes around, it'll
 
2804
                        //              immediately be in the right place for starting the next parse
 
2805
 
 
2806
                        while (( *current_header_position == '\n') ||( *current_header_position == '\r' )) current_header_position++;
 
2807
                }
 
2808
 
 
2809
                if (( header_name_end_position == NULL )||( header_name_end_position > current_header_position))
 
2810
                { 
 
2811
                        // Some headers can contain various levels of non name/value pairings,
 
2812
                        //              while their presence could be debatable in terms of RFC validity
 
2813
                        //              we will 'ignore' them rather than throwing up our arms.  This 
 
2814
                        //              ensures that we are not made to break over spurilous data.
 
2815
 
 
2816
                        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: This line contains no header:value pair (%s)", FL, current_header_position);
 
2817
                        continue;
 
2818
 
 
2819
                } else {
 
2820
 
 
2821
                        // Get the header-value string and prepare to
 
2822
                        //              parse the data through our various parsing 
 
2823
                        //              functions.
 
2824
 
 
2825
                        header_value = header_name_end_position +1;
 
2826
                        header_value_end_position = strpbrk( header_value, "\n\r" );
 
2827
                        if ( header_value_end_position != NULL )
 
2828
                        {
 
2829
                                *header_name_end_position = '\0';
 
2830
                                *header_value_end_position = '\0';
 
2831
                                if (MIMEH_DNORMAL)
 
2832
                                {
 
2833
                                        LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Header Name ='%s'", FL, header_name );
 
2834
                                        LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Header Value='%s'", FL, header_value );
 
2835
                                }
 
2836
 
 
2837
                                // To make parsing simpler, convert our
 
2838
                                //              header name to lowercase, that way
 
2839
                                //              we also reduce the CPU requirements for 
 
2840
                                //              searching because pre-lowering the header-name
 
2841
                                //              occurs once, but string testing against it
 
2842
                                //              occurs multiple times ( at least once per parsing
 
2843
 
 
2844
                                PLD_strlower( header_name );
 
2845
                                MIMEH_parse_subject( header_name, header_value, hinfo );
 
2846
                                MIMEH_parse_contenttype( header_name, header_value, hinfo );
 
2847
                                MIMEH_parse_contenttransferencoding( header_name, header_value, hinfo );
 
2848
                                MIMEH_parse_contentdisposition( header_name, header_value, hinfo );
 
2849
                                /** These items aren't really -imperative- to have, but they do
 
2850
                                  ** help with the sanity checking **/
 
2851
                                MIMEH_parse_date( header_name, header_value, hinfo );
 
2852
                                MIMEH_parse_from( header_name, header_value, hinfo );
 
2853
                                MIMEH_parse_to( header_name, header_value, hinfo );
 
2854
                                MIMEH_parse_messageid( header_name, header_value, hinfo );
 
2855
                                MIMEH_parse_received( header_name, header_value, hinfo );
 
2856
 
 
2857
                                if (hinfo->filename[0] == '\0')
 
2858
                                {
 
2859
                                        MIMEH_parse_contentlocation( header_name, header_value, hinfo );
 
2860
                                }
 
2861
 
 
2862
                        } else {
 
2863
                                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headerss:DEBUG: Header value end position is NULL",FL);
 
2864
                        }
 
2865
                }
 
2866
 
 
2867
 
 
2868
 
 
2869
        } // while
 
2870
 
 
2871
        // Final analysis on our headers:
 
2872
        if ( hinfo->content_type == _CTYPE_MULTIPART_APPLEDOUBLE )
 
2873
        {
 
2874
                char tmp[128];
 
2875
                snprintf( tmp, sizeof(tmp), "mac-%s", hinfo->filename );
 
2876
                snprintf( hinfo->filename, sizeof(hinfo->filename), "%s", tmp );
 
2877
                snprintf( hinfo->name, sizeof(hinfo->name), "%s", tmp );
 
2878
        }
 
2879
 
 
2880
        // PLD:20031205
 
2881
        // Act like Outlook *God forbid!* and if there's a octect-stream 
 
2882
        //      content-type, but the encoding is still null/empty, then 
 
2883
        //      change the content-encoding to be RAW
 
2884
 
 
2885
        if ( hinfo->content_type == _CTYPE_OCTECT )
 
2886
        {
 
2887
                if ((hinfo->content_transfer_encoding == _CTRANS_ENCODING_UNSPECIFIED)
 
2888
                                || (hinfo->content_transfer_encoding == _CTRANS_ENCODING_UNKNOWN)
 
2889
                                || (strlen(hinfo->content_transfer_encoding_string) < 1)
 
2890
                        )       
 
2891
                {
 
2892
                        //LOGGER_log("%s:%d:DEBUG: Encoding pair was octet but no encoding, filename=%s\n",FL,hinfo->filename);
 
2893
                        hinfo->content_transfer_encoding = _CTRANS_ENCODING_RAW;
 
2894
                }
 
2895
        }
 
2896
 
 
2897
 
 
2898
        if (safehl)
 
2899
        {
 
2900
                free(safehl);
 
2901
        }
 
2902
        else LOGGER_log("%s:%d:MIME_parse_headers:WARNING: Unable to free HEADERS allocated memory\n", FL);
 
2903
 
 
2904
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: END [hinfo=%p]\n", FL, hinfo);
 
2905
 
 
2906
        return 0;
 
2907
}
 
2908
 
 
2909
 
 
2910
/*-----------------------------------------------------------------\
 
2911
  Function Name : MIMEH_get_headers
 
2912
  Returns Type  : int
 
2913
  ----Parameter List
 
2914
  1. struct MIMEH_header_info *hinfo, 
 
2915
  2.  FFGET_FILE *f , 
 
2916
  ------------------
 
2917
  Exit Codes    : 
 
2918
  Side Effects  : 
 
2919
  --------------------------------------------------------------------
 
2920
Comments:
 
2921
 
 
2922
--------------------------------------------------------------------
 
2923
Changes:
 
2924
 
 
2925
\------------------------------------------------------------------*/
 
2926
int MIMEH_headers_get( struct MIMEH_header_info *hinfo, FFGET_FILE *f )
 
2927
{
 
2928
        int result = 0;
 
2929
 
 
2930
        // Setup some basic defaults 
 
2931
        hinfo->filename[0] = '\0';
 
2932
        hinfo->name[0] = '\0';
 
2933
        hinfo->content_type = _CTYPE_UNKNOWN;
 
2934
        hinfo->subject[0] = '\0';
 
2935
 
 
2936
        // 20040116-1234:PLD - added to appease valgrind
 
2937
        hinfo->content_disposition = 0;
 
2938
        hinfo->content_transfer_encoding = 0;
 
2939
        hinfo->boundary_located = 0;
 
2940
 
 
2941
        hinfo->crlf_count=0;
 
2942
        hinfo->crcr_count=0;
 
2943
        hinfo->lf_count=0;
 
2944
        snprintf(hinfo->delimeter,sizeof(hinfo->delimeter),"\r\n");
 
2945
 
 
2946
        // Initialise header defects array.
 
2947
        hinfo->header_defect_count = 0;
 
2948
        memset(hinfo->defects, 0, _MIMEH_DEFECT_ARRAY_SIZE);
 
2949
 
 
2950
        snprintf( hinfo->content_type_string, _MIMEH_CONTENT_TYPE_MAX , "text/plain" ); 
 
2951
 
 
2952
 
 
2953
        // Read from the file, the headers we need
 
2954
        FFGET_set_watch_SDL(1);
 
2955
        result = MIMEH_read_headers(hinfo, f);
 
2956
        FFGET_set_watch_SDL(0);
 
2957
 
 
2958
        if (hinfo->lf_count > hinfo->crlf_count) { 
 
2959
                snprintf(hinfo->delimeter,sizeof(hinfo->delimeter),"\n");
 
2960
        }
 
2961
 
 
2962
        // If we ran out of input whilst looking at headers, then, we basically
 
2963
        // flag this, free up the headers, and return.
 
2964
        if (result == -1)
 
2965
        {
 
2966
                if (glb.headerline) free(glb.headerline);
 
2967
                return result;
 
2968
        }
 
2969
 
 
2970
        // If we came back with an OKAY result, but there's nothing in the
 
2971
        //      headers, then flag off an error
 
2972
        if (glb.headerline == NULL)
 
2973
        {
 
2974
                if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIME_parse_headers:DEBUG: null headerline\n", FL);
 
2975
                return 1;
 
2976
        }
 
2977
 
 
2978
        return result;
 
2979
}
 
2980
 
 
2981
/*-----------------------------------------------------------------\
 
2982
  Function Name : MIMEH_headers_cleanup
 
2983
  Returns Type  : int
 
2984
  ----Parameter List
 
2985
  1. void , 
 
2986
  ------------------
 
2987
  Exit Codes    : 
 
2988
  Side Effects  : 
 
2989
  --------------------------------------------------------------------
 
2990
Comments:
 
2991
 
 
2992
--------------------------------------------------------------------
 
2993
Changes:
 
2994
 
 
2995
\------------------------------------------------------------------*/
 
2996
int MIMEH_headers_cleanup( void )
 
2997
{
 
2998
        if (glb.headerline != NULL)
 
2999
        {
 
3000
                free(glb.headerline);
 
3001
                glb.headerline = NULL;
 
3002
        }
 
3003
 
 
3004
        if (glb.headerline_original != NULL)
 
3005
        { 
 
3006
                free(glb.headerline_original);
 
3007
                glb.headerline_original = NULL;
 
3008
        } 
 
3009
 
 
3010
        return 0;
 
3011
}
 
3012
 
 
3013
 
 
3014
 
 
3015
/*-----------------------------------------------------------------\
 
3016
  Function Name : MIMEH_parse_headers
 
3017
  Returns Type  : int
 
3018
  ----Parameter List
 
3019
  1. FFGET_FILE *f, 
 
3020
  2.  struct MIMEH_header_info *hinfo , 
 
3021
  ------------------
 
3022
  Exit Codes    : 
 
3023
  Side Effects  : 
 
3024
  --------------------------------------------------------------------
 
3025
Comments:
 
3026
 
 
3027
--------------------------------------------------------------------
 
3028
Changes:
 
3029
 
 
3030
\------------------------------------------------------------------*/
 
3031
int MIMEH_parse_headers( FFGET_FILE *f, struct MIMEH_header_info *hinfo )
 
3032
{
 
3033
        int result = 0;
 
3034
        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Start [F=%p, hinfo=%p]\n", FL, f, hinfo);
 
3035
 
 
3036
        /** 20041216-1100:PLD: Set the header sanity to zero **/
 
3037
        if ( result == 0 ) hinfo->sanity = 0; 
 
3038
        
 
3039
        /** Proceed to read, process and finish headers **/
 
3040
        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Getting headers",FL);
 
3041
        if ( result == 0 ) result = MIMEH_headers_get( hinfo, f );
 
3042
        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Processing headers",FL);
 
3043
        if ( result == 0 ) result = MIMEH_headers_process( hinfo, glb.headerline );
 
3044
        DMIMEH LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: Cleanup of headers",FL);
 
3045
        if ( result == 0 ) result = MIMEH_headers_cleanup(); 
 
3046
        if (MIMEH_DNORMAL) LOGGER_log("%s:%d:MIMEH_parse_headers:DEBUG: END [F=%p, hinfo=%p, sanity=%d]\n", FL, f, hinfo, hinfo->sanity);
 
3047
 
 
3048
        return result;
 
3049
}
 
3050
 
 
3051
/*-----------------------------------------------------------------\
 
3052
  Function Name : MIMEH_dump_defects
 
3053
  Returns Type  : int
 
3054
  ----Parameter List
 
3055
  1. struct MIMEH_header_info *hinfo , 
 
3056
  ------------------
 
3057
  Exit Codes    : 
 
3058
  Side Effects  : 
 
3059
  --------------------------------------------------------------------
 
3060
Comments:
 
3061
Displays a list of the located defects
 
3062
 
 
3063
--------------------------------------------------------------------
 
3064
Changes:
 
3065
 
 
3066
\------------------------------------------------------------------*/
 
3067
int MIMEH_dump_defects( struct MIMEH_header_info *hinfo )
 
3068
{
 
3069
        int i;
 
3070
 
 
3071
        MIMEH_defect_description_array[MIMEH_DEFECT_MISSING_SEPARATORS] = strdup("Missing separators");
 
3072
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_FIELD_OCCURANCE] = strdup("Multiple field occurance");
 
3073
        MIMEH_defect_description_array[MIMEH_DEFECT_UNBALANCED_BOUNDARY_QUOTE] = strdup("Unbalanced boundary quote");
 
3074
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_BOUNDARIES] = strdup("Multiple boundries");
 
3075
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_COLON_SEPARATORS] = strdup("Multiple colon separators");
 
3076
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_EQUALS_SEPARATORS] = strdup("Multiple equals separators");
 
3077
        MIMEH_defect_description_array[MIMEH_DEFECT_UNBALANCED_QUOTES] = strdup("Unbalanced quotes");
 
3078
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_QUOTES] = strdup("Multiple quotes");
 
3079
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_NAMES] = strdup("Multiple names");
 
3080
        MIMEH_defect_description_array[MIMEH_DEFECT_MULTIPLE_FILENAMES] = strdup("Multiple filenames");
 
3081
 
 
3082
        for (i = 0; i < _MIMEH_DEFECT_ARRAY_SIZE; i++)
 
3083
        {
 
3084
                if (hinfo->defects[i] > 0)
 
3085
                {
 
3086
                        LOGGER_log("Header Defect: %s: %d",MIMEH_defect_description_array[i],hinfo->defects[i]);
 
3087
                }
 
3088
 
 
3089
        }
 
3090
 
 
3091
        return 0;
 
3092
}
 
3093
 
 
3094
/*-----------------------------------------------------------------\
 
3095
  Function Name : MIMEH_get_defect_count
 
3096
  Returns Type  : int
 
3097
  ----Parameter List
 
3098
  1. struct MIMEH_header_info *hinfo , 
 
3099
  ------------------
 
3100
  Exit Codes    : 
 
3101
  Side Effects  : 
 
3102
  --------------------------------------------------------------------
 
3103
Comments:
 
3104
 
 
3105
--------------------------------------------------------------------
 
3106
Changes:
 
3107
 
 
3108
\------------------------------------------------------------------*/
 
3109
int MIMEH_get_defect_count( struct MIMEH_header_info *hinfo )
 
3110
{
 
3111
 
 
3112
        return hinfo->header_defect_count;
 
3113
}
 
3114
 
 
3115
 
 
3116
//----------------------END
 
3117