VFS
[ class tree: VFS ] [ index: VFS ] [ all elements ]

Source for file kolab.php

Documentation is available at kolab.php

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

Documentation generated on Mon, 11 Mar 2019 15:34:54 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.