Overview

Packages

  • Vfs

Classes

  • Horde_Vfs
  • Horde_Vfs_Base
  • Horde_Vfs_Browser
  • Horde_Vfs_Exception
  • Horde_Vfs_File
  • Horde_Vfs_Ftp
  • Horde_Vfs_Gc
  • Horde_Vfs_Horde
  • Horde_Vfs_Kolab
  • Horde_Vfs_ListItem
  • Horde_Vfs_Musql
  • Horde_Vfs_Object
  • Horde_Vfs_Smb
  • Horde_Vfs_Sql
  • Horde_Vfs_SqlFile
  • Horde_Vfs_Ssh2
  • Horde_Vfs_Translation
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * VFS implementation for a Kolab IMAP server.
  4:  *
  5:  * Copyright 2002-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author  Gunnar Wrobel <wrobel@pardus.de>
 11:  * @package Vfs
 12:  */
 13: class Horde_Vfs_Kolab extends Horde_Vfs_Base
 14: {
 15:     /**
 16:      * Variable holding the connection to the Kolab storage system.
 17:      *
 18:      * @var Horde_Kolab_IMAP
 19:      */
 20:     protected $_imap = false;
 21: 
 22:     /**
 23:      * Cache for the list of folders.
 24:      *
 25:      * @var array
 26:      */
 27:     protected $_folders;
 28: 
 29:     /**
 30:      * Retrieves a file from the VFS.
 31:      *
 32:      * @param string $path  The pathname to the file.
 33:      * @param string $name  The filename to retrieve.
 34:      *
 35:      * @return string  The file data.
 36:      * @throws Horde_Vfs_Exception
 37:      */
 38:     public function read($path, $name)
 39:     {
 40:         list($app, $uid) = $this->_getAppUid($path);
 41:         if ($app && $uid) {
 42:             $handler = $this->_getAppHandler($app, $uid);
 43:             $object = $handler->getObject($uid);
 44: 
 45:             if (isset($object['_attachments'][$name])) {
 46:                 return $handler->getAttachment($object['_attachments'][$name]['key']);
 47:             }
 48:         }
 49: 
 50:         //FIXME
 51:         if ($this->isFolder(dirname($path), basename($path))) {
 52:             $session = Horde_Kolab_Session::singleton();
 53:             $imap = $session->getImap();
 54: 
 55:             $result = $imap->select(substr($path,1));
 56:             if ($result instanceof PEAR_Error) {
 57:                 throw new Horde_Vfs_Exception($result->getMessage());
 58:             }
 59: 
 60:             $file = explode('/', $name);
 61: 
 62:             return $this->_getFile($imap, $file[0], $file[1]);
 63:         }
 64: 
 65:         return '';
 66:     }
 67: 
 68:     /**
 69:      * Stores a file in the VFS.
 70:      *
 71:      * @param string $path         The path to store the file in.
 72:      * @param string $name         The filename to use.
 73:      * @param string $tmpFile      The temporary file containing the data to
 74:      *                             be stored.
 75:      * @param boolean $autocreate  Automatically create directories?
 76:      *
 77:      * @throws Horde_Vfs_Exception
 78:      */
 79:     public function write($path, $name, $tmpFile, $autocreate = false)
 80:     {
 81:         list($app, $uid) = $this->_getAppUid($path);
 82:         if ($app) {
 83:             $handler = $this->_getAppHandler($app, $uid);
 84:             $object = $handler->getObject($uid);
 85:             $object['_attachments'][$name]['path'] = $tmpFile;
 86:             if (empty($object['link-attachment'])) {
 87:                 $object['link-attachment'] = array($name);
 88:             } else {
 89:                 $object['link-attachment'][] = $name;
 90:             }
 91: 
 92:             return $handler->save($object, $uid);
 93:         }
 94: 
 95:         if ($autocreate && !$this->isFolder(dirname($path), basename($path))) {
 96:             $this->autocreatePath($path);
 97:         }
 98: 
 99:         //FIXME
100:         throw new Horde_Vfs_Exception('Not supported.');
101:     }
102: 
103:     /**
104:      * Deletes a file from the VFS.
105:      *
106:      * @param string $path  The path to delete the file from.
107:      * @param string $name  The filename to delete.
108:      *
109:      * @throws Horde_Vfs_Exception
110:      */
111:     public function deleteFile($path, $name)
112:     {
113:         list($app, $uid) = $this->_getAppUid($path);
114:         if ($app) {
115:             $handler = $this->_getAppHandler($app, $uid);
116:             $object = $handler->getObject($uid);
117:             if (!isset($object['_attachments'][$name])) {
118:                 throw new Horde_Vfs_Exception('Unable to delete VFS file.');
119:             }
120:             unset($object['_attachments'][$name]);
121:             $object['link-attachment'] = array_values(array_diff($object['link-attachment'], array($name)));
122: 
123:             return $handler->save($object, $uid);
124:         }
125: 
126:         //FIXME
127:         throw new Horde_Vfs_Exception('Not supported.');
128:     }
129: 
130:     /**
131:      * Creates a folder on the VFS.
132:      *
133:      * @param string $path  The parent folder.
134:      * @param string $name  The name of the new folder.
135:      *
136:      * @throws Horde_Vfs_Exception
137:      */
138:     public function createFolder($path, $name)
139:     {
140:         $list = Kolab_List::singleton();
141:         $folder = $this->_getFolder($path, $name);
142: 
143:         $object = $list->getNewFolder();
144:         $object->setName($folder);
145: 
146:         $object->save(array('type' => 'h-file'));
147:         if ($result instanceof PEAR_Error) {
148:             throw new Horde_Vfs_Exception($result->getMessage());
149:         }
150: 
151:         $this->_folders = null;
152:     }
153: 
154:      /**
155:      * Deletes a folder from the VFS.
156:      *
157:      * @param string $path        The parent folder.
158:      * @param string $name        The name of the folder to delete.
159:      * @param boolean $recursive  Force a recursive delete?
160:      *
161:      * @throws Horde_Vfs_Exception
162:      */
163:     public function deleteFolder($path, $name, $recursive = false)
164:     {
165:         if ($recursive) {
166:             $this->emptyFolder($path . '/' . $name);
167:         } else {
168:             $list = $this->listFolder($path . '/' . $name, null, false);
169:             if (count($list)) {
170:                 throw new Horde_Vfs_Exception(sprintf('Unable to delete %s, the directory is not empty', $path . '/' . $name));
171:             }
172:         }
173: 
174:         list($app, $uid) = $this->_getAppUid($path . '/' . $name);
175:         if ($app) {
176:             /**
177:              * Objects provide no real folders and we don't delete them.
178:              */
179:             return;
180:         }
181: 
182:         $folders = $this->_getFolders();
183:         $folder = $this->_getFolder($path, $name);
184: 
185:         if (!empty($folders['/' . $folder])) {
186:             $folders['/' . $folder]->delete();
187:             $this->_folders = null;
188:             return;
189:         }
190: 
191:         throw new Horde_Vfs_Exception(sprintf('No such folder %s!', '/' . $folder));
192:     }
193: 
194:     /**
195:      * Recursively remove all files and subfolders from the given
196:      * folder.
197:      *
198:      * @param string $path  The path of the folder to empty.
199:      *
200:      * @throws Horde_Vfs_Exception
201:      */
202:     public function emptyFolder($path)
203:     {
204:         // Get and delete the subfolders.
205:         $list = $this->listFolder($path, null, false, true);
206:         foreach ($list as $folder) {
207:             $this->deleteFolder($path, $folder['name'], true);
208:         }
209: 
210:         // Only files are left, get and delete them.
211:         $list = $this->listFolder($path, null, false);
212:         foreach ($list as $file) {
213:             $this->deleteFile($path, $file['name']);
214:         }
215:     }
216: 
217:     /**
218:      * Returns an an unsorted file list of the specified directory.
219:      *
220:      * @param string $path       The path of the directory.
221:      * @param mixed $filter      String/hash to filter file/dirname on.
222:      * @param boolean $dotfiles  Show dotfiles?
223:      * @param boolean $dironly   Show only directories?
224:      *
225:      * @return array  File list.
226:      * @throws Horde_Vfs_Exception
227:      */
228:     protected function _listFolder($path = '', $filter = null, $dotfiles = true,
229:                                    $dironly = false)
230:     {
231:         list($app, $uid) = $this->_getAppUid($path);
232:         if ($app) {
233:             if ($dironly) {
234:                 /**
235:                  * Objects dont support directories.
236:                  */
237:                 return array();
238:             }
239:             if ($uid) {
240:                 $handler = $this->_getAppHandler($app, $uid);
241:                 $object = $handler->getObject($uid);
242:                 if ($object instanceof PEAR_Error) {
243:                     throw new Horde_Vfs_Exception($object->getMessage());
244:                 }
245: 
246:                 $filenames = isset($object['_attachments'])
247:                     ? array_keys($object['_attachments'])
248:                     : array();
249:             } else {
250:                 $filenames = $this->_getAppUids($app);
251:             }
252: 
253:             $owner = $GLOBALS['registry']->getAuth();
254: 
255:             $file = $files = array();
256:             foreach ($filenames as $filename) {
257:                 $name = explode('.', $filename);
258: 
259:                 if (count($name) == 1) {
260:                     $file['type'] = '**none';
261:                 } else {
262:                     $file['type'] = Horde_String::lower($name[count($name) - 1]);
263:                 }
264: 
265:                 $file['size'] = '-1';
266:                 $file['name'] = $filename;
267:                 $file['group'] = 'none';
268:                 $file['owner'] = $owner;
269:                 $file['date'] = 0;
270:                 $file['perms'] = 'rwxrwx---';
271: 
272:                 $files[$file['name']] = $file;
273:             }
274: 
275:             return $files;
276:         }
277: 
278:         $owner = $GLOBALS['registry']->getAuth();
279: 
280:         $file = $files = array();
281: 
282:         $folders = $this->listFolders($path, $filter, $dotfiles);
283:         $list = $this->_getFolders();
284: 
285:         foreach ($folders as $folder) {
286:             $file['type'] = '**dir';
287:             $file['size'] = -1;
288:             $file['name'] = $folder['abbrev'];
289:             //FIXME
290:             $file['group'] = 'none';
291:             //FIXME
292:             $file['owner'] = $owner;
293:             //FIXME
294:             $file['date'] = 0;
295:             //FIXME
296:             $file['perms'] = 'rwxrwx---';
297: 
298:             $files[$file['name']] = $file;
299:         }
300: 
301:         if (!$dironly &&
302:             $this->isFolder(basename($path), basename($path)) &&
303:             !empty($list[$path])) {
304:             $session = Horde_Kolab_Session::singleton();
305:             $imap = $session->getImap();
306: 
307:             $result = $imap->select(substr($path, 1));
308:             if ($result instanceof PEAR_Error) {
309:                 throw new Horde_Vfs_Exception($result->getMessage());
310:             }
311: 
312:             $uids = $imap->getUids();
313:             if ($uids instanceof PEAR_Error) {
314:                 throw new Horde_Vfs_Exception($uids->getMessage());
315:             }
316: 
317:             foreach ($uids as $uid) {
318:                 $result = array_merge($files, $this->_parseMessage($imap, $uid));
319:                 $files = $result;
320:             }
321:         }
322: 
323:         return $files;
324:     }
325: 
326:     /**
327:      */
328:     protected function _parseMessage($imap, $uid)
329:     {
330:         $result = $imap->getMessageHeader($uid);
331:         if ($result instanceof PEAR_Error) {
332:             throw new Horde_Vfs_Exception($result->getMessage());
333:         }
334: 
335:         $raw_headers = $result;
336: 
337:         $body = $imap->getMessageBody($uid);
338:         if ($body instanceof PEAR_Error) {
339:             throw new Horde_Vfs_Exception($body->getMessage());
340:         }
341: 
342:         $raw_message = $raw_headers . $body;
343: 
344:         $mime_message = Horde_Mime_Part::parseMessage($raw_message);
345:         $parts = $mime_message->contentTypeMap();
346: 
347:         $owner = $GLOBALS['registry']->getAuth();
348: 
349:         $file = $files = array();
350: 
351:         foreach ($parts as $part_id => $disposition) {
352:             $part = $mime_message->getPart($part_id);
353: 
354:             $filename = $part->getDispositionParameter('filename');
355: 
356:             if ($filename) {
357:                 $file['type'] = '**file';
358:                 $file['size'] = $part->getSize();
359:                 $file['name'] = $uid . '/' . $filename;
360:                 //FIXME
361:                 $file['group'] = 'none';
362:                 //FIXME
363:                 $file['owner'] = $owner;
364:                 //FIXME
365:                 $file['date'] = 0;
366:                 //FIXME
367:                 $file['perms'] = 'rwxrwx---';
368: 
369:                 $files[$file['name']] = $file;
370:             }
371: 
372:         }
373: 
374:         return $files;
375:     }
376: 
377:     /**
378:      */
379:     protected function _getFile($imap, $uid, $filename)
380:     {
381:         $result = $imap->getMessageHeader($uid);
382:         if ($result instanceof PEAR_Error) {
383:             throw new Horde_Vfs_Exception($result->getMessage());
384:         }
385: 
386:         $raw_headers = $result;
387: 
388:         $body = $imap->getMessageBody($uid);
389:         if ($body instanceof PEAR_Error) {
390:             throw new Horde_Vfs_Exception($body->getMessage());
391:         }
392: 
393:         $raw_message = $raw_headers . $body;
394: 
395:         $mime_message = Horde_Mime_Part::parseMessage($raw_message);
396:         $parts = $mime_message->contentTypeMap();
397: 
398:         $owner = $GLOBALS['registry']->getAuth();
399: 
400:         foreach ($parts as $part_id => $disposition) {
401:             $part = $mime_message->getPart($part_id);
402: 
403:             $f = $part->getDispositionParameter('filename');
404:             if ($f && $f == $filename) {
405:                 return $part->transferDecode();
406:             }
407:         }
408: 
409:         return '';
410:     }
411: 
412:     /**
413:      * Returns a sorted list of folders in the specified directory.
414:      *
415:      * @param string $path         The path of the directory to get the
416:      *                             directory list for.
417:      * @param mixed $filter        Hash of items to filter based on folderlist.
418:      * @param boolean $dotfolders  Include dotfolders?
419:      *
420:      * @return array  Folder list.
421:      * @throws Horde_Vfs_Exception
422:      */
423:     public function listFolders($path = '', $filter = null, $dotfolders = true)
424:     {
425:         if (substr($path, -1) != '/') {
426:             $path .= '/';
427:         }
428: 
429:         $aFolder = $aFolders = array();
430: 
431:         if ($dotfolders && $path != '/') {
432:             $aFolder['val'] = dirname($path);
433:             $aFolder['abbrev'] = '..';
434:             $aFolder['label'] = '..';
435: 
436:             $aFolders[$aFolder['val']] = $aFolder;
437:         }
438: 
439:         $folders = $this->_getFolders();
440: 
441:         $base_len = strlen($path);
442:         foreach (array_keys($folders) as $folder) {
443:             if (substr($folder, 0, $base_len) == $path) {
444:                 $name = substr($folder, $base_len);
445:                 if (!strpos($name, '/')) {
446:                     $aFolder['val'] = $folder;
447:                     $aFolder['abbrev'] = $name;
448:                     $aFolder['label'] = $folder;
449:                     $aFolders[$aFolder['val']] = $aFolder;
450:                 }
451:             }
452:         }
453: 
454:         ksort($aFolders);
455:         return $aFolders;
456:     }
457: 
458:     /**
459:      */
460:     protected function _getFolder($path, $name)
461:     {
462:         $folder = $path . '/' . $name;
463: 
464:         while (substr($folder, 0, 1) == '/') {
465:             $folder = substr($folder, 1);
466:         }
467: 
468:         while (substr($folder, -1) == '/') {
469:             $folder = substr($folder, 0, -1);
470:         }
471: 
472:         return $folder;
473:     }
474: 
475:     /**
476:      */
477:     protected function _getFolders()
478:     {
479:         if (!isset($this->_folders)) {
480:             $vfs_folders = array();
481: 
482:             $list = Kolab_List::singleton();
483: 
484:             if (!empty($this->_params['all_folders'])) {
485:                 $folders = $list->getFolders();
486:             } else {
487:                 $folders = $list->getByType('h-file');
488:             }
489: 
490:             if ($folders instanceof PEAR_Error) {
491:                 throw new Horde_Vfs_Exception($folders->getMessage());
492:             }
493: 
494:             foreach ($folders as $folder) {
495:                 $vfs_folders['/' . $folder->name] = &$folder;
496:             }
497: 
498:             foreach (array_keys($vfs_folders) as $name) {
499:                 $dir = dirname($name);
500:                 while ($dir != '/') {
501:                     if (!isset($vfs_folders[$dir])) {
502:                         $vfs_folders[$dir] = null;
503:                     }
504:                     $dir = dirname($dir);
505:                 }
506:             }
507:             $this->_folders = $vfs_folders;
508:         }
509: 
510:         return $this->_folders;
511:     }
512: 
513:     /**
514:      */
515:     protected function _getAppUid($path)
516:     {
517:         if (defined('TURBA_VFS_PATH') &&
518:             substr($path, 0, strlen(TURBA_VFS_PATH)) == TURBA_VFS_PATH) {
519:             return array('turba', substr($path, strlen(TURBA_VFS_PATH) + 1));
520:         }
521: 
522:         return array(false, false);
523:     }
524: 
525:     /**
526:      */
527:     protected function _getAppHandler($app, $uid)
528:     {
529:         global $registry;
530: 
531:         switch ($app) {
532:         case 'turba':
533:             $sources = $registry->call('contacts/sources',
534:                                        array('writeable' => true));
535:             $fields = array();
536:             foreach (array_keys($sources) as $source) {
537:                 $fields[$source] = array('__uid');
538:             }
539:             $result = $registry->call('contacts/search',
540:                                       array('names' => $uid,
541:                                             'sources' => array_keys($sources),
542:                                             'fields' => $fields));
543:             if (!isset($result[$uid])) {
544:                 throw new Horde_Vfs_Exception('No such contact!');
545:             }
546:             $list = Kolab_List::singleton();
547:             $share = $list->getByShare($result[$uid][0]['source'], 'contact');
548:             if ($share instanceof PEAR_Error) {
549:                 throw new Horde_Vfs_Exception($share->getMessage());
550:             }
551:             return $share->getData();
552:         }
553:     }
554: 
555:     /**
556:      */
557:     protected function _getAppUids($app)
558:     {
559:         global $registry;
560: 
561:         switch ($app) {
562:         case 'turba':
563:             $sources = $registry->call('contacts/sources',
564:                                        array('writeable' => true));
565:             $result = $registry->call('contacts/search',
566:                                       array('names' => '',
567:                                             'sources' => array_keys($sources),
568:                                             'fields' => array()));
569:             $uids = array();
570:             foreach ($result[''] as $contact) {
571:                 if (isset($contact['__uid'])) {
572:                     $uids[] = $contact['__uid'];
573:                 }
574:             }
575:             return $uids;
576:         }
577:     }
578: 
579: }
580: 
API documentation generated by ApiGen