Switch to unified view

a/src/bincimapmime/mime-parsefull.cc b/src/bincimapmime/mime-parsefull.cc
...
...
25
 */
25
 */
26
#ifdef HAVE_CONFIG_H
26
#ifdef HAVE_CONFIG_H
27
#include <config.h>
27
#include <config.h>
28
#endif
28
#endif
29
29
30
#include "mime.h"
30
#include <string.h>
31
#include "mime-utils.h"
31
#include <ctype.h>
32
#include "mime-inputsource.h"
32
#include <stdio.h>
33
#include "convert.h"
33
#include <errno.h>
34
34
#include <string>
35
#include <string>
35
#include <vector>
36
#include <vector>
36
#include <map>
37
#include <map>
37
#include <exception>
38
#include <exception>
38
#include <iostream>
39
#include <iostream>
39
40
40
#include <string.h>
41
#include <ctype.h>
42
#include <stdio.h>
43
#include <errno.h>
44
45
Binc::MimeInputSource *mimeSource = 0;
46
47
#ifndef NO_NAMESPACES
41
#ifndef NO_NAMESPACES
48
using namespace ::std;
42
using namespace ::std;
49
#endif /* NO_NAMESPACES */
43
#endif /* NO_NAMESPACES */
50
44
51
#undef MPF
45
#include "mime.h"
46
#include "mime-utils.h"
47
#include "mime-inputsource.h"
48
#include "convert.h"
49
50
// #define MPF
52
#ifdef MPF
51
#ifdef MPF
53
#define MPFDEB(X) fprintf X
52
#define MPFDEB(X) fprintf X
54
#else
53
#else
55
#define MPFDEB(X)
54
#define MPFDEB(X)
56
#endif
55
#endif
57
56
58
//------------------------------------------------------------------------
57
//------------------------------------------------------------------------
59
void Binc::MimeDocument::parseFull(int fd) const
58
void Binc::MimeDocument::parseFull(int fd)
60
{
59
{
61
  if (allIsParsed)
60
  if (allIsParsed)
62
    return;
61
    return;
63
62
64
  allIsParsed = true;
63
  allIsParsed = true;
65
64
66
  if (!mimeSource || mimeSource->getFileDescriptor() != fd) {
67
    delete mimeSource;
65
  delete doc_mimeSource;
68
    mimeSource = new MimeInputSource(fd);
66
  doc_mimeSource = new MimeInputSource(fd);
69
  } else {
70
    mimeSource->reset();
71
  }
72
67
73
  headerstartoffsetcrlf = 0;
68
  headerstartoffsetcrlf = 0;
74
  headerlength = 0;
69
  headerlength = 0;
75
  bodystartoffsetcrlf = 0;
70
  bodystartoffsetcrlf = 0;
76
  bodylength = 0;
71
  bodylength = 0;
...
...
78
  messagerfc822 = false;
73
  messagerfc822 = false;
79
  multipart = false;
74
  multipart = false;
80
75
81
  int bsize = 0;
76
  int bsize = 0;
82
  string bound;
77
  string bound;
83
  doParseFull(bound, bsize);
78
  doParseFull(doc_mimeSource, bound, bsize);
84
79
85
  // eat any trailing junk to get the correct size
80
  // eat any trailing junk to get the correct size
86
  char c;
81
  char c;
87
  while (mimeSource->getChar(&c));
82
  while (doc_mimeSource->getChar(&c));
88
83
89
  size = mimeSource->getOffset();
84
  size = doc_mimeSource->getOffset();
90
}
85
}
91
86
92
void Binc::MimeDocument::parseFull(istream& s) const
87
void Binc::MimeDocument::parseFull(istream& s)
93
{
88
{
94
  if (allIsParsed)
89
  if (allIsParsed)
95
    return;
90
    return;
96
91
97
  allIsParsed = true;
92
  allIsParsed = true;
98
93
99
  delete mimeSource;
94
  delete doc_mimeSource;
100
  mimeSource = new MimeInputSourceStream(s);
95
  doc_mimeSource = new MimeInputSourceStream(s);
101
96
102
  headerstartoffsetcrlf = 0;
97
  headerstartoffsetcrlf = 0;
103
  headerlength = 0;
98
  headerlength = 0;
104
  bodystartoffsetcrlf = 0;
99
  bodystartoffsetcrlf = 0;
105
  bodylength = 0;
100
  bodylength = 0;
...
...
107
  messagerfc822 = false;
102
  messagerfc822 = false;
108
  multipart = false;
103
  multipart = false;
109
104
110
  int bsize = 0;
105
  int bsize = 0;
111
  string bound;
106
  string bound;
112
  doParseFull(bound, bsize);
107
  doParseFull(doc_mimeSource, bound, bsize);
113
108
114
  // eat any trailing junk to get the correct size
109
  // eat any trailing junk to get the correct size
115
  char c;
110
  char c;
116
  while (mimeSource->getChar(&c));
111
  while (doc_mimeSource->getChar(&c));
117
112
118
  size = mimeSource->getOffset();
113
  size = doc_mimeSource->getOffset();
119
}
114
}
120
115
121
//------------------------------------------------------------------------
116
//------------------------------------------------------------------------
122
static bool parseOneHeaderLine(Binc::Header *header, unsigned int *nlines)
117
bool Binc::MimePart::parseOneHeaderLine(Binc::Header *header, 
118
                  unsigned int *nlines)
