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 Kolab storage mock 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 Kolab storage mock 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_Mock
 29: extends Horde_Kolab_Storage_Driver_Base
 30: {
 31:     /**
 32:      * The data of the folders.
 33:      *
 34:      * @var Horde_Kolab_Storage_Driver_Mock_Data
 35:      */
 36:     private $_data;
 37: 
 38:     /**
 39:      * The regular expression for converting folder names.
 40:      *
 41:      * @var string
 42:      */
 43:     private $_conversion_pattern;
 44: 
 45:     /**
 46:      * The data of the folder currently opened
 47:      *
 48:      * @var array
 49:      */
 50:     private $_mbox = null;
 51: 
 52:     /**
 53:      * The name of the folder currently opened
 54:      *
 55:      * @var array
 56:      */
 57:     private $_mboxname = null;
 58: 
 59:     /**
 60:      * A list of groups (associates users [key] with an array of group names
 61:      * [value]).
 62:      *
 63:      * @var array
 64:      */
 65:     private $_groups = array();
 66: 
 67:     /**
 68:      * Constructor.
 69:      *
 70:      * @param Horde_Kolab_Storage_Factory $factory A factory for helper objects.
 71:      * @param array $params                        Connection parameters.
 72:      */
 73:     public function __construct(Horde_Kolab_Storage_Factory $factory,
 74:                                 $params = array())
 75:     {
 76:         if (isset($params['data'])) {
 77:             if (is_array($params['data'])) {
 78:                 $params['data'] = new Horde_Kolab_Storage_Driver_Mock_Data(
 79:                     $params['data']
 80:                 );
 81:             }
 82:             $this->_data = $params['data'];
 83:             unset($params['data']);
 84:         } else {
 85:             $this->_data = new Horde_Kolab_Storage_Driver_Mock_Data(array());
 86:         }
 87:         parent::__construct($factory, $params);
 88:     }
 89: 
 90:     /**
 91:      * Convert the external folder id to an internal folder name.
 92:      *
 93:      * @param string $folder The external folder name.
 94:      *
 95:      * @return string The internal folder id.
 96:      */
 97:     private function _convertToInternal($folder)
 98:     {
 99:         if (substr($folder, 0, 5) == 'INBOX') {
100:             $user = explode('@', $this->getAuth());
101:             return 'user/' . $user[0] . substr($folder, 5);
102:         }
103:         return $folder;
104:     }
105: 
106:     /**
107:      * Convert the internal folder name into an external folder id.
108:      *
109:      * @param string $mbox The internal folder name.
110:      *
111:      * @return string The external folder id.
112:      */
113:     private function _convertToExternal($mbox)
114:     {
115:         if ($this->_conversion_pattern === null) {
116:             if ($this->getAuth() != '') {
117:                 $user = explode('@', $this->getAuth());
118:                 $this->_conversion_pattern = '#^user/' . $user[0] . '#';
119:             } else {
120:                 /**
121:                  * @todo: FIXME, this is a hack for the current state of the
122:                  * Kolab share driver which does not yet know how to properly
123:                  * deal with system shares.
124:                  */
125:                 if ($mbox == 'user/') {
126:                     return 'INBOX';
127:                 } else {
128:                     return preg_replace('#^user//#', 'INBOX/', $mbox);
129:                 }
130:             }
131:         }
132:         return preg_replace($this->_conversion_pattern, 'INBOX', $mbox);
133:     }
134: 
135:     /**
136:      * Set a group list.
137:      *
138:      * @param array $groups A list of groups. User names are the keys, an array
139:      *                      of group names are the values.
140:      *
141:      * @return NULL
142:      */
143:     public function setGroups($groups)
144:     {
145:         $this->_groups = $groups;
146:     }
147: 
148:     /**
149:      * Create the backend driver.
150:      *
151:      * @return mixed The backend driver.
152:      */
153:     public function createBackend()
154:     {
155:     }
156: 
157:     /**
158:      * Return the unique connection id.
159:      *
160:      * @return string The connection id.
161:      */
162:     public function getId()
163:     {
164:         return $this->getAuth() . '@mock:0';
165:     }
166: 
167:     /**
168:      * Retrieves a list of folders on the server.
169:      *
170:      * @return array The list of folders.
171:      */
172:     public function listFolders()
173:     {
174:         $result = array();
175:         foreach ($this->_data->arrayKeys() as $mbox) {
176:             if ($this->_folderVisible($mbox, $this->getAuth())) {
177:                 $result[] = $this->_convertToExternal($mbox);
178:             }
179:         }
180:         return $result;
181:     }
182: 
183:     /**
184:      * Create the specified folder.
185:      *
186:      * @param string $folder The folder to create.
187:      *
188:      * @return NULL
189:      */
190:     public function create($folder)
191:     {
192:         $folder = $this->_convertToInternal($folder);
193:         if (isset($this->_data[$folder])) {
194:             throw new Horde_Kolab_Storage_Exception(
195:                 sprintf("IMAP folder %s does already exist!", $folder)
196:             );
197:         }
198:         $this->_data[$folder] = array(
199:             'status' => array(
200:                 'uidvalidity' => time(),
201:                 'uidnext' => 1
202:             ),
203:             'mails' => array(),
204:             'permissions' => array($this->getAuth() => 'lrswipkxtecda'),
205:             'annotations' => array(),
206:         );
207:     }
208: 
209:     /**
210:      * Delete the specified folder.
211:      *
212:      * @param string $folder The folder to delete.
213:      *
214:      * @return NULL
215:      */
216:     public function delete($folder)
217:     {
218:         $folder = $this->_convertToInternal($folder);
219:         if (!isset($this->_data[$folder])) {
220:             throw new Horde_Kolab_Storage_Exception(
221:                 sprintf("IMAP folder %s does not exist!", $folder)
222:             );
223:         }
224:         unset($this->_data[$folder]);
225:     }
226: 
227:     /**
228:      * Rename the specified folder.
229:      *
230:      * @param string $old  The folder to rename.
231:      * @param string $new  The new name of the folder.
232:      *
233:      * @return NULL
234:      */
235:     public function rename($old, $new)
236:     {
237:         $old = $this->_convertToInternal($old);
238:         $new = $this->_convertToInternal($new);
239:         if (!isset($this->_data[$old])) {
240:             throw new Horde_Kolab_Storage_Exception(
241:                 sprintf("IMAP folder %s does not exist!", $old)
242:             );
243:         }
244:         if (isset($this->_data[$new])) {
245:             throw new Horde_Kolab_Storage_Exception(
246:                 sprintf("IMAP folder %s does already exist!", $new)
247:             );
248:         }
249:         $this->_data[$new] = $this->_data[$old];
250:         unset($this->_data[$old]);
251:     }
252: 
253:     /**
254:      * Does the backend support ACL?
255:      *
256:      * @return boolean True if the backend supports ACLs.
257:      */
258:     public function hasAclSupport()
259:     {
260:         return true;
261:     }
262: 
263:     /**
264:      * Retrieve the access rights for a folder.
265:      *
266:      * @param string $folder The folder to retrieve the ACL for.
267:      *
268:      * @return array An array of rights.
269:      */
270:     public function getAcl($folder)
271:     {
272:         $folder = $this->_convertToInternal($folder);
273:         $this->_failOnMissingFolder($folder);
274:         $this->_failOnNoAdmin($folder);
275:         if ($this->_data->hasPermissions($folder)) {
276:             return $this->_data->getPermissions($folder);
277:         }
278:         return array();
279:     }
280: 
281:     /**
282:      * Retrieve the access rights the current user has on a folder.
283:      *
284:      * @param string $folder The folder to retrieve the user ACL for.
285:      *
286:      * @return string The user rights.
287:      */
288:     public function getMyAcl($folder)
289:     {
290:         $folder = $this->_convertToInternal($folder);
291:         $this->_failOnMissingFolder($folder);
292:         $myacl = array();
293:         $users = array($this->getAuth(), 'anyone', 'anonymous');
294:         if (isset($this->_groups[$this->getAuth()])) {
295:             foreach ($this->_groups[$this->getAuth()] as $group) {
296:                 $users[] = 'group:' . $group;
297:             }
298:         }
299:         foreach ($users as $user) {
300:             if ($this->_data->hasUserPermissions($folder, $user)) {
301:                 $myacl = array_merge($myacl, str_split($this->_data->getUserPermissions($folder, $user)));
302:             }
303:         }
304:         return join('', $myacl);
305:     }
306: 
307:     /**
308:      * Set the access rights for a folder.
309:      *
310:      * @param string $folder  The folder to act upon.
311:      * @param string $user    The user to set the ACL for.
312:      * @param string $acl     The ACL.
313:      *
314:      * @return NULL
315:      */
316:     public function setAcl($folder, $user, $acl)
317:     {
318:         $folder = $this->_convertToInternal($folder);
319:         $this->_failOnMissingFolder($folder);
320:         $this->_failOnNoAdmin($folder);
321:         $this->_data->setUserPermissions($folder, $user, $acl);
322:     }
323: 
324:     /**
325:      * Delete the access rights for user on a folder.
326:      *
327:      * @param string $folder  The folder to act upon.
328:      * @param string $user    The user to delete the ACL for
329:      *
330:      * @return NULL
331:      */
332:     public function deleteAcl($folder, $user)
333:     {
334:         $folder = $this->_convertToInternal($folder);
335:         $this->_failOnMissingFolder($folder);
336:         $this->_failOnNoAdmin($folder);
337:         if ($this->_data->hasUserPermissions($folder, $user)) {
338:             $this->_data->deleteUserPermissions($folder, $user);
339:         }
340:     }
341: 
342:     /**
343:      * Retrieves the specified annotation for the complete list of folders.
344:      *
345:      * @param string $annotation The name of the annotation to retrieve.
346:      *
347:      * @return array An associative array combining the folder names as key with
348:      *               the corresponding annotation value.
349:      */
350:     public function listAnnotation($annotation)
351:     {
352:         $result = array();
353:         foreach ($this->_data->arrayKeys() as $folder) {
354:             if ($this->_data->hasAnnotation($folder, $annotation)) {
355:                 $result[$this->_convertToExternal($folder)] = $this->_data->getAnnotation($folder, $annotation);
356:             }
357:         }
358:         return $result;
359:     }
360: 
361:     /**
362:      * Fetches the annotation from a folder.
363:      *
364:      * @param string $folder    The name of the folder.
365:      * @param string $annotation The annotation to get.
366:      *
367:      * @return string The annotation value.
368:      */
369:     public function getAnnotation($folder, $annotation)
370:     {
371:         $folder = $this->_convertToInternal($folder);
372:         $this->_failOnMissingFolder($folder);
373:         if ($this->_data->hasAnnotation($folder, $annotation)) {
374:             return $this->_data->getAnnotation($folder, $annotation);
375:         }
376:         return '';
377:     }
378: 
379:     /**
380:      * Sets the annotation on a folder.
381:      *
382:      * @param string $folder    The name of the folder.
383:      * @param string $annotation The annotation to set.
384:      * @param array  $value      The values to set
385:      *
386:      * @return NULL
387:      */
388:     public function setAnnotation($folder, $annotation, $value)
389:     {
390:         $folder = $this->_convertToInternal($folder);
391:         $this->_failOnMissingFolder($folder);
392:         $this->_data->setAnnotation($folder, $annotation, $value);
393:     }
394: 
395:     /**
396:      * Error out in case the provided folder is missing.
397:      *
398:      * @param string  $folder The folder.
399:      *
400:      * @return NULL
401:      *
402:      * @throws Horde_Kolab_Storage_Exception In case the folder is missing.
403:      */
404:     private function _failOnMissingFolder($folder)
405:     {
406:         if (!isset($this->_data[$folder])
407:             || !$this->_folderVisible($folder, $this->getAuth())) {
408:             $this->_folderMissing($folder);
409:         }
410:     }
411: 
412:     /**
413:      * Is the folder visible to the specified user (or a global group)?
414:      *
415:      * @param string $folder The folder.
416:      * @param string $user   The user.
417:      *
418:      * @return boolean True if the folder is visible.
419:      */
420:     private function _folderVisible($folder, $user)
421:     {
422:         return empty($user)
423:             || $this->_folderVisibleToUnique($folder, $user)
424:             || $this->_folderVisibleToGroup($folder, $user)
425:             || $this->_folderVisibleToUnique($folder, 'anyone')
426:             || $this->_folderVisibleToUnique($folder, 'anonymous');
427:     }
428: 
429:     /**
430:      * Is the folder visible to a group the user belongs to?
431:      *
432:      * @param string $folder The folder.
433:      * @param string $user   The user.
434:      *
435:      * @return boolean True if the folder is visible.
436:      */
437:     private function _folderVisibleToGroup($folder, $user)
438:     {
439:         if (isset($this->_groups[$user])) {
440:             foreach ($this->_groups[$user] as $group) {
441:                 if ($this->_folderVisibleToUnique($folder, 'group:' . $group)) {
442:                     return true;
443:                 }
444:             }
445:         }
446:         return false;
447:     }
448: 
449:     /**
450:      * Is the folder visible to exactly the specified user?
451:      *
452:      * @param string $folder The folder.
453:      * @param string $user   The user.
454:      *
455:      * @return boolean True if the folder is visible.
456:      */
457:     private function _folderVisibleToUnique($folder, $user)
458:     {
459:         if ($this->_data->hasUserPermissions($folder, $user)) {
460:             if (strpos($this->_data->getUserPermissions($folder, $user), 'l') !== false
461:                 || strpos($this->_data->getUserPermissions($folder, $user), 'r') !== false
462:                 || strpos($this->_data->getUserPermissions($folder, $user), 'a') !== false) {
463:                 return true;
464:             }
465:         }
466:         return false;
467:     }
468: 
469:     /**
470:      * Error out indicating that the user does not have the required
471:      * permissions.
472:      *
473:      * @param string  $folder The folder.
474:      *
475:      * @return NULL
476:      *
477:      * @throws Horde_Kolab_Storage_Exception In case the folder is missing.
478:      */
479:     private function _folderMissing($folder)
480:     {
481:         throw new Horde_Kolab_Storage_Exception(
482:             sprintf('The folder %s does not exist!', $folder)
483:         );
484:     }
485: 
486:     /**
487:      * Error out in case the user is no admin of the specified folder.
488:      *
489:      * @param string  $folder The folder.
490:      *
491:      * @return NULL
492:      *
493:      * @throws Horde_Kolab_Storage_Exception In case the user has no admin rights.
494:      */
495:     private function _failOnNoAdmin($folder)
496:     {
497:         if (!isset($this->_data[$folder])
498:             || !$this->_folderAdmin($folder, $this->getAuth())) {
499:             $this->_permissionDenied();
500:         }
501:     }
502: 
503:     /**
504:      * Is the user a folder admin (or one of the global groups)?
505:      *
506:      * @param string $folder The folder.
507:      * @param string $user   The user.
508:      *
509:      * @return boolean True if the user has admin rights on the folder.
510:      */
511:     private function _folderAdmin($folder, $user)
512:     {
513:         return empty($user)
514:             || $this->_folderAdminForUnique($folder, $user)
515:             || $this->_folderAdminForGroup($folder, $user)
516:             || $this->_folderAdminForUnique($folder, 'anyone')
517:             || $this->_folderAdminForUnique($folder, 'anonymous');
518:     }
519: 
520:     /**
521:      * Is the folder visible to a group the user belongs to?
522:      *
523:      * @param string $folder The folder.
524:      * @param string $user   The user.
525:      *
526:      * @return boolean True if the folder is visible.
527:      */
528:     private function _folderAdminForGroup($folder, $user)
529:     {
530:         if (isset($this->_groups[$user])) {
531:             foreach ($this->_groups[$user] as $group) {
532:                 if ($this->_folderAdminForUnique($folder, 'group:' . $group)) {
533:                     return true;
534:                 }
535:             }
536:         }
537:         return false;
538:     }
539: 
540:     /**
541:      * Is the exact specified user an admin for the folder?
542:      *
543:      * @param string $folder The folder.
544:      * @param string $user   The user.
545:      *
546:      * @return boolean True if the user has admin rights on the folder.
547:      */
548:     private function _folderAdminForUnique($folder, $user)
549:     {
550:         if ($this->_data->hasUserPermissions($folder, $user)
551:             && strpos($this->_data->getUserPermissions($folder, $user), 'a') !== false) {
552:             return true;
553:         }
554:         return false;
555:     }
556: 
557:     /**
558:      * Error out indicating that the user does not have the required
559:      * permissions.
560:      *
561:      * @return NULL
562:      *
563:      * @throws Horde_Kolab_Storage_Exception In case the folder is missing.
564:      */
565:     private function _permissionDenied()
566:     {
567:         throw new Horde_Kolab_Storage_Exception('Permission denied!');
568:     }
569: 
570:     /**
571:      * Opens the given folder.
572:      *
573:      * @param string $folder  The folder to open
574:      *
575:      * @return NULL
576:      */
577:     public function select($folder)
578:     {
579:         $this->_data->select($this->_convertToInternal($folder));
580:     }
581: 
582:     /**
583:      * Returns the status of the current folder.
584:      *
585:      * @param string $folder Check the status of this folder.
586:      *
587:      * @return array  An array that contains 'uidvalidity' and 'uidnext'.
588:      */
589:     public function status($folder)
590:     {
591:         return $this->_data->status($this->_convertToInternal($folder));
592:     }
593: 
594:     /**
595:      * Returns the message ids of the messages in this folder.
596:      *
597:      * @param string $folder Check the status of this folder.
598:      *
599:      * @return array  The message ids.
600:      */
601:     public function getUids($folder)
602:     {
603:         return $this->_data->getUids($this->_convertToInternal($folder));
604:     }
605: 
606:     /**
607:      * Retrieves the messages for the given message ids.
608:      *
609:      * @param string $folder The folder to fetch the messages from.
610:      * @param array  $uids                The message UIDs.
611:      *
612:      * @return array An array of message structures parsed into Horde_Mime_Part
613:      *               instances.
614:      */
615:     public function fetchStructure($folder, $uids)
616:     {
617:         return $this->_data->fetchStructure(
618:             $this->_convertToInternal($folder),
619:             $uids
620:         );
621:     }
622: 
623:     /**
624:      * Retrieves a complete message.
625:      *
626:      * @param string $folder The folder to fetch the messages from.
627:      * @param array  $uid    The message UID.
628:      *
629:      * @return array The message encapsuled as an array that contains a
630:      *               Horde_Mime_Headers and a Horde_Mime_Part object.
631:      */
632:     public function fetchComplete($folder, $uid)
633:     {
634:         return $this->_data->fetchComplete(
635:             $this->_convertToInternal($folder),
636:             $uid
637:         );
638:     }
639: 
640:     /**
641:      * Retrieves a bodypart for the given message ID and mime part ID.
642:      *
643:      * @param string $folder The folder to fetch the messages from.
644:      * @param array  $uid                 The message UID.
645:      * @param array  $id                  The mime part ID.
646:      *
647:      * @return resource|string The body part, as a stream resource or string.
648:      */
649:     public function fetchBodypart($folder, $uid, $id)
650:     {
651:         return $this->_data->fetchBodypart(
652:             $this->_convertToInternal($folder),
653:             $uid,
654:             $id
655:         );
656:     }
657: 
658:     /**
659:      * Appends a message to the given folder.
660:      *
661:      * @param string   $folder  The folder to append the message(s) to.
662:      * @param resource $msg     The message to append.
663:      *
664:      * @return mixed True or the UID of the new message in case the backend
665:      *               supports UIDPLUS.
666:      */
667:     public function appendMessage($folder, $msg)
668:     {
669:         return $this->_data->appendMessage(
670:             $this->_convertToInternal($folder),
671:             $msg
672:         );
673:     }
674: 
675:     /**
676:      * Deletes messages from the specified folder.
677:      *
678:      * @param string  $folder  The folder to delete messages from.
679:      * @param integer $uids    IMAP message ids.
680:      *
681:      * @return NULL
682:      */
683:     public function deleteMessages($folder, $uids)
684:     {
685:         $this->_data->deleteMessages(
686:             $this->_convertToInternal($folder),
687:             $uids
688:         );
689:     }
690: 
691:     /**
692:      * Moves a message to a new folder.
693:      *
694:      * @param integer $uid         IMAP message id.
695:      * @param string  $old_folder  Source folder.
696:      * @param string  $new_folder  Target folder.
697:      *
698:      * @return NULL
699:      */
700:     public function moveMessage($uid, $old_folder, $new_folder)
701:     {
702:         $this->_data->moveMessage(
703:             $uid,
704:             $this->_convertToInternal($old_folder),
705:             $this->_convertToInternal($new_folder)
706:         );
707:     }
708: 
709:     /**
710:      * Expunges messages in the current folder.
711:      *
712:      * @param string $folder The folder to expunge.
713:      *
714:      * @return NULL
715:      */
716:     public function expunge($folder)
717:     {
718:         $this->_data->expunge($this->_convertToInternal($folder));
719:     }
720: }
721: 
API documentation generated by ApiGen