1 /* -*- mode:c++;c-basic-offset:2 -*- */
2 /*  --------------------------------------------------------------------
3  *  Filename:
4  *    mime-parseonlyheader.cc
5  *
6  *  Description:
7  *    Implementation of main mime parser components
8  *  --------------------------------------------------------------------
9  *  Copyright 2002-2005 Andreas Aardal Hanssen
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *  --------------------------------------------------------------------
25  */
26 #include "autoconfig.h"
27 
28 #include "mime.h"
29 #include "mime-utils.h"
30 #include "mime-inputsource.h"
31 #include "convert.h"
32 #include <string>
33 #include <vector>
34 #include <map>
35 #include <exception>
36 #include <iostream>
37 
38 #include <string.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <errno.h>
42 
43 using namespace std;
44 
45 //------------------------------------------------------------------------
parseOnlyHeader(int fd)46 void Binc::MimeDocument::parseOnlyHeader(int fd)
47 {
48   if (allIsParsed || headerIsParsed)
49     return;
50 
51   headerIsParsed = true;
52 
53   delete doc_mimeSource;
54   doc_mimeSource = new MimeInputSource(fd);
55 
56   headerstartoffsetcrlf = 0;
57   headerlength = 0;
58   bodystartoffsetcrlf = 0;
59   bodylength = 0;
60   messagerfc822 = false;
61   multipart = false;
62 
63   nlines = 0;
64   nbodylines = 0;
65 
66   doParseOnlyHeader(doc_mimeSource);
67 }
68 
parseOnlyHeader(istream & s)69 void Binc::MimeDocument::parseOnlyHeader(istream& s)
70 {
71   if (allIsParsed || headerIsParsed)
72     return;
73 
74   headerIsParsed = true;
75 
76   delete doc_mimeSource;
77   doc_mimeSource = new MimeInputSourceStream(s);
78 
79   headerstartoffsetcrlf = 0;
80   headerlength = 0;
81   bodystartoffsetcrlf = 0;
82   bodylength = 0;
83   messagerfc822 = false;
84   multipart = false;
85 
86   nlines = 0;
87   nbodylines = 0;
88 
89   doParseOnlyHeader(doc_mimeSource);
90 }
91 
92 //------------------------------------------------------------------------
doParseOnlyHeader(MimeInputSource * ms)93 int Binc::MimePart::doParseOnlyHeader(MimeInputSource *ms)
94 {
95   mimeSource = ms;
96   string name;
97   string content;
98   char cqueue[4];
99   memset(cqueue, 0, sizeof(cqueue));
100 
101   headerstartoffsetcrlf = mimeSource->getOffset();
102 
103   bool quit = false;
104   char c = '\0';
105 
106   while (!quit) {
107     // read name
108     while (1) {
109       if (!mimeSource->getChar(&c)) {
110     quit = true;
111     break;
112       }
113 
114       if (c == '\n') ++nlines;
115       if (c == ':') break;
116       if (c == '\n') {
117     for (int i = int(name.length()) - 1; i >= 0; --i)
118       mimeSource->ungetChar();
119 
120     quit = true;
121     name.clear();
122     break;
123       }
124 
125       name += c;
126 
127       if (name.length() == 2 && name.substr(0, 2) == "\r\n") {
128     name.clear();
129     quit = true;
130     break;
131       }
132     }
133 
134     if (name.length() == 1 && name[0] == '\r') {
135       name.clear();
136       break;
137     }
138 
139     if (quit) break;
140 
141     while (!quit) {
142       if (!mimeSource->getChar(&c)) {
143     quit = true;
144     break;
145       }
146 
147       if (c == '\n') ++nlines;
148 
149       for (int i = 0; i < 3; ++i)
150     cqueue[i] = cqueue[i + 1];
151       cqueue[3] = c;
152 
153       if (strncmp(cqueue, "\r\n\r\n", 4) == 0) {
154     quit = true;
155     break;
156       }
157 
158       if (cqueue[2] == '\n') {
159 
160     // guess the mime rfc says what can not appear on the beginning
161     // of a line.
162     if (!isspace(cqueue[3])) {
163       if (content.length() > 2)
164         content.resize(content.length() - 2);
165 
166       trim(content);
167       h.add(name, content);
168 
169       name = c;
170       content.clear();
171       break;
172     }
173       }
174 
175       content += c;
176     }
177   }
178 
179   if (name != "") {
180     if (content.length() > 2)
181       content.resize(content.length() - 2);
182     h.add(name, content);
183   }
184 
185   headerlength = mimeSource->getOffset() - headerstartoffsetcrlf;
186 
187   return 1;
188 }
189