123
{
119
{
124
  using namespace ::Binc;
120
  using namespace ::Binc;
125
  char c;
121
  char c;
126
  bool eof = false;
122
  bool eof = false;
127
  char cqueue[4];
123
  char cqueue[4];
...
...
200
196
201
  return !(eof || endOfHeaders);
197
  return !(eof || endOfHeaders);
202
}
198
}
203
199
204
//------------------------------------------------------------------------
200
//------------------------------------------------------------------------
205
static void parseHeader(Binc::Header *header, unsigned int *nlines)
201
void Binc::MimePart::parseHeader(Binc::Header *header, unsigned int *nlines)
206
{
202
{
207
  while (parseOneHeaderLine(header, nlines))
203
  while (parseOneHeaderLine(header, nlines))
208
  { }
204
  { }
209
}
205
}
210
206
211
//------------------------------------------------------------------------
207
//------------------------------------------------------------------------
212
static void analyzeHeader(Binc::Header *header, bool *multipart,
208
void Binc::MimePart::analyzeHeader(Binc::Header *header, bool *multipart,
213
              bool *messagerfc822, string *subtype,
209
                 bool *messagerfc822, string *subtype,
214
              string *boundary)
210
                 string *boundary)
215
{
211
{
216
  using namespace ::Binc;
212
  using namespace ::Binc;
217
213
218
  // Do simple parsing of headers to determine the
214
  // Do simple parsing of headers to determine the
219
  // type of message (multipart,messagerfc822 etc)
215
  // type of message (multipart,messagerfc822 etc)
...
...
265
      }
261
      }
266
    }
262
    }
267
  }
263
  }
268
}
264
}
269
265
270
static void parseMessageRFC822(vector<Binc::MimePart> *members,
266
void Binc::MimePart::parseMessageRFC822(vector<Binc::MimePart> *members,
271
                   bool *foundendofpart,
267
                  bool *foundendofpart,
272
                   unsigned int *bodylength,
268
                  unsigned int *bodylength,
273
                   unsigned int *nbodylines,
269
                  unsigned int *nbodylines,
274
                   const string &toboundary)
270
                  const string &toboundary)
