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