Overview

Packages

  • Kolab
    • Storage

Classes

  • Horde_Kolab_Storage_Base
  • Horde_Kolab_Storage_Cache
  • Horde_Kolab_Storage_Cache_Data
  • Horde_Kolab_Storage_Cache_List
  • Horde_Kolab_Storage_Cached
  • Horde_Kolab_Storage_Data_Base
  • Horde_Kolab_Storage_Data_Cached
  • Horde_Kolab_Storage_Data_Decorator_Log
  • Horde_Kolab_Storage_Data_Format_Mime
  • Horde_Kolab_Storage_Data_Modifiable
  • Horde_Kolab_Storage_Data_Old
  • Horde_Kolab_Storage_Data_Parser_Structure
  • Horde_Kolab_Storage_Data_Query_History_Base
  • Horde_Kolab_Storage_Data_Query_History_Cache
  • Horde_Kolab_Storage_Data_Query_Preferences_Base
  • Horde_Kolab_Storage_Data_Query_Preferences_Cache
  • Horde_Kolab_Storage_Decorator_Synchronization
  • Horde_Kolab_Storage_Driver_Base
  • Horde_Kolab_Storage_Driver_Cclient
  • Horde_Kolab_Storage_Driver_Decorator_Base
  • Horde_Kolab_Storage_Driver_Decorator_Log
  • Horde_Kolab_Storage_Driver_Decorator_Timer
  • Horde_Kolab_Storage_Driver_Imap
  • Horde_Kolab_Storage_Driver_Mock
  • Horde_Kolab_Storage_Driver_Mock_Data
  • Horde_Kolab_Storage_Driver_Pear
  • Horde_Kolab_Storage_Driver_Rcube
  • Horde_Kolab_Storage_Exception
  • Horde_Kolab_Storage_Exception_Pear
  • Horde_Kolab_Storage_Factory
  • Horde_Kolab_Storage_Folder_Base
  • Horde_Kolab_Storage_Folder_Decorator_Base
  • Horde_Kolab_Storage_Folder_Decorator_Trigger
  • Horde_Kolab_Storage_Folder_Namespace
  • Horde_Kolab_Storage_Folder_Namespace_Config
  • Horde_Kolab_Storage_Folder_Namespace_Element
  • Horde_Kolab_Storage_Folder_Namespace_Element_Other
  • Horde_Kolab_Storage_Folder_Namespace_Element_Personal
  • Horde_Kolab_Storage_Folder_Namespace_Element_Shared
  • Horde_Kolab_Storage_Folder_Namespace_Element_SharedWithPrefix
  • Horde_Kolab_Storage_Folder_Namespace_Fixed
  • Horde_Kolab_Storage_Folder_Namespace_Imap
  • Horde_Kolab_Storage_Folder_Stamp_Uids
  • Horde_Kolab_Storage_Folder_Type
  • Horde_Kolab_Storage_List_Base
  • Horde_Kolab_Storage_List_Decorator_Cache
  • Horde_Kolab_Storage_List_Decorator_Log
  • Horde_Kolab_Storage_List_Query_Acl_Base
  • Horde_Kolab_Storage_List_Query_Acl_Cache
  • Horde_Kolab_Storage_List_Query_ActiveSync_Base
  • Horde_Kolab_Storage_List_Query_ActiveSync_Cache
  • Horde_Kolab_Storage_List_Query_List_Base
  • Horde_Kolab_Storage_List_Query_List_Cache
  • Horde_Kolab_Storage_List_Query_Share_Base
  • Horde_Kolab_Storage_List_Query_Share_Cache
  • Horde_Kolab_Storage_QuerySet_Base
  • Horde_Kolab_Storage_QuerySet_Cached
  • Horde_Kolab_Storage_QuerySet_Uncached
  • Horde_Kolab_Storage_Synchronization
  • Horde_Kolab_Storage_Translation
  • Horde_Kolab_Storage_Uncached

