29530c1b0e035247b0f1ae4cfc9ea3737e454806
[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 (!is_object($hdr->from) && 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 case 'u':
225 /* User-Agent */
226 if (strtolower(substr($line,0,10)) == 'user-agent') {
227 $hdr->xmailer = trim(substr($line, 10));
228 }
229 $i++;
230 break;
231 default:
232 $i++;
233 break;
234 }
235 }
236 return $hdr;
237 }
238
239 /**
240 * function to process addresses.
241 */
242 function sqimap_parse_address($address, $ar, $addr_ar = array(), $group = '') {
243 $pos = 0;
244 $j = strlen( $address );
245 $name = '';
246 $addr = '';
247
248 while ( $pos < $j ) {
249 if ($address{$pos} == '"') { /* get the personal name */
250 $pos++;
251 while ( $address{$pos} != '"' &&
252 $pos < $j ) {
253 if (substr($address, $pos, 2) == '\\"') {
254 $name .= $address{$pos};
255 $pos++;
256 } elseif (substr($address, $pos, 2) == '\\\\') {
257 $name .= $address{$pos};
258 $pos++;
259 }
260 $name .= $address{$pos};
261 $pos++;
262 }
263 } elseif ($address{$pos} == '<') { /* get email address */
264 $addr_start=$pos;
265 $pos++;
266 while ( $address{$pos} != '>' &&
267 $pos < $j ) {
268 $addr .= $address{$pos};
269 $pos++;
270 }
271 } elseif ($address{$pos} == '(') { /* rip off comments */
272 $addr_start=$pos;
273 $pos++;
274 while ( $address{$pos} != ')' &&
275 $pos < $j ) {
276 $addr .= $address{$pos};
277 $pos++;
278 }
279 $address_start = substr($address,0,$addr_start);
280 $address_end = substr($address,$pos+1);
281 $address = $address_start . $address_end;
282 $j = strlen( $address );
283 $pos = $addr_start;
284 } elseif ( $address{$pos} == ',' ) { /* we reached a delimiter */
285 if ($addr == '') {
286 $addr = substr($address,0,$pos);
287 } elseif ($name == '') {
288 $name = substr($address,0,$addr_start);
289 }
290 $at = strpos($addr, '@');
291 $addr_structure = new address_structure();
292 $addr_structure->personal = $name;
293 $addr_structure->group = $group;
294
295 if ($at) {
296 $addr_structure->mailbox = substr($addr,0,$at);
297 $addr_structure->host = substr($addr,$at+1);
298 } else {
299 $addr_structure->mailbox = $addr;
300 }
301 $address = substr($address,$pos+1);
302 $j = strlen( $address );
303 $pos = 0;
304 $name = '';
305 $addr = '';
306 $addr_ar[] = $addr_structure;
307
308 } elseif ( $address{$pos} == ":" ) { /* process the group addresses */
309 /* group marker */
310 $group = substr($address,0,$pos);
311 $address = substr($address,$pos+1);
312 $result = sqimap_parse_address($address, $ar, $addr_ar, $group);
313 $addr_ar = $result[0];
314 $pos = $result[1];
315 $address = substr($address,$pos);
316 $j = strlen( $address );
317 $group = '';
318 } elseif ($address{$pos} == ';' && $group ) {
319 $address = substr($address, 0, $pos-1);
320 break;
321 }
322 $pos++;
323 }
324 if ($addr == '') {
325 $addr = substr($address,0,$pos);
326 } elseif ($name == '') {
327 $name = substr($address,0,$addr_start);
328 }
329 $at = strpos($addr, '@');
330 $addr_structure = new address_structure();
331 $addr_structure->group = $group;
332 if ($at) {
333 $addr_structure->mailbox = trim(substr($addr,0,$at));
334 $addr_structure->host = trim(substr($addr,$at+1));
335 } else {
336 $addr_structure->mailbox = trim($addr);
337 }
338
339 if ($group && $addr == '') { /* no addresses found in group */
340 $name = "$group: Undisclosed recipients;";
341 $addr_structure->personal = $name;
342 $addr_ar[] = $addr_structure;
343 return (array($addr_ar,$pos+1));
344 } else {
345 $addr_structure->personal = $name;
346 if ($name || $addr) {
347 $addr_ar[] = $addr_structure;
348 }
349 }
350 if ($ar) {
351 return ($addr_ar);
352 } else {
353 return ($addr_ar[0]);
354 }
355
356 }
357 ?>