~olivier-chatelain/php-addressbook/trunk

« back to all changes in this revision

Viewing changes to z-push/backend/maildir.php

  • Committer: chatelao
  • Date: 2016-09-11 07:59:37 UTC
  • Revision ID: git-v1:03926e44d99a04a3b05d4761e322a1f5e8a405d7
Chg: Upgrade z-push from 2.0.3 to 2.2.12 (stable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
/***********************************************
3
 
* File      :   maildir.php
4
 
* Project   :   Z-Push
5
 
* Descr     :   This backend is based on
6
 
*               'BackendDiff' which handles the
7
 
*               intricacies of generating
8
 
*               differentials from static
9
 
*               snapshots. This means that the
10
 
*               implementation here needs no
11
 
*               state information, and can simply
12
 
*               return the current state of the
13
 
*               messages. The diffbackend will
14
 
*               then compare the current state
15
 
*               to the known last state of the PDA
16
 
*               and generate change increments
17
 
*               from that.
18
 
*
19
 
* Created   :   01.10.2007
20
 
*
21
 
* Copyright 2007 - 2012 Zarafa Deutschland GmbH
22
 
*
23
 
* This program is free software: you can redistribute it and/or modify
24
 
* it under the terms of the GNU Affero General Public License, version 3,
25
 
* as published by the Free Software Foundation with the following additional
26
 
* term according to sec. 7:
27
 
*
28
 
* According to sec. 7 of the GNU Affero General Public License, version 3,
29
 
* the terms of the AGPL are supplemented with the following terms:
30
 
*
31
 
* "Zarafa" is a registered trademark of Zarafa B.V.
32
 
* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
33
 
* The licensing of the Program under the AGPL does not imply a trademark license.
34
 
* Therefore any rights, title and interest in our trademarks remain entirely with us.
35
 
*
36
 
* However, if you propagate an unmodified version of the Program you are
37
 
* allowed to use the term "Z-Push" to indicate that you distribute the Program.
38
 
* Furthermore you may use our trademarks where it is necessary to indicate
39
 
* the intended purpose of a product or service provided you use it in accordance
40
 
* with honest practices in industrial or commercial matters.
41
 
* If you want to propagate modified versions of the Program under the name "Z-Push",
42
 
* you may only do so if you have a written permission by Zarafa Deutschland GmbH
43
 
* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
44
 
*
45
 
* This program is distributed in the hope that it will be useful,
46
 
* but WITHOUT ANY WARRANTY; without even the implied warranty of
47
 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48
 
* GNU Affero General Public License for more details.
49
 
*
50
 
* You should have received a copy of the GNU Affero General Public License
51
 
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
52
 
*
53
 
* Consult LICENSE file for details
54
 
************************************************/
55
 
 
56
 
include_once('lib/default/diffbackend/diffbackend.php');
57
 
include_once('include/mimeDecode.php');
58
 
require_once('include/z_RFC822.php');
59
 
 
60
 
class BackendMaildir extends BackendDiff {
61
 
    /**----------------------------------------------------------------------------------------------------------
62
 
     * default backend methods
63
 
     */
64
 
 
65
 
    /**
66
 
     * Authenticates the user - NOT EFFECTIVELY IMPLEMENTED
67
 
     * Normally some kind of password check would be done here.
68
 
     * Alternatively, the password could be ignored and an Apache
69
 
     * authentication via mod_auth_* could be done
70
 
     *
71
 
     * @param string        $username
72
 
     * @param string        $domain
73
 
     * @param string        $password
74
 
     *
75
 
     * @access public
76
 
     * @return boolean
77
 
     */
78
 
    public function Logon($username, $domain, $password) {
79
 
        return true;
80
 
    }
81
 
 
82
 
    /**
83
 
     * Logs off
84
 
     *
85
 
     * @access public
86
 
     * @return boolean
87
 
     */
88
 
    public function Logoff() {
89
 
        return true;
90
 
    }
91
 
 
92
 
    /**
93
 
     * Sends an e-mail
94
 
     * Not implemented here
95
 
     *
96
 
     * @param SyncSendMail  $sm     SyncSendMail object
97
 
     *
98
 
     * @access public
99
 
     * @return boolean
100
 
     * @throws StatusException
101
 
     */
102
 
    public function SendMail($sm) {
103
 
        return false;
104
 
    }
105
 
 
106
 
    /**
107
 
     * Returns the waste basket
108
 
     *
109
 
     * @access public
110
 
     * @return string
111
 
     */
112
 
    public function GetWasteBasket() {
113
 
        return false;
114
 
    }
115
 
 
116
 
    /**
117
 
     * Returns the content of the named attachment as stream. The passed attachment identifier is
118
 
     * the exact string that is returned in the 'AttName' property of an SyncAttachment.
119
 
     * Any information necessary to find the attachment must be encoded in that 'attname' property.
120
 
     * Data is written directly (with print $data;)
121
 
     *
122
 
     * @param string        $attname
123
 
     *
124
 
     * @access public
125
 
     * @return SyncItemOperationsAttachment
126
 
     * @throws StatusException
127
 
     */
128
 
    public function GetAttachmentData($attname) {
129
 
        list($id, $part) = explode(":", $attname);
130
 
 
131
 
        $fn = $this->findMessage($id);
132
 
        if ($fn == false)
133
 
            throw new StatusException(sprintf("BackendMaildir->GetAttachmentData('%s'): Error, requested message/attachment can not be found", $attname), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);
134
 
 
135
 
        // Parse e-mail
136
 
        $rfc822 = file_get_contents($this->getPath() . "/$fn");
137
 
 
138
 
        $message = Mail_mimeDecode::decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\n", 'charset' => 'utf-8'));
139
 
 
140
 
        include_once('include/stringstreamwrapper.php');
141
 
        $attachment = new SyncItemOperationsAttachment();
142
 
        $attachment->data = StringStreamWrapper::Open($message->parts[$part]->body);
143
 
        if (isset($message->parts[$part]->ctype_primary) && isset($message->parts[$part]->ctype_secondary))
144
 
            $attachment->contenttype = $message->parts[$part]->ctype_primary .'/'.$message->parts[$part]->ctype_secondary;
145
 
 
146
 
        return $attachment;
147
 
    }
148
 
 
149
 
    /**----------------------------------------------------------------------------------------------------------
150
 
     * implemented DiffBackend methods
151
 
     */
152
 
 
153
 
 
154
 
    /**
155
 
     * Returns a list (array) of folders.
156
 
     * In simple implementations like this one, probably just one folder is returned.
157
 
     *
158
 
     * @access public
159
 
     * @return array
160
 
     */
161
 
    public function GetFolderList() {
162
 
        $folders = array();
163
 
 
164
 
        $inbox = array();
165
 
        $inbox["id"] = "root";
166
 
        $inbox["parent"] = "0";
167
 
        $inbox["mod"] = "Inbox";
168
 
 
169
 
        $folders[]=$inbox;
170
 
 
171
 
        $sub = array();
172
 
        $sub["id"] = "sub";
173
 
        $sub["parent"] = "root";
174
 
        $sub["mod"] = "Sub";
175
 
 
176
 
//        $folders[]=$sub;
177
 
 
178
 
        return $folders;
179
 
    }
180
 
 
181
 
    /**
182
 
     * Returns an actual SyncFolder object
183
 
     *
184
 
     * @param string        $id           id of the folder
185
 
     *
186
 
     * @access public
187
 
     * @return object       SyncFolder with information
188
 
     */
189
 
    public function GetFolder($id) {
190
 
        if($id == "root") {
191
 
            $inbox = new SyncFolder();
192
 
 
193
 
            $inbox->serverid = $id;
194
 
            $inbox->parentid = "0"; // Root
195
 
            $inbox->displayname = "Inbox";
196
 
            $inbox->type = SYNC_FOLDER_TYPE_INBOX;
197
 
 
198
 
            return $inbox;
199
 
        } else if($id == "sub") {
200
 
            $inbox = new SyncFolder();
201
 
            $inbox->serverid = $id;
202
 
            $inbox->parentid = "root";
203
 
            $inbox->displayname = "Sub";
204
 
            $inbox->type = SYNC_FOLDER_TYPE_OTHER;
205
 
 
206
 
            return $inbox;
207
 
        } else {
208
 
            return false;
209
 
        }
210
 
    }
211
 
 
212
 
 
213
 
    /**
214
 
     * Returns folder stats. An associative array with properties is expected.
215
 
     *
216
 
     * @param string        $id             id of the folder
217
 
     *
218
 
     * @access public
219
 
     * @return array
220
 
     */
221
 
    public function StatFolder($id) {
222
 
        $folder = $this->GetFolder($id);
223
 
 
224
 
        $stat = array();
225
 
        $stat["id"] = $id;
226
 
        $stat["parent"] = $folder->parentid;
227
 
        $stat["mod"] = $folder->displayname;
228
 
 
229
 
        return $stat;
230
 
    }
231
 
 
232
 
 
233
 
    /**
234
 
     * Creates or modifies a folder
235
 
     * not implemented
236
 
     *
237
 
     * @param string        $folderid       id of the parent folder
238
 
     * @param string        $oldid          if empty -> new folder created, else folder is to be renamed
239
 
     * @param string        $displayname    new folder name (to be created, or to be renamed to)
240
 
     * @param int           $type           folder type
241
 
     *
242
 
     * @access public
243
 
     * @return boolean                      status
244
 
     * @throws StatusException              could throw specific SYNC_FSSTATUS_* exceptions
245
 
     *
246
 
     */
247
 
    public function ChangeFolder($folderid, $oldid, $displayname, $type){
248
 
        return false;
249
 
    }
250
 
 
251
 
    /**
252
 
     * Deletes a folder
253
 
     *
254
 
     * @param string        $id
255
 
     * @param string        $parent         is normally false
256
 
     *
257
 
     * @access public
258
 
     * @return boolean                      status - false if e.g. does not exist
259
 
     * @throws StatusException              could throw specific SYNC_FSSTATUS_* exceptions
260
 
     *
261
 
     */
262
 
    public function DeleteFolder($id, $parentid){
263
 
        return false;
264
 
    }
265
 
 
266
 
    /**
267
 
     * Returns a list (array) of messages
268
 
     *
269
 
     * @param string        $folderid       id of the parent folder
270
 
     * @param long          $cutoffdate     timestamp in the past from which on messages should be returned
271
 
     *
272
 
     * @access public
273
 
     * @return array/false  array with messages or false if folder is not available
274
 
     */
275
 
    public function GetMessageList($folderid, $cutoffdate) {
276
 
        $this->moveNewToCur();
277
 
 
278
 
        if($folderid != "root")
279
 
            return false;
280
 
 
281
 
        // return stats of all messages in a dir. We can do this faster than
282
 
        // just calling statMessage() on each message; We still need fstat()
283
 
        // information though, so listing 10000 messages is going to be
284
 
        // rather slow (depending on filesystem, etc)
285
 
 
286
 
        // we also have to filter by the specified cutoffdate so only the
287
 
        // last X days are retrieved. Normally, this would mean that we'd
288
 
        // have to open each message, get the Received: header, and check
289
 
        // whether that is in the filter range. Because this is much too slow, we
290
 
        // are depending on the creation date of the message instead, which should
291
 
        // normally be just about the same, unless you just did some kind of import.
292
 
 
293
 
        $messages = array();
294
 
        $dirname = $this->getPath();
295
 
 
296
 
        $dir = opendir($dirname);
297
 
 
298
 
        if(!$dir)
299
 
            return false;
300
 
 
301
 
        while($entry = readdir($dir)) {
302
 
            if($entry{0} == ".")
303
 
                continue;
304
 
 
305
 
            $message = array();
306
 
 
307
 
            $stat = stat("$dirname/$entry");
308
 
 
309
 
            if($stat["mtime"] < $cutoffdate) {
310
 
                // message is out of range for curoffdate, ignore it
311
 
                continue;
312
 
            }
313
 
 
314
 
            $message["mod"] = $stat["mtime"];
315
 
 
316
 
            $matches = array();
317
 
 
318
 
            // Flags according to http://cr.yp.to/proto/maildir.html (pretty authoritative - qmail author's website)
319
 
            if(!preg_match("/([^:]+):2,([PRSTDF]*)/",$entry,$matches))
320
 
                continue;
321
 
            $message["id"] = $matches[1];
322
 
            $message["flags"] = 0;
323
 
 
324
 
            if(strpos($matches[2],"S") !== false) {
325
 
                $message["flags"] |= 1; // 'seen' aka 'read' is the only flag we want to know about
326
 
            }
327
 
 
328
 
            array_push($messages, $message);
329
 
        }
330
 
 
331
 
        return $messages;
332
 
    }
333
 
 
334
 
    /**
335
 
     * Returns the actual SyncXXX object type.
336
 
     *
337
 
     * @param string            $folderid           id of the parent folder
338
 
     * @param string            $id                 id of the message
339
 
     * @param ContentParameters $contentparameters  parameters of the requested message (truncation, mimesupport etc)
340
 
     *
341
 
     * @access public
342
 
     * @return object/false     false if the message could not be retrieved
343
 
     */
344
 
    public function GetMessage($folderid, $id, $truncsize, $mimesupport = 0) {
345
 
        if($folderid != 'root')
346
 
            return false;
347
 
 
348
 
        $fn = $this->findMessage($id);
349
 
 
350
 
        // Get flags, etc
351
 
        $stat = $this->StatMessage($folderid, $id);
352
 
 
353
 
        // Parse e-mail
354
 
        $rfc822 = file_get_contents($this->getPath() . "/" . $fn);
355
 
 
356
 
        $message = Mail_mimeDecode::decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\n", 'charset' => 'utf-8'));
357
 
 
358
 
        $output = new SyncMail();
359
 
 
360
 
        $output->body = str_replace("\n", "\r\n", $this->getBody($message));
361
 
        $output->bodysize = strlen($output->body);
362
 
        $output->bodytruncated = 0; // We don't implement truncation in this backend
363
 
        $output->datereceived = $this->parseReceivedDate($message->headers["received"][0]);
364
 
        $output->messageclass = "IPM.Note";
365
 
        $output->subject = $message->headers["subject"];
366
 
        $output->read = $stat["flags"];
367
 
        $output->from = $message->headers["from"];
368
 
 
369
 
        $Mail_RFC822 = new Mail_RFC822();
370
 
        $toaddr = $ccaddr = $replytoaddr = array();
371
 
        if(isset($message->headers["to"]))
372
 
            $toaddr = $Mail_RFC822->parseAddressList($message->headers["to"]);
373
 
        if(isset($message->headers["cc"]))
374
 
            $ccaddr = $Mail_RFC822->parseAddressList($message->headers["cc"]);
375
 
        if(isset($message->headers["reply_to"]))
376
 
            $replytoaddr = $Mail_RFC822->parseAddressList($message->headers["reply_to"]);
377
 
 
378
 
        $output->to = array();
379
 
        $output->cc = array();
380
 
        $output->reply_to = array();
381
 
        foreach(array("to" => $toaddr, "cc" => $ccaddr, "reply_to" => $replytoaddr) as $type => $addrlist) {
382
 
            foreach($addrlist as $addr) {
383
 
                $address = $addr->mailbox . "@" . $addr->host;
384
 
                $name = $addr->personal;
385
 
 
386
 
                if (!isset($output->displayto) && $name != "")
387
 
                    $output->displayto = $name;
388
 
 
389
 
                if($name == "" || $name == $address)
390
 
                    $fulladdr = w2u($address);
391
 
                else {
392
 
                    if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') {
393
 
                        $fulladdr = "\"" . w2u($name) ."\" <" . w2u($address) . ">";
394
 
                    }
395
 
                    else {
396
 
                        $fulladdr = w2u($name) ." <" . w2u($address) . ">";
397
 
                    }
398
 
                }
399
 
 
400
 
                array_push($output->$type, $fulladdr);
401
 
            }
402
 
        }
403
 
 
404
 
        // convert mime-importance to AS-importance
405
 
        if (isset($message->headers["x-priority"])) {
406
 
            $mimeImportance =  preg_replace("/\D+/", "", $message->headers["x-priority"]);
407
 
            if ($mimeImportance > 3)
408
 
                $output->importance = 0;
409
 
            if ($mimeImportance == 3)
410
 
                $output->importance = 1;
411
 
            if ($mimeImportance < 3)
412
 
                $output->importance = 2;
413
 
        }
414
 
 
415
 
        // Attachments are only searched in the top-level part
416
 
        $n = 0;
417
 
        if(isset($message->parts)) {
418
 
            foreach($message->parts as $part) {
419
 
                if($part->ctype_primary == "application") {
420
 
                    $attachment = new SyncAttachment();
421
 
                    $attachment->attsize = strlen($part->body);
422
 
 
423
 
                    if(isset($part->d_parameters['filename']))
424
 
                        $attname = $part->d_parameters['filename'];
425
 
                    else if(isset($part->ctype_parameters['name']))
426
 
                        $attname = $part->ctype_parameters['name'];
427
 
                    else if(isset($part->headers['content-description']))
428
 
                        $attname = $part->headers['content-description'];
429
 
                    else $attname = "unknown attachment";
430
 
 
431
 
                    $attachment->displayname = $attname;
432
 
                    $attachment->attname = $id . ":" . $n;
433
 
                    $attachment->attmethod = 1;
434
 
                    $attachment->attoid = isset($part->headers['content-id']) ? $part->headers['content-id'] : "";
435
 
 
436
 
                    array_push($output->attachments, $attachment);
437
 
                }
438
 
                $n++;
439
 
            }
440
 
        }
441
 
 
442
 
        return $output;
443
 
    }
444
 
 
445
 
    /**
446
 
     * Returns message stats, analogous to the folder stats from StatFolder().
447
 
     *
448
 
     * @param string        $folderid       id of the folder
449
 
     * @param string        $id             id of the message
450
 
     *
451
 
     * @access public
452
 
     * @return array
453
 
     */
454
 
    public function StatMessage($folderid, $id) {
455
 
        $dirname = $this->getPath();
456
 
        $fn = $this->findMessage($id);
457
 
        if(!$fn)
458
 
            return false;
459
 
 
460
 
        $stat = stat("$dirname/$fn");
461
 
 
462
 
        $entry = array();
463
 
        $entry["id"] = $id;
464
 
        $entry["flags"] = 0;
465
 
 
466
 
        if(strpos($fn,"S"))
467
 
            $entry["flags"] |= 1;
468
 
        $entry["mod"] = $stat["mtime"];
469
 
 
470
 
        return $entry;
471
 
    }
472
 
 
473
 
    /**
474
 
     * Called when a message has been changed on the mobile.
475
 
     * This functionality is not available for emails.
476
 
     *
477
 
     * @param string        $folderid       id of the folder
478
 
     * @param string        $id             id of the message
479
 
     * @param SyncXXX       $message        the SyncObject containing a message
480
 
     *
481
 
     * @access public
482
 
     * @return array                        same return value as StatMessage()
483
 
     * @throws StatusException              could throw specific SYNC_STATUS_* exceptions
484
 
     */
485
 
    public function ChangeMessage($folderid, $id, $message) {
486
 
        return false;
487
 
    }
488
 
 
489
 
    /**
490
 
     * Changes the 'read' flag of a message on disk
491
 
     *
492
 
     * @param string        $folderid       id of the folder
493
 
     * @param string        $id             id of the message
494
 
     * @param int           $flags          read flag of the message
495
 
     *
496
 
     * @access public
497
 
     * @return boolean                      status of the operation
498
 
     * @throws StatusException              could throw specific SYNC_STATUS_* exceptions
499
 
     */
500
 
    public function SetReadFlag($folderid, $id, $flags) {
501
 
        if($folderid != 'root')
502
 
            return false;
503
 
 
504
 
        $fn = $this->findMessage($id);
505
 
 
506
 
        if(!$fn)
507
 
            return true; // message may have been deleted
508
 
 
509
 
        if(!preg_match("/([^:]+):2,([PRSTDF]*)/",$fn,$matches))
510
 
            return false;
511
 
 
512
 
        // remove 'seen' (S) flag
513
 
        if(!$flags) {
514
 
            $newflags = str_replace("S","",$matches[2]);
515
 
        } else {
516
 
            // make sure we don't double add the 'S' flag
517
 
            $newflags = str_replace("S","",$matches[2]) . "S";
518
 
        }
519
 
 
520
 
        $newfn = $matches[1] . ":2," . $newflags;
521
 
        // rename if required
522
 
        if($fn != $newfn)
523
 
            rename($this->getPath() ."/$fn", $this->getPath() . "/$newfn");
524
 
 
525
 
        return true;
526
 
    }
527
 
 
528
 
    /**
529
 
     * Called when the user has requested to delete (really delete) a message
530
 
     *
531
 
     * @param string        $folderid       id of the folder
532
 
     * @param string        $id             id of the message
533
 
     *
534
 
     * @access public
535
 
     * @return boolean                      status of the operation
536
 
     * @throws StatusException              could throw specific SYNC_STATUS_* exceptions
537
 
     */
538
 
    public function DeleteMessage($folderid, $id) {
539
 
        if($folderid != 'root')
540
 
            return false;
541
 
 
542
 
        $fn = $this->findMessage($id);
543
 
 
544
 
        if(!$fn)
545
 
            return true; // success because message has been deleted already
546
 
 
547
 
        if(!unlink($this->getPath() . "/$fn")) {
548
 
            return true; // success - message may have been deleted in the mean time (since findMessage)
549
 
        }
550
 
 
551
 
        return true;
552
 
    }
553
 
 
554
 
    /**
555
 
     * Called when the user moves an item on the PDA from one folder to another
556
 
     * not implemented
557
 
     *
558
 
     * @param string        $folderid       id of the source folder
559
 
     * @param string        $id             id of the message
560
 
     * @param string        $newfolderid    id of the destination folder
561
 
     *
562
 
     * @access public
563
 
     * @return boolean                      status of the operation
564
 
     * @throws StatusException              could throw specific SYNC_MOVEITEMSSTATUS_* exceptions
565
 
     */
566
 
    public function MoveMessage($folderid, $id, $newfolderid) {
567
 
        return false;
568
 
    }
569
 
 
570
 
 
571
 
    /**----------------------------------------------------------------------------------------------------------
572
 
     * private maildir-specific internals
573
 
     */
574
 
 
575
 
    /**
576
 
     * Searches for the message
577
 
     *
578
 
     * @param string        $id        id of the message
579
 
     *
580
 
     * @access private
581
 
     * @return string
582
 
     */
583
 
    private function findMessage($id) {
584
 
        // We could use 'this->folderid' for path info but we currently
585
 
        // only support a single INBOX. We also have to use a glob '*'
586
 
        // because we don't know the flags of the message we're looking for.
587
 
 
588
 
        $dirname = $this->getPath();
589
 
        $dir = opendir($dirname);
590
 
 
591
 
        while($entry = readdir($dir)) {
592
 
            if(strpos($entry,$id) === 0)
593
 
                return $entry;
594
 
        }
595
 
        return false; // not found
596
 
    }
597
 
 
598
 
    /**
599
 
     * Parses the message and return only the plaintext body
600
 
     *
601
 
     * @param string        $message        html message
602
 
     *
603
 
     * @access private
604
 
     * @return string       plaintext message
605
 
     */
606
 
    private function getBody($message) {
607
 
        $body = "";
608
 
        $htmlbody = "";
609
 
 
610
 
        $this->getBodyRecursive($message, "plain", $body);
611
 
 
612
 
        if(!isset($body) || $body === "") {
613
 
            $this->getBodyRecursive($message, "html", $body);
614
 
            // remove css-style tags
615
 
            $body = preg_replace("/<style.*?<\/style>/is", "", $body);
616
 
            // remove all other html
617
 
            $body = strip_tags($body);
618
 
        }
619
 
 
620
 
        return $body;
621
 
    }
622
 
 
623
 
    /**
624
 
     * Get all parts in the message with specified type and concatenate them together, unless the
625
 
     * Content-Disposition is 'attachment', in which case the text is apparently an attachment
626
 
     *
627
 
     * @param string        $message        mimedecode message(part)
628
 
     * @param string        $message        message subtype
629
 
     * @param string        &$body          body reference
630
 
     *
631
 
     * @access private
632
 
     * @return
633
 
     */
634
 
    private function getBodyRecursive($message, $subtype, &$body) {
635
 
        if(!isset($message->ctype_primary)) return;
636
 
        if(strcasecmp($message->ctype_primary,"text")==0 && strcasecmp($message->ctype_secondary,$subtype)==0 && isset($message->body))
637
 
            $body .= $message->body;
638
 
 
639
 
        if(strcasecmp($message->ctype_primary,"multipart")==0 && isset($message->parts) && is_array($message->parts)) {
640
 
            foreach($message->parts as $part) {
641
 
                if(!isset($part->disposition) || strcasecmp($part->disposition,"attachment"))  {
642
 
                    $this->getBodyRecursive($part, $subtype, $body);
643
 
                }
644
 
            }
645
 
        }
646
 
    }
647
 
 
648
 
    /**
649
 
     * Parses the received date
650
 
     *
651
 
     * @param string        $received        received date string
652
 
     *
653
 
     * @access private
654
 
     * @return long
655
 
     */
656
 
    private function parseReceivedDate($received) {
657
 
        $pos = strpos($received, ";");
658
 
        if(!$pos)
659
 
            return false;
660
 
 
661
 
        $datestr = substr($received, $pos+1);
662
 
        $datestr = ltrim($datestr);
663
 
 
664
 
        return strtotime($datestr);
665
 
    }
666
 
 
667
 
    /**
668
 
     * Moves everything in Maildir/new/* to Maildir/cur/
669
 
     *
670
 
     * @access private
671
 
     * @return
672
 
     */
673
 
    private function moveNewToCur() {
674
 
        $newdirname = MAILDIR_BASE . "/" . $this->store . "/" . MAILDIR_SUBDIR . "/new";
675
 
 
676
 
        $newdir = opendir($newdirname);
677
 
 
678
 
        while($newentry = readdir($newdir)) {
679
 
            if($newentry{0} == ".")
680
 
                continue;
681
 
 
682
 
            // link/unlink == move. This is the way to move the message according to cr.yp.to
683
 
            link($newdirname . "/" . $newentry, $this->getPath() . "/" . $newentry . ":2,");
684
 
            unlink($newdirname . "/" . $newentry);
685
 
        }
686
 
    }
687
 
 
688
 
    /**
689
 
     * The path we're working on
690
 
     *
691
 
     * @access private
692
 
     * @return string
693
 
     */
694
 
    private function getPath() {
695
 
        return MAILDIR_BASE . "/" . $this->store . "/" . MAILDIR_SUBDIR . "/cur";
696
 
    }
697
 
}
698
 
 
699
 
?>
 
 
b'\\ No newline at end of file'