275
{
271
{
276
  using namespace ::Binc;
272
  using namespace ::Binc;
277
273
278
  // message rfc822 means a completely enclosed mime document. we
274
  // message rfc822 means a completely enclosed mime document. we
279
  // call the parser recursively, and pass on the boundary string
275
  // call the parser recursively, and pass on the boundary string
...
...
284
  unsigned int bodystartoffsetcrlf = mimeSource->getOffset();
280
  unsigned int bodystartoffsetcrlf = mimeSource->getOffset();
285
    
281
    
286
  // parsefull returns the number of bytes that need to be removed
282
  // parsefull returns the number of bytes that need to be removed
287
  // from the body because of the terminating boundary string.
283
  // from the body because of the terminating boundary string.
288
  int bsize = 0;
284
  int bsize = 0;
289
  if (m.doParseFull(toboundary, bsize))
285
  if (m.doParseFull(mimeSource, toboundary, bsize))
290
    *foundendofpart = true;
286
    *foundendofpart = true;
291
287
292
  // make sure bodylength doesn't overflow    
288
  // make sure bodylength doesn't overflow    
293
  *bodylength = mimeSource->getOffset();
289
  *bodylength = mimeSource->getOffset();
294
  if (*bodylength >= bodystartoffsetcrlf) {
290
  if (*bodylength >= bodystartoffsetcrlf) {
...
...
305
  *nbodylines += m.getNofLines();
301
  *nbodylines += m.getNofLines();
306
302
307
  members->push_back(m);
303
  members->push_back(m);
308
}
304
}
309
305
310
static bool skipUntilBoundary(const string &delimiter,
306
bool Binc::MimePart::skipUntilBoundary(const string &delimiter,
311
                  unsigned int *nlines, bool *eof)
307
                     unsigned int *nlines, bool *eof)
312
{
308
{
313
  int endpos = delimiter.length();
309
  int endpos = delimiter.length();
314
  char *delimiterqueue = 0;
310
  char *delimiterqueue = 0;
315
  int delimiterpos = 0;
311
  int delimiterpos = 0;
316
  const char *delimiterStr = delimiter.c_str();
312
  const char *delimiterStr = delimiter.c_str();
...
...
358
354
359
// JFD: Things we do after finding a boundary (something like CRLF--somestring)
355
// JFD: Things we do after finding a boundary (something like CRLF--somestring)
360
// Need to see if this is a final one (with an additional -- at the end),
356
// Need to see if this is a final one (with an additional -- at the end),
361
// and need to check if it is immediately followed by another boundary 
357
// and need to check if it is immediately followed by another boundary 
362
// (in this case, we give up our final CRLF in its favour)
358
// (in this case, we give up our final CRLF in its favour)
363
static inline void postBoundaryProcessing(bool *eof,
359
inline void Binc::MimePart::postBoundaryProcessing(bool *eof,
364
                      unsigned int *nlines,
360
                         unsigned int *nlines,
365
                      int *boundarysize,
361
                         int *boundarysize,
366
                      bool *foundendofpart)
362
                         bool *foundendofpart)
367
{
363
{
368
    // Read two more characters. This may be CRLF, it may be "--" and
364
    // Read two more characters. This may be CRLF, it may be "--" and
369
    // it may be any other two characters.
365
    // it may be any other two characters.
370
    char a = '\0';
366
    char a = '\0';
371
    if (!mimeSource->getChar(&a))
367
    if (!mimeSource->getChar(&a))
...
...
428
      mimeSource->ungetChar();
424
      mimeSource->ungetChar();
429
      mimeSource->ungetChar();
425
      mimeSource->ungetChar();
430
    }
426
    }
431
}
427
}
432
428
433
static void parseMultipart(const string &boundary,
429
void Binc::MimePart::parseMultipart(const string &boundary,
434
               const string &toboundary,
430
                  const string &toboundary,
435
               bool *eof,
431
                  bool *eof,
436
               unsigned int *nlines,
432
                  unsigned int *nlines,
437
               int *boundarysize,
433
                  int *boundarysize,
438
               bool *foundendofpart,
434
                  bool *foundendofpart,
439
               unsigned int *bodylength,
435
                  unsigned int *bodylength,
440
               vector<Binc::MimePart> *members)
436
                  vector<Binc::MimePart> *members)
441
{
437
{
442
  MPFDEB((stderr, "BINC: ParseMultipart: boundary [%s], toboundary[%s]\n", 
438
  MPFDEB((stderr, "BINC: ParseMultipart: boundary [%s], toboundary[%s]\n", 
443
      boundary.c_str(),
439
      boundary.c_str(),
444
      toboundary.c_str()));
440
      toboundary.c_str()));
445
  using namespace ::Binc;
441
  using namespace ::Binc;
...
...
466
      MimePart m;
462
      MimePart m;
467
463
468
      // If parseFull returns != 0, then it encountered the multipart's
464
      // If parseFull returns != 0, then it encountered the multipart's
469
      // final boundary.
465
      // final boundary.
470
      int bsize = 0;
466
      int bsize = 0;
471
      if (m.doParseFull(boundary, bsize)) {
467
      if (m.doParseFull(mimeSource, boundary, bsize)) {
472
    quit = true;
468
    quit = true;
473
    *boundarysize = bsize;
469
    *boundarysize = bsize;
474
      }
470
      }
475
471
476
      members->push_back(m);
472
      members->push_back(m);
...
...
506
    *bodylength = 0;
502
    *bodylength = 0;
507
  }
503
  }
508
  MPFDEB((stderr, "BINC: ParseMultipart return\n"));
504
  MPFDEB((stderr, "BINC: ParseMultipart return\n"));
509
}
505
}
510
506
511
static void parseSinglePart(const string &toboundary,
507
void Binc::MimePart::parseSinglePart(const string &toboundary,
512
                int *boundarysize,
508
                int *boundarysize,
513
                unsigned int *nbodylines,
509
                unsigned int *nbodylines,
514
                unsigned int *nlines,
510
                unsigned int *nlines,
515
                bool *eof, bool *foundendofpart,
511
                bool *eof, bool *foundendofpart,
516
                unsigned int *bodylength)
512
                unsigned int *bodylength)
