Added search for "x-mailer" and "disposition notification to" and add it to
[squirrelmail.git] / functions / imap_parse.php
1 <?php
2
3 function sqimap_parse_RFC822Header ($read, $hdr) {
4 $i = 0;
5 /* Set up some defaults */
6 $hdr->type0 = "text";
7 $hdr->type1 = "plain";
8 $hdr->charset = "us-ascii";
9
10 $count = count($read);
11 while ($i < $count) {
12 /* unfold multi-line headers */
13 while (($i + 1 < $count) && (strspn($read[$i + 1], "\t ") > 0) ) {
14 $read[$i + 1] = substr($read[$i], 0, -2) . ' ' . ltrim($read[$i+1]);
15 array_splice($read, $i, 1);
16 $count--;
17 }
18 $line = $read[$i];
19 $c = strtolower($line{0});
20 switch ($c) {
21 case 'm':
22 $c2 = strtolower($line{1});
23 switch ($c2) {
24 case 'i':
25 if (substr($line, 0, 17) == "MIME-Version: 1.0") {
26 $hdr->mime = true;
27 }
28 $i++;
29 break;
30 case 'e':
31 /* MESSAGE ID */
32 if (strtolower(substr($line, 0, 11)) == "message-id:") {
33 $hdr->message_id = trim(substr($line, 11));
34 }
35 $i++;
36 break;
37 default:
38 $i++;
39 break;
40 }
41 break;
42 case 'c':
43 $c2 = strtolower($line{1});
44 switch ($c2) {
45 case 'o':
46 /* Content-Transfer-Encoding */
47 if (substr(strtolower($line), 0, 26) == "content-transfer-encoding:") {
48 $hdr->encoding = strtolower(trim(substr($line, 26)));
49 $i++;
50 }
51 /* Content-Type */
52 else if (strtolower(substr($line, 0, 13)) == "content-type:") {
53 $cont = strtolower(trim(substr($line, 13)));
54 if (strpos($cont, ";")) {
55 $cont = substr($cont, 0, strpos($cont, ";"));
56 }
57 if (strpos($cont, "/")) {
58 $hdr->type0 = substr($cont, 0, strpos($cont, "/"));
59 $hdr->type1 = substr($cont, strpos($cont, "/")+1);
60 } else {
61 $hdr->type0 = $cont;
62 }
63 $line = $read[$i];
64 $i++;
65 while ( (substr(substr($read[$i], 0, strpos($read[$i], " ")), -1) != ":") && (trim($read[$i]) != "") && (trim($read[$i]) != ")")) {
66 str_replace("\n", "", $line);
67 str_replace("\n", "", $read[$i]);
68 $line = "$line $read[$i]";
69 $i++;
70 }
71
72 /* Detect the boundary of a multipart message */
73 if (eregi('boundary="([^"]+)"', $line, $regs)) {
74 $hdr->boundary = $regs[1];
75 }
76
77 /* Detect the charset */
78 if (strpos(strtolower(trim($line)), "charset=")) {
79 $pos = strpos($line, "charset=") + 8;
80 $charset = trim($line);
81 if (strpos($line, ";", $pos) > 0) {
82 $charset = substr($charset, $pos, strpos($line, ";", $pos)-$pos);
83 } else {
84 $charset = substr($charset, $pos);
85 }
86 $charset = str_replace("\"", "", $charset);
87 $hdr->charset = $charset;
88 } else {
89 $hdr->charset = "us-ascii";
90 }
91 /* Detect type in case of multipart/related */
92 if (strpos(strtolower(trim($line)), "type=")) {
93 $pos = strpos($line, "type=") + 6;
94 $type = trim($line);
95 if (strpos($line, ";", $pos) > 0) {
96 $type = substr($type, $pos, strpos($line, ";", $pos)-$pos);
97 } else {
98 $type = substr($type, $pos);
99 }
100 $hdr->type = $type;
101 }
102 }
103 else if (strtolower(substr($line, 0, 20)) == "content-disposition:") {
104 /* Add better content-disposition support */
105 $i++;
106 while ( (substr(substr($read[$i], 0, strpos($read[$i], " ")), -1) != ":") && (trim($read[$i]) != "") && (trim($read[$i]) != ")")) {
107 str_replace("\n", "", $line);
108 str_replace("\n", "", $read[$i]);
109 $line = "$line $read[$i]";
110 $i++;
111 }
112
113 /* Detects filename if any */
114 if (strpos(strtolower(trim($line)), "filename=")) {
115 $pos = strpos($line, "filename=") + 9;
116 $name = trim($line);
117 if (strpos($line, " ", $pos) > 0) {
118 $name = substr($name, $pos, strpos($line, " ", $pos));
119 } else {
120 $name = substr($name, $pos);
121 }
122 $name = str_replace("\"", "", $name);
123 $hdr->filename = $name;
124 }
125 } else $i++;
126 break;
127 case 'c': /* Cc */
128 if (strtolower(substr($line, 0, 3)) == "cc:") {
129 $hdr->cc = sqimap_parse_address(trim(substr($line, 3, strlen($line) - 4)), true);
130 }
131 $i++;
132 break;
133 default:
134 $i++;
135 break;
136 }
137 break;
138 case 'r': /* Reply-To */
139 if (strtolower(substr($line, 0, 9)) == "reply-to:") {
140 $hdr->replyto = sqimap_parse_address(trim(substr($line, 9, strlen($line) - 10)), false);
141 }
142 $i++;
143 break;
144 case 'f': /* From */
145 if (strtolower(substr($line, 0, 5)) == "from:") {
146 $hdr->from=sqimap_parse_address(trim(substr($line, 5, strlen($line) - 6)), false);
147 if (! isset($hdr->replyto) || $hdr->replyto == "") {
148 $hdr->replyto = $hdr->from;
149 }
150 }
151 $i++;
152 break;
153 case 'd':
154 $c2 = strtolower($line{1});
155 switch ($c2) {
156 case 'a': /* Date */
157 if (strtolower(substr($line, 0, 5)) == "date:") {
158 $d = substr($read[$i], 5);
159 $d = trim($d);
160 $d = strtr($d, array(' ' => ' '));
161 $d = explode(' ', $d);
162 $hdr->date = getTimeStamp($d);
163 }
164 $i++;
165 break;
166 case 'i': /* Disposition-Notification-To */
167 if (strtolower(substr($line, 0, 28)) == "disposition-notification-to:") {
168 $dnt = trim(substr($read[$i], 28));
169 $hdr->dnt = sqimap_parse_address($dnt, false);
170 }
171 $i++;
172 break;
173 default:
174 $i++;
175 break;
176 }
177 break;
178 case 's':
179 /* SUBJECT */
180 if (strtolower(substr($line, 0, 8)) == "subject:") {
181 $hdr->subject = trim(substr($line, 8, strlen($line) - 9));
182 if (strlen(Chop($hdr->subject)) == 0) {
183 $hdr->subject = _("(no subject)");
184 }
185 }
186 $i++;
187 break;
188 case 'b':
189 /* BCC */
190 if (strtolower(substr($line, 0, 4)) == "bcc:") {
191 $hdr->bcc = sqimap_parse_address(trim(substr($line, 4, strlen($line) - 5)), true);
192 }
193 $i++;
194 break;
195 case 't':
196 /* TO */
197 if (strtolower(substr($line, 0, 3)) == "to:") {
198 $hdr->to = sqimap_parse_address(trim(substr($line, 3, strlen($line) - 4)), true);
199 }
200 $i++;
201 break;
202 case ')':
203 /* ERROR CORRECTION */
204 if (strlen(trim($hdr->subject)) == 0) {
205 $hdr->subject = _("(no subject)");
206 }
207 if (strlen(trim($hdr->from)) == 0) {
208 $hdr->from = _("(unknown sender)");
209 }
210 if (strlen(trim($hdr->date)) == 0) {
211 $hdr->date = time();
212 }
213 $i++;
214 break;
215 case 'x':
216 /* X-PRIORITY */
217 if (strtolower(substr($line, 0, 11)) == 'x-priority:') {
218 $hdr->priority = trim(substr($line, 11));
219 } else if (strtolower(substr($line,0,9)) == 'x-mailer:') {
220 $hdr->xmailer = trim(substr($line, 9));
221 }
222 $i++;
223 break;
224 default:
225 $i++;
226 break;
227 }
228 }
229 return $hdr;
230 }
231
232 /**
233 * function to process addresses.
234 */
235 function sqimap_parse_address($address, $ar, $addr_ar = array(), $group = '') {
236 $pos = 0;
237 $j = strlen( $address );
238 $name = '';
239 $addr = '';
240
241 while ( $pos < $j ) {
242 if ($address{$pos} == '"') { /* get the personal name */
243 $pos++;
244 while ( $address{$pos} != '"' &&
245 $pos < $j ) {
246 if (substr($address, $pos, 2) == '\\"') {
247 $name .= $address{$pos};
248 $pos++;
249 } elseif (substr($address, $pos, 2) == '\\\\') {
250 $name .= $address{$pos};
251 $pos++;
252 }
253 $name .= $address{$pos};
254 $pos++;
255 }
256 } elseif ($address{$pos} == '<') { /* get email address */
257 $addr_start=$pos;
258 $pos++;
259 while ( $address{$pos} != '>' &&
260 $pos < $j ) {
261 $addr .= $address{$pos};
262 $pos++;
263 }
264 } elseif ($address{$pos} == '(') { /* rip off comments */
265 $addr_start=$pos;
266 $pos++;
267 while ( $address{$pos} != ')' &&
268 $pos < $j ) {
269 $addr .= $address{$pos};
270 $pos++;
271 }
272 $address_start = substr($address,0,$addr_start);
273 $address_end = substr($address,$pos+1);
274 $address = $address_start . $address_end;
275 $j = strlen( $address );
276 $pos = $addr_start;
277 } elseif ( $address{$pos} == ',' ) { /* we reached a delimiter */
278 if ($addr == '') {
279 $addr = substr($address,0,$pos);
280 } elseif ($name == '') {
281 $name = substr($address,0,$addr_start);
282 }
283 $at = strpos($addr, '@');
284 $addr_structure = new address_structure();
285 $addr_structure->personal = $name;
286 $addr_structure->group = $group;
287
288 if ($at) {
289 $addr_structure->mailbox = substr($addr,0,$at);
290 $addr_structure->host = substr($addr,$at+1);
291 } else {
292 $addr_structure->mailbox = $addr;
293 }
294 $address = substr($address,$pos+1);
295 $j = strlen( $address );
296 $pos = 0;
297 $name = '';
298 $addr = '';
299 $addr_ar[] = $addr_structure;
300
301 } elseif ( $address{$pos} == ":" ) { /* process the group addresses */
302 /* group marker */
303 $group = substr($address,0,$pos);
304 $address = substr($address,$pos+1);
305 $result = sqimap_parse_address($address, $ar, $addr_ar, $group);
306 $addr_ar = $result[0];
307 $pos = $result[1];
308 $address = substr($address,$pos);
309 $j = strlen( $address );
310 $group = '';
311 } elseif ($address{$pos} == ';' && $group ) {
312 $address = substr($address, 0, $pos-1);
313 break;
314 }
315 $pos++;
316 }
317 if ($addr == '') {
318 $addr = substr($address,0,$pos);
319 } elseif ($name == '') {
320 $name = substr($address,0,$addr_start);
321 }
322 $at = strpos($addr, '@');
323 $addr_structure = new address_structure();
324 $addr_structure->group = $group;
325 if ($at) {
326 $addr_structure->mailbox = trim(substr($addr,0,$at));
327 $addr_structure->host = trim(substr($addr,$at+1));
328 } else {
329 $addr_structure->mailbox = trim($addr);
330 }
331
332 if ($group && $addr == '') { /* no addresses found in group */
333 $name = "$group: Undisclosed recipients;";
334 $addr_structure->personal = $name;
335 $addr_ar[] = $addr_structure;
336 return (array($addr_ar,$pos+1));
337 } else {
338 $addr_structure->personal = $name;
339 if ($name || $addr) {
340 $addr_ar[] = $addr_structure;
341 }
342 }
343 if ($ar) {
344 return ($addr_ar);
345 } else {
346 return ($addr_ar[0]);
347 }
348
349 }
350 ?>