Interfaces

  • Horde_Kolab_Storage
  • Horde_Kolab_Storage_Data
  • Horde_Kolab_Storage_Data_Format
  • Horde_Kolab_Storage_Data_Parser
  • Horde_Kolab_Storage_Data_Query
  • Horde_Kolab_Storage_Data_Query_History
  • Horde_Kolab_Storage_Data_Query_Preferences
  • Horde_Kolab_Storage_Driver
  • Horde_Kolab_Storage_Folder
  • Horde_Kolab_Storage_Folder_Stamp
  • Horde_Kolab_Storage_List
  • Horde_Kolab_Storage_List_Query
  • Horde_Kolab_Storage_List_Query_Acl
  • Horde_Kolab_Storage_List_Query_ActiveSync
  • Horde_Kolab_Storage_List_Query_List
  • Horde_Kolab_Storage_List_Query_Share
  • Horde_Kolab_Storage_Queriable
  • Horde_Kolab_Storage_Query
  • Horde_Kolab_Storage_QuerySet
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * An cclient based Kolab storage driver.
  4:  *
  5:  * PHP version 5
  6:  *
  7:  * @category Kolab
  8:  * @package  Kolab_Storage
  9:  * @author   Gunnar Wrobel <wrobel@pardus.de>
 10:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 11:  * @link     http://pear.horde.org/index.php?package=Kolab_Storage
 12:  */
 13: 
 14: /**
 15:  * An cclient based Kolab storage driver.
 16:  *
 17:  * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
 18:  *
 19:  * See the enclosed file COPYING for license information (LGPL). If you
 20:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 21:  *
 22:  * @category Kolab
 23:  * @package  Kolab_Storage
 24:  * @author   Gunnar Wrobel <wrobel@pardus.de>
 25:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 26:  * @link     http://pear.horde.org/index.php?package=Kolab_Storage
 27:  */
 28: class Horde_Kolab_Storage_Driver_Cclient
 29: extends Horde_Kolab_Storage_Driver_Base
 30: {
 31:     /**
 32:      * The c-client code -> MIME type conversion table.
 33:      *
 34:      * @var array
 35:      */
 36:     protected $_mimeTypes = array(
 37:         TYPETEXT => 'text',
 38:         TYPEMULTIPART => 'multipart',
 39:         TYPEMESSAGE => 'message',
 40:         TYPEAPPLICATION => 'application',
 41:         TYPEAUDIO => 'audio',
 42:         TYPEIMAGE => 'image',
 43:         TYPEVIDEO => 'video',
 44:         TYPEMODEL => 'model',
 45:         TYPEOTHER => 'other'
 46:     );
 47: 
 48:     /**
 49:      * The c-client code -> MIME encodings conversion table.
 50:      *
 51:      * @var array
 52:      */
 53:     protected $_mimeEncodings = array(
 54:         ENC7BIT => '7bit',
 55:         ENC8BIT => '8bit',
 56:         ENCBINARY => 'binary',
 57:         ENCBASE64 => 'base64',
 58:         ENCQUOTEDPRINTABLE => 'quoted-printable',
 59:         ENCOTHER => 'unknown'
 60:     );
 61: 
 62:     /**
 63:      * Server name.
 64:      *
 65:      * @var string
 66:      */
 67:     private $_host;
 68: 
 69:     /**
 70:      * Basic IMAP connection string.
 71:      *
 72:      * @var string
 73:      */
 74:     private $_base_mbox;
 75: 
 76:     /**
 77:      * The currently selected folder.
 78:      *
 79:      * @var string
 80:      */
 81:     private $_selected;
 82: 
 83:     /**
 84:      * Create the backend driver.
 85:      *
 86:      * @return mixed The backend driver.
 87:      */
 88:     public function createBackend()
 89:     {
 90:         if (!function_exists('imap_open')) {
 91:             throw new Horde_Kolab_Storage_Exception('The IMAP extension is not available!');
 92:         }
 93:         $result = @imap_open(
 94:             $this->_getBaseMbox(),
 95:             $this->getParam('username'),
 96:             $this->getParam('password'),
 97:             OP_HALFOPEN
 98:         );
 99:         if (!$result) {
100:             throw new Horde_Kolab_Storage_Exception(
101:                 sprintf(
102:                     Horde_Kolab_Storage_Translation::t(
103:                         "Connecting to server %s failed. Error: %s"
104:                     ),
105:                     $this->_getHost(),
106:                     imap_last_error()
107:                 )
108:             );
109:         }
110:         return $result;
111:     }
112: 
113:     /**
114:      * Return the root folder of the current user.
115:      *
116:      * @return string The id of the user that opened the IMAP connection.
117:      */
118:     private function _getBaseMbox()
119:     {
120:         if (!isset($this->_base_mbox)) {
121:             $this->_base_mbox = '{' . $this->_getHost()
122:                 . ':' . $this->getParam('port') . '/imap';
123:             $secure = $this->getParam('secure');
124:             if (!empty($secure)) {
125:                 $this->_base_mbox .= '/' . $secure . '/novalidate-cert';
126:             } else {
127:                 $this->_base_mbox .= '/notls';
128:             }
129:             $this->_base_mbox .= '}';
130:         }
131:         return $this->_base_mbox;
132:     }
133: 
134:     /**
135:      * Return the root folder of the current user.
136:      *
137:      * @return string The id of the user that opened the IMAP connection.
138:      */
139:     private function _getHost()
140:     {
141:         if (!isset($this->_host)) {
142:             $this->_host = $this->getParam('host');
143:             if (empty($this->_host)) {
144:                 throw new Horde_Kolab_Storage_Exception(
145:                     Horde_Kolab_Storage_Translation::t(
146:                         "Missing \"host\" parameter!"
147:                     )
148:                 );
149:             }
150:         }
151:         return $this->_host;
152:     }
153: 
154:     /**
155:      * Retrieves a list of folders on the server.
156:      *
157:      * @return array The list of folders.
158:      *
159:      * @throws Horde_Kolab_Storage_Exception In case listing the folders failed.
160:      */
161:     public function listFolders()
162:     {
163:         return $this->decodeList($this->_listFolders());
164:     }
165: 
166:     /**
167:      * Retrieves a UTF7-IMAP encoded list of folders on the server.
168:      *
169:      * @return array The list of folders.
170:      *
171:      * @throws Horde_Kolab_Storage_Exception In case listing the folders failed.
172:      */
173:     private function _listFolders()
174:     {
175:         $folders = array();
176: 
177:         $result = imap_list($this->getBackend(), $this->_getBaseMbox(), '*');
178:         if (!$result) {
179:             throw new Horde_Kolab_Storage_Exception(
180:                 sprintf(
181:                     Horde_Kolab_Storage_Translation::t(
182:                         "Listing folders for %s failed. Error: %s"
183:                     ),
184:                     $this->_getBaseMbox(),
185:                     imap_last_error()
186:                 )
187:             );
188:         }
189: 
190:         $root = $this->_getBaseMbox();
191:         $server_len = strlen($root);
192:         foreach ($result as $folder) {
193:             if (substr($folder, 0, $server_len) == $root) {
194:                 $folders[] = substr($folder, $server_len);
195:             }
196:         }
197: 
198:         return $folders;
199:     }
200: 
201:     /**
202:      * Create the specified folder.
203:      *
204:      * @param string $folder The folder to create.
205:      *
206:      * @return NULL
207:      */
208:     public function create($folder)
209:     {
210:         $result = imap_createmailbox(
211:             $this->getBackend(),
212:             $this->_getBaseMbox() . $this->encodePath($folder)
213:         );
214:         if (!$result) {
215:             throw new Horde_Kolab_Storage_Exception(
216:                 sprintf(
217:                     Horde_Kolab_Storage_Translation::t(
218:                         "Creating folder %s%s failed. Error: %s"
219:                     ),
220:                     $this->_getBaseMbox(),
221:                     $folder,
222:                     imap_last_error()
223:                 )
224:             );
225:         }
226:     }
227: 
228:     /**
229:      * Delete the specified folder.
230:      *
231:      * @param string $folder  The folder to delete.
232:      *
233:      * @return NULL
234:      */
235:     public function delete($folder)
236:     {
237:         $result = imap_deletemailbox(
238:             $this->getBackend(),
239:             $this->_getBaseMbox() . $this->encodePath($folder)
240:         );
241:         if (!$result) {
242:             throw new Horde_Kolab_Storage_Exception(
243:                 sprintf(
244:                     Horde_Kolab_Storage_Translation::t(
245:                         "Deleting folder %s%s failed. Error: %s"
246:                     ),
247:                     $this->_getBaseMbox(),
248:                     $folder,
249:                     imap_last_error()
250:                 )
251:             );
252:         }
253:     }
254: 
255:     /**
256:      * Rename the specified folder.
257:      *
258:      * @param string $old  The folder to rename.
259:      * @param string $new  The new name of the folder.
260:      *
261:      * @return NULL
262:      */
263:     public function rename($old, $new)
264:     {
265:         $result = imap_renamemailbox(
266:             $this->getBackend(),
267:             $this->_getBaseMbox() . $this->encodePath($old),
268:             $this->_getBaseMbox() . $this->encodePath($new)
269:         );
270:         if (!$result) {
271:             throw new Horde_Kolab_Storage_Exception(
272:                 sprintf(
273:                     Horde_Kolab_Storage_Translation::t(
274:                         "Renaming folder %s%s to %s%s failed. Error: %s"
275:                     ),
276:                     $this->_getBaseMbox(),
277:                     $old,
278:                     $this->_getBaseMbox(),
279:                     $new,
280:                     imap_last_error()
281:                 )
282:             );
283:         }
284:     }
285: 
286:     /**
287:      * Does the backend support ACL?
288:      *
289:      * @return boolean True if the backend supports ACLs.
290:      */
291:     public function hasAclSupport()
292:     {
293:         @imap_getacl(
294:             $this->getBackend(),
295:             $this->_getBaseMbox()
296:         );
297:         if (imap_last_error()  == 'ACL not available on this IMAP server') {
298:             return false;
299:         } else {
300:             return true;
301:         }
302:     }
303: 
304:     /**
305:      * Retrieve the access rights for a folder.
306:      *
307:      * @param string $folder The folder to retrieve the ACL for.
308:      *
309:      * @return array An array of rights.
310:      */
311:     public function getAcl($folder)
312:     {
313:         $result = imap_getacl($this->getBackend(), $this->encodePath($folder));
314:         if (!$result) {
315:             throw new Horde_Kolab_Storage_Exception(
316:                 sprintf(
317:                     Horde_Kolab_Storage_Translation::t(
318:                         "Failed reading ACL on folder %s. Error: %s"
319:                     ),
320:                     $folder,
321:                     imap_last_error()
322:                 )
323:             );
324:         }
325:         return $result;
326:     }
327: 
328:     /**
329:      * Retrieve the access rights the current user has on a folder.
330:      *
331:      * @param string $folder The folder to retrieve the user ACL for.
332:      *
333:      * @return string The user rights.
334:      */
335:     public function getMyAcl($folder)
336:     {
337:         if (!function_exists('imap_myrights')) {
338:             throw new Horde_Kolab_Storage_Exception('PHP does not support imap_myrights.');
339:         }
340: 
341:         $result = imap_myrights($this->getBackend(), $this->encodePath($folder));
342:         if (!$result) {
343:             throw new Horde_Kolab_Storage_Exception(
344:                 sprintf(
345:                     Horde_Kolab_Storage_Translation::t(
346:                         "Failed reading user rights on folder %s. Error: %s"
347:                     ),
348:                     $folder,
349:                     imap_last_error()
350:                 )
351:             );
352:         }
353:         return $result;
354:     }
355: 
356:     /**
357:      * Set the access rights for a folder.
358:      *
359:      * @param string $folder  The folder to act upon.
360:      * @param string $user    The user to set the ACL for.
361:      * @param string $acl     The ACL.
362:      *
363:      * @return NULL
364:      */
365:     public function setAcl($folder, $user, $acl)
366:     {
367:         $result = imap_setacl($this->getBackend(), $this->encodePath($folder), $user, $acl);
368:         if (!$result) {
369:             throw new Horde_Kolab_Storage_Exception(
370:                 sprintf(
371:                     Horde_Kolab_Storage_Translation::t(
372:                         "Failed setting ACL on folder %s for user %s to %s. Error: %s"
373:                     ),
374:                     $folder,
375:                     $user,
376:                     $acl,
377:                     imap_last_error()
378:                 )
379:             );
380:         }
381:         return $result;
382:     }
383: 
384:     /**
385:      * Delete the access rights for user on a folder.
386:      *
387:      * @param string $folder  The folder to act upon.
388:      * @param string $user    The user to delete the ACL for
389:      *
390:      * @return NULL
391:      */
392:     public function deleteAcl($folder, $user)
393:     {
394:         $this->setAcl($folder, $user, '');
395:     }
396: 
397:     /**
398:      * Retrieves the specified annotation for the complete list of folders.
399:      *
400:      * @param string $annotation The name of the annotation to retrieve.
401:      *
402:      * @return array An associative array combining the folder names as key with
403:      *               the corresponding annotation value.
404:      */
405:     public function listAnnotation($annotation)
406:     {
407:         if (!function_exists('imap_getannotation')) {
408:             throw new Horde_Kolab_Storage_Exception(
409:                 'This driver is not supported by your variant of PHP. The function "imap_getannotation" is missing!'
410:             );
411:         }
412:         list($entry, $value) = $this->_getAnnotateMoreEntry($annotation);
413:         $list = array();
414:         foreach ($this->_listFolders() as $folder) {
415:             $result = imap_getannotation($this->getBackend(), $folder, $entry, $value);
416:             if (isset($result[$value])) {
417:                 $list[$folder] = $result[$value];
418:             }
419:         }
420:         return $this->decodeListKeys($list);
421:     }
422: 
423:     /**
424:      * Fetches the annotation from a folder.
425:      *
426:      * @param string $folder    The name of the folder.
427:      * @param string $annotation The annotation to get.
428:      *
429:      * @return string The annotation value.
430:      */
431:     public function getAnnotation($folder, $annotation)
432:     {
433:         list($entry, $key) = $this->_getAnnotateMoreEntry($annotation);
434:         $result = imap_getannotation(
435:             $this->getBackend(), $this->encodePath($folder), $entry, $key
436:         );
437:         if (!$result) {
438:             throw new Horde_Kolab_Storage_Exception(
439:                 sprintf(
440:                     Horde_Kolab_Storage_Translation::t(
441:                         "Retrieving annotation %s[%s] on folder %s%s failed. Error: %s"
442:                     ),
443:                     $entry,
444:                     $key,
445:                     $this->_getBaseMbox(),
446:                     $folder,
447:                     imap_last_error()
448:                 )
449:             );
450:         }
451:         return $result[$key];
452:     }
453: 
454:     /**
455:      * Sets the annotation on a folder.
456:      *
457:      * @param string $folder    The name of the folder.
458:      * @param string $annotation The annotation to set.
459:      * @param array  $value      The values to set
460:      *
461:      * @return NULL
462:      */
463:     public function setAnnotation($folder, $annotation, $value)
464:     {
465:         list($entry, $key) = $this->_getAnnotateMoreEntry($annotation);
466:         $result = imap_setannotation(
467:             $this->getBackend(), $this->encodePath($folder), $entry, $key, $value
468:         );
469:         if (!$result) {
470:             throw new Horde_Kolab_Storage_Exception(
471:                 sprintf(
472:                     Horde_Kolab_Storage_Translation::t(
473:                         "Setting annotation %s[%s] on folder %s%s to %s failed. Error: %s"
474:                     ),
475:                     $entry,
476:                     $key,
477:                     $this->_getBaseMbox(),
478:                     $folder,
479:                     $value,
480:                     imap_last_error()
481:                 )
482:             );
483:         }
484:     }
485: 
486:     /**
487:      * Opens the given folder.
488:      *
489:      * @param string $folder  The folder to open
490:      *
491:      * @return NULL
492:      */
493:     public function select($folder)
494:     {
495:         $selection = $this->_getBaseMbox() . $this->encodePath($folder);
496:         if ($this->_selected != $selection) {
497:             $result = imap_reopen($this->getBackend(), $selection);
498:             if (!$result) {
499:                 throw new Horde_Kolab_Storage_Exception(
500:                     sprintf(
501:                         Horde_Kolab_Storage_Translation::t(
502:                             "Failed opening folder %s%s. Error: %s"
503:                         ),
504:                         $this->_getBaseMbox(),
505:                         $folder,
506:                         imap_last_error()
507:                     )
508:                 );
509:             }
510:         }
511:     }
512: 
513:     /**
514:      * Returns the status of the current folder.
515:      *
516:      * @param string $folder Check the status of this folder.
517:      *
518:      * @return array  An array that contains 'uidvalidity' and 'uidnext'.
519:      */
520:     public function status($folder)
521:     {
522:         $this->select($folder);
523:         $status = imap_status_current($this->getBackend(), SA_MESSAGES | SA_UIDVALIDITY | SA_UIDNEXT);
524:         if (!$status) {
525:             /**
526:              * @todo: The cclient method seems pretty much unable to detect
527:              * missing folders. It always returns "true"
528:              */
529:             throw new Horde_Kolab_Storage_Exception(
530:                 sprintf(
531:                     Horde_Kolab_Storage_Translation::t(
532:                         "Failed retrieving status information for folder %s%s. Error: %s"
533:                     ),
534:                     $this->_getBaseMbox(),
535:                     $folder,
536:                     imap_last_error()
537:                 )
538:             );
539:         }
540:         return array(
541:             'uidvalidity' => $status->uidvalidity,
542:             'uidnext' => $status->uidnext
543:         );
544:     }
545: 
546:     /**
547:      * Returns the message ids of the messages in this folder.
548:      *
549:      * @param string $folder Check the status of this folder.
550:      *
551:      * @return array  The message ids.
552:      */
553:     public function getUids($folder)
554:     {
555:         $this->select($folder);
556:         $uids = imap_search($this->getBackend(), 'UNDELETED', SE_UID);
557:         /**
558:          * @todo Error recognition? Nada... :(
559:          */
560:         if (!is_array($uids)) {
561:             $uids = array();
562:         }
563:         return $uids;
564:     }
565: 
566:     /**
567:      * Retrieves a complete message.
568:      *
569:      * @param string $folder The folder to fetch the messages from.
570:      * @param array  $uid    The message UID.
571:      *
572:      * @return array The message encapsuled as an array that contains a
573:      *               Horde_Mime_Headers and a Horde_Mime_Part object.
574:      */
575:     public function fetchComplete($folder, $uid)
576:     {
577:         $this->select($folder);
578: 
579:         $headers = @imap_fetchheader($this->getBackend(), $uid, FT_UID | FT_PREFETCHTEXT);
580:         $body = @imap_body($this->getBackend(), $uid, FT_UID);
581:         if ($headers && $body) {
582:             return array(
583:                 Horde_Mime_Headers::parseHeaders($headers),
584:                 Horde_Mime_Part::parseMessage($body)
585:             );
586:         } else {
587:             throw new Horde_Kolab_Storage_Exception(
588:                 sprintf(
589:                     Horde_Kolab_Storage_Translation::t(
590:                         "Failed fetching message %s in folder %s%s. Error: %s"
591:                     ),
592:                     $this->_getBaseMbox(),
593:                     $uid,
594:                     $folder,
595:                     imap_last_error()
596:                 )
597:             );
598:         }
599:     }
600: 
601:     /**
602:      * Retrieves the messages for the given message ids.
603:      *
604:      * @param string $folder The folder to fetch the messages from.
605:      * @param array  $uids   The message UIDs.
606:      *
607:      * @return array An array of message structures parsed into Horde_Mime_Part
608:      *               instances.
609:      */
610:     public function fetchStructure($folder, $uids)
611:     {
612:         $result = array();
613: 
614:         $this->select($folder);
615:         foreach ($uids as $uid) {
616:             $structure = @imap_fetchstructure($this->getBackend(), $uid, FT_UID);
617:             if ($structure) {
618:                 $ob = $this->_parseStructure($structure);
619:                 $ob->buildMimeIds();
620:                 $result[$uid]['structure'] = $ob;
621:             } else {
622:                 throw new Horde_Kolab_Storage_Exception(
623:                     sprintf(
624:                         Horde_Kolab_Storage_Translation::t(
625:                             "Failed fetching structure information for messages %s in folder %s%s. Error: %s"
626:                         ),
627:                         $this->_getBaseMbox(),
628:                         join(',', $uids),
629:                         $folder,
630:                         imap_last_error()
631:                     )
632:                 );
633:             }
634:         }
635: 
636:         return $result;
637:     }
638: 
639:     /**
640:      * Retrieves a bodypart for the given message ID and mime part ID.
641:      *
642:      * @param string $folder The folder to fetch the messages from.
643:      * @param array  $uid    The message UID.
644:      * @param array  $id     The mime part ID.
645:      *
646:      * @return resource|string The body part, as a stream resource or string.
647:      */
648:     public function fetchBodypart($folder, $uid, $id)
649:     {
650:         $this->select($folder);
651: 
652:         $result = @imap_fetchbody($this->getBackend(), $uid, $id, FT_UID);
653:         if (!$result) {
654:             throw new Horde_Kolab_Storage_Exception(
655:                 sprintf(
656:                     Horde_Kolab_Storage_Translation::t(
657:                         "Failed fetching body part %s for message %s in folder %s%s. Error: %s"
658:                     ),
659:                     $this->_getBaseMbox(),
660:                     $id,
661:                     $uid,
662:                     $folder,
663:                     imap_last_error()
664:                 )
665:             );
666:         }
667:         return $result;
668:     }
669: 
670:     /**
671:      * Appends a message to the given folder.
672:      *
673:      * @param string   $folder  The folder to append the message(s) to.
674:      * @param resource $msg     The message to append.
675:      *
676:      * @return mixed True or the UID of the new message in case the backend
677:      *               supports UIDPLUS.
678:      */
679:     public function appendMessage($folder, $msg)
680:     {
681:         rewind($msg);
682:         $result = @imap_append(
683:             $this->getBackend(),
684:             $this->_getBaseMbox() . $this->encodePath($folder),
685:             stream_get_contents($msg)
686:         );
687:         if (!$result) {
688:             throw new Horde_Kolab_Storage_Exception(
689:                 sprintf(
690:                     Horde_Kolab_Storage_Translation::t(
691:                         "Failed appending new message to folder %s%s. Error: %s"
692:                     ),
693:                     $this->_getBaseMbox(),
694:                     $folder,
695:                     imap_last_error()
696:                 )
697:             );
698:         }
699:         return $result;
700:     }
701: 
702:     /**
703:      * Deletes messages from the specified folder.
704:      *
705:      * @param string  $folder  The folder to delete messages from.
706:      * @param integer $uids    IMAP message ids.
707:      *
708:      * @return NULL
709:      */
710:     public function deleteMessages($folder, $uids)
711:     {
712:         $this->select($folder);
713: 
714:         foreach ($uids as $uid) {
715:             $result = @imap_delete(
716:                 $this->getBackend(),
717:                 $uid,
718:                 FT_UID
719:             );
720:             if (!$result) {
721:                 throw new Horde_Kolab_Storage_Exception(
722:                     sprintf(
723:                         Horde_Kolab_Storage_Translation::t(
724:                             "Failed deleting message %s in folder %s. Error: %s"
725:                         ),
726:                         $uid,
727:                         $folder,
728:                         imap_last_error()
729:                     )
730:                 );
731:             }
732:         }
733:     }
734: 
735:     /**
736:      * Moves a message to a new folder.
737:      *
738:      * @param integer $uid         IMAP message id.
739:      * @param string  $old_folder  Source folder.
740:      * @param string  $new_folder  Target folder.
741:      *
742:      * @return NULL
743:      */
744:     public function moveMessage($uid, $old_folder, $new_folder)
745:     {
746:         $this->select($old_folder);
747: 
748:         $result = @imap_mail_move(
749:             $this->getBackend(),
750:             $uid,
751:             $this->encodePath($new_folder),
752:             CP_UID
753:         );
754:         if (!$result) {
755:             throw new Horde_Kolab_Storage_Exception(
756:                 sprintf(
757:                     Horde_Kolab_Storage_Translation::t(
758:                         "Failed message %s from folder %s to folder %s. Error: %s"
759:                     ),
760:                     $uid,
761:                     $old_folder,
762:                     $new_folder,
763:                     imap_last_error()
764:                 )
765:             );
766:         }
767:     }
768: 
769:     /**
770:      * Expunges messages in the current folder.
771:      *
772:      * @param string $folder The folder to append the message(s) to. Either
773:      *                        in UTF7-IMAP or UTF-8.
774:      *
775:      * @return mixed  True or a PEAR error in case of an error.
776:      */
777:     public function expunge($folder)
778:     {
779:         $this->select($folder);
780:         $result = @imap_expunge($this->getBackend());
781:         if (!$result) {
782:             throw new Horde_Kolab_Storage_Exception(
783:                 sprintf(
784:                     Horde_Kolab_Storage_Translation::t(
785:                         "Failed expunging folder %s. Error: %s"
786:                     ),
787:                     $folder,
788:                     imap_last_error()
789:                 )
790:             );
791:         }
792:     }
793: 
794:     /**
795:      * Parse the output from imap_fetchstructure() into a MIME Part object.
796:      *
797:      * @param object $data  Data from imap_fetchstructure().
798:      *
799:      * @return Horde_Mime_Part  A MIME Part object.
800:      */
801:     protected function _parseStructure($data)
802:     {
803:         $ob = new Horde_Mime_Part();
804: 
805:         $ob->setType($this->_mimeTypes[$data->type] . '/' . ($data->ifsubtype ? strtolower($data->subtype) : Horde_Mime_Part::UNKNOWN));
806: 
807:         // Optional for multipart-parts, required for all others
808:         if ($data->ifparameters) {
809:             $params = array();
810:             foreach ($data->parameters as $val) {
811:                 $params[$val->attribute] = $val->value;
812:             }
813: 
814:             $params = Horde_Mime::decodeParam('content-type', $params, 'UTF-8');
815:             foreach ($params['params'] as $key => $val) {
816:                 $ob->setContentTypeParameter($key, $val);
817:             }
818:         }
819: 
820:         // Optional entries. 'location' and 'language' not supported
821:         if ($data->ifdisposition) {
822:             $ob->setDisposition($data->disposition);
823:             if ($data->ifdparameters) {
824:                 $dparams = array();
825:                 foreach ($data->dparameters as $val) {
826:                     $dparams[$val->attribute] = $val->value;
827:                 }
828: 
829:                 $dparams = Horde_Mime::decodeParam('content-disposition', $dparams, 'UTF-8');
830:                 foreach ($dparams['params'] as $key => $val) {
831:                     $ob->setDispositionParameter($key, $val);
832:                 }
833:             }
834:         }
835: 
836:         if ($ob->getPrimaryType() == 'multipart') {
837:             // multipart/* specific entries
838:             foreach ($data->parts as $val) {
839:                 $ob->addPart($this->_parseStructure($val));
840:             }
841:         } else {
842:             // Required options
843:             if ($data->ifid) {
844:                 $ob->setContentId($data->id);
845:             }
846:             if ($data->ifdescription) {
847:                 $ob->setDescription(Horde_Mime::decode($data->description, 'UTF-8'));
848:             }
849: 
850:             $ob->setTransferEncoding($this->_mimeEncodings[$data->encoding]);
851:             $ob->setBytes($data->bytes);
852: 
853:             if ($ob->getType() == 'message/rfc822') {
854:                 $ob->addPart($this->_parseStructure(reset($data->parts)));
855:             }
856:         }
857: 
858:         return $ob;
859:     }
860: }
861: 
API documentation generated by ApiGen