...
...
589
  MPFDEB((stderr, "BINC: parseSimple ret: bodylength %d, boundarysize %d\n",
585
  MPFDEB((stderr, "BINC: parseSimple ret: bodylength %d, boundarysize %d\n",
590
      *bodylength, *boundarysize));
586
      *bodylength, *boundarysize));
591
}
587
}
592
588
593
//------------------------------------------------------------------------
589
//------------------------------------------------------------------------
594
int Binc::MimePart::doParseFull(const string &toboundary,
590
int Binc::MimePart::doParseFull(MimeInputSource *ms, const string &toboundary,
595
                  int &boundarysize) const
591
              int &boundarysize)
596
{
592
{
597
  MPFDEB((stderr, "BINC: doParsefull, toboundary[%s]\n", toboundary.c_str()));
593
  MPFDEB((stderr, "BINC: doParsefull, toboundary[%s]\n", toboundary.c_str()));
594
  mimeSource = ms;
598
  headerstartoffsetcrlf = mimeSource->getOffset();
595
  headerstartoffsetcrlf = mimeSource->getOffset();
599
596
600
  // Parse the header of this mime part.
597
  // Parse the header of this mime part.
601
  parseHeader(&h, &nlines);
598
  parseHeader(&h, &nlines);
602
599
603
  // Headerlength includes the seperating CRLF. Body starts after the
600
  // Headerlength includes the seperating CRLF. Body starts after the
604
  // CRLF.
601
  // CRLF.
605
  headerlength = mimeSource->getOffset() - headerstartoffsetcrlf;
602
  headerlength = mimeSource->getOffset() - headerstartoffsetcrlf;
606
  bodystartoffsetcrlf = mimeSource->getOffset();
603
  bodystartoffsetcrlf = mimeSource->getOffset();
604
  MPFDEB((stderr, "BINC: doParsefull, bodystartoffsetcrlf %d\n", bodystartoffsetcrlf));
607
  bodylength = 0;
605
  bodylength = 0;
608
606
609
  // Determine the type of mime part by looking at fields in the
607
  // Determine the type of mime part by looking at fields in the
610
  // header.
608
  // header.
611
  analyzeHeader(&h, &multipart, &messagerfc822, &subtype, &boundary);
609
  analyzeHeader(&h, &multipart, &messagerfc822, &subtype, &boundary);