Changeset View
Changeset View
Standalone View
Standalone View
plugins/libkolab/lib/kolab_storage_dav.php
- This file was added.
<?php | |||||
/** | |||||
* Kolab storage class providing access to groupware objects on a *DAV server. | |||||
* | |||||
* @author Aleksander Machniak <machniak@apheleia-it.ch> | |||||
* | |||||
* Copyright (C) 2022, Apheleia IT AG <contact@apheleia-it.ch> | |||||
* | |||||
* This program is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU Affero General Public License as | |||||
* published by the Free Software Foundation, either version 3 of the | |||||
* License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU Affero General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Affero General Public License | |||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
class kolab_storage_dav | |||||
{ | |||||
const ERROR_DAV_CONN = 1; | |||||
const ERROR_CACHE_DB = 2; | |||||
const ERROR_NO_PERMISSION = 3; | |||||
const ERROR_INVALID_FOLDER = 4; | |||||
protected $dav; | |||||
protected $url; | |||||
/** | |||||
* Object constructor | |||||
*/ | |||||
public function __construct($url) | |||||
{ | |||||
$this->url = $url; | |||||
$this->setup(); | |||||
} | |||||
/** | |||||
* Setup the environment | |||||
*/ | |||||
public function setup() | |||||
{ | |||||
$rcmail = rcube::get_instance(); | |||||
$this->config = $rcmail->config; | |||||
$this->dav = new kolab_dav_client($this->url); | |||||
} | |||||
/** | |||||
* Get a list of storage folders for the given data type | |||||
* | |||||
* @param string Data type to list folders for (contact,distribution-list,event,task,note) | |||||
* | |||||
* @return array List of kolab_storage_dav_folder objects | |||||
*/ | |||||
public function get_folders($type) | |||||
{ | |||||
$davTypes = [ | |||||
'event' => 'VEVENT', | |||||
'task' => 'VTODO', | |||||
'contact' => 'VCARD', | |||||
]; | |||||
// TODO: This should be cached | |||||
$folders = $this->dav->discover($davTypes[$type]); | |||||
if (is_array($folders)) { | |||||
foreach ($folders as $idx => $folder) { | |||||
// Exclude some special folders | |||||
if (in_array('schedule-inbox', $folder['resource_type']) || in_array('schedule-outbox', $folder['resource_type'])) { | |||||
unset($folders[$idx]); | |||||
continue; | |||||
} | |||||
$folders[$idx] = new kolab_storage_dav_folder($this->dav, $folder, $type); | |||||
} | |||||
} | |||||
return $folders ?: []; | |||||
} | |||||
/** | |||||
* Getter for the storage folder for the given type | |||||
* | |||||
* @param string Data type to list folders for (contact,distribution-list,event,task,note) | |||||
* | |||||
* @return object kolab_storage_dav_folder The folder object | |||||
*/ | |||||
public function get_default_folder($type) | |||||
{ | |||||
// TODO: Not used | |||||
} | |||||
/** | |||||
* Getter for a specific storage folder | |||||
* | |||||
* @param string $id Folder to access | |||||
* @param string $type Expected folder type | |||||
* | |||||
* @return ?object kolab_storage_folder The folder object | |||||
*/ | |||||
public function get_folder($id, $type = null) | |||||
{ | |||||
foreach ($this->get_folders($type) as $folder) { | |||||
if ($folder->id == $id) { | |||||
return $folder; | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Getter for a single Kolab object, identified by its UID. | |||||
* This will search all folders storing objects of the given type. | |||||
* | |||||
* @param string Object UID | |||||
* @param string Object type (contact,event,task,journal,file,note,configuration) | |||||
* | |||||
* @return array The Kolab object represented as hash array or false if not found | |||||
*/ | |||||
public function get_object($uid, $type) | |||||
{ | |||||
// TODO | |||||
return false; | |||||
} | |||||
/** | |||||
* Execute cross-folder searches with the given query. | |||||
* | |||||
* @param array Pseudo-SQL query as list of filter parameter triplets | |||||
* @param string Folder type (contact,event,task,journal,file,note,configuration) | |||||
* @param int Expected number of records or limit (for performance reasons) | |||||
* | |||||
* @return array List of Kolab data objects (each represented as hash array) | |||||
*/ | |||||
public function select($query, $type, $limit = null) | |||||
{ | |||||
$result = []; | |||||
foreach ($this->get_folders($type) as $folder) { | |||||
if ($limit) { | |||||
$folder->set_order_and_limit(null, $limit); | |||||
} | |||||
foreach ($folder->select($query) as $object) { | |||||
$result[] = $object; | |||||
} | |||||
} | |||||
return $result; | |||||
} | |||||
/** | |||||
* Compose an URL to query the free/busy status for the given user | |||||
* | |||||
* @param string Email address of the user to get free/busy data for | |||||
* @param object DateTime Start of the query range (optional) | |||||
* @param object DateTime End of the query range (optional) | |||||
* | |||||
* @return string Fully qualified URL to query free/busy data | |||||
*/ | |||||
public static function get_freebusy_url($email, $start = null, $end = null) | |||||
{ | |||||
return kolab_storage::get_freebusy_url($email, $start, $end); | |||||
} | |||||
/** | |||||
* Deletes a folder | |||||
* | |||||
* @param string $name Folder name | |||||
* | |||||
* @return bool True on success, false on failure | |||||
*/ | |||||
public function folder_delete($name) | |||||
{ | |||||
// TODO | |||||
} | |||||
/** | |||||
* Creates a folder | |||||
* | |||||
* @param string $name Folder name (UTF7-IMAP) | |||||
* @param string $type Folder type | |||||
* @param bool $subscribed Sets folder subscription | |||||
* @param bool $active Sets folder state (client-side subscription) | |||||
* | |||||
* @return bool True on success, false on failure | |||||
*/ | |||||
public function folder_create($name, $type = null, $subscribed = false, $active = false) | |||||
{ | |||||
// TODO | |||||
} | |||||
/** | |||||
* Renames DAV folder | |||||
* | |||||
* @param string $oldname Old folder name (UTF7-IMAP) | |||||
* @param string $newname New folder name (UTF7-IMAP) | |||||
* | |||||
* @return bool True on success, false on failure | |||||
*/ | |||||
public function folder_rename($oldname, $newname) | |||||
{ | |||||
// TODO | |||||
} | |||||
/** | |||||
* Rename or Create a new folder. | |||||
* | |||||
* Does additional checks for permissions and folder name restrictions | |||||
* | |||||
* @param array &$prop Hash array with folder properties and metadata | |||||
* - name: Folder name | |||||
* - oldname: Old folder name when changed | |||||
* - parent: Parent folder to create the new one in | |||||
* - type: Folder type to create | |||||
* - subscribed: Subscribed flag (IMAP subscription) | |||||
* - active: Activation flag (client-side subscription) | |||||
* | |||||
* @return string|false New folder name or False on failure | |||||
*/ | |||||
public function folder_update(&$prop) | |||||
{ | |||||
// TODO | |||||
} | |||||
/** | |||||
* Getter for human-readable name of a folder | |||||
* | |||||
* @param string $folder Folder name (UTF7-IMAP) | |||||
* @param string $folder_ns Will be set to namespace name of the folder | |||||
* | |||||
* @return string Name of the folder-object | |||||
*/ | |||||
public static function object_name($folder, &$folder_ns = null) | |||||
{ | |||||
// TODO: Shared folders | |||||
$folder_ns = 'personal'; | |||||
return $folder; | |||||
} | |||||
/** | |||||
* Creates a SELECT field with folders list | |||||
* | |||||
* @param string $type Folder type | |||||
* @param array $attrs SELECT field attributes (e.g. name) | |||||
* @param string $current The name of current folder (to skip it) | |||||
* | |||||
* @return html_select SELECT object | |||||
*/ | |||||
public function folder_selector($type, $attrs, $current = '') | |||||
{ | |||||
// TODO | |||||
} | |||||
/** | |||||
* Returns a list of folder names | |||||
* | |||||
* @param string Optional root folder | |||||
* @param string Optional name pattern | |||||
* @param string Data type to list folders for (contact,event,task,journal,file,note,mail,configuration) | |||||
* @param bool Enable to return subscribed folders only (null to use configured subscription mode) | |||||
* @param array Will be filled with folder-types data | |||||
* | |||||
* @return array List of folders | |||||
*/ | |||||
public function list_folders($root = '', $mbox = '*', $filter = null, $subscribed = null, &$folderdata = array()) | |||||
{ | |||||
// TODO | |||||
} | |||||
/** | |||||
* Search for shared or otherwise not listed groupware folders the user has access | |||||
* | |||||
* @param string Folder type of folders to search for | |||||
* @param string Search string | |||||
* @param array Namespace(s) to exclude results from | |||||
* | |||||
* @return array List of matching kolab_storage_folder objects | |||||
*/ | |||||
public function search_folders($type, $query, $exclude_ns = []) | |||||
{ | |||||
// TODO | |||||
return []; | |||||
} | |||||
/** | |||||
* Sort the given list of folders by namespace/name | |||||
* | |||||
* @param array List of kolab_storage_dav_folder objects | |||||
* | |||||
* @return array Sorted list of folders | |||||
*/ | |||||
public static function sort_folders($folders) | |||||
{ | |||||
// TODO | |||||
return $folders; | |||||
} | |||||
/** | |||||
* Returns folder types indexed by folder name | |||||
* | |||||
* @param string $prefix Folder prefix (Default '*' for all folders) | |||||
* | |||||
* @return array|bool List of folders, False on failure | |||||
*/ | |||||
public function folders_typedata($prefix = '*') | |||||
{ | |||||
// TODO: Used by kolab_folders, kolab_activesync, kolab_delegation | |||||
return []; | |||||
} | |||||
/** | |||||
* Returns type of a DAV folder | |||||
* | |||||
* @param string $folder Folder name (UTF7-IMAP) | |||||
* | |||||
* @return string Folder type | |||||
*/ | |||||
public function folder_type($folder) | |||||
{ | |||||
// TODO: Used by kolab_folders, kolab_activesync, kolab_delegation | |||||
return 'event'; | |||||
} | |||||
/** | |||||
* Sets folder content-type. | |||||
* | |||||
* @param string $folder Folder name | |||||
* @param string $type Content type | |||||
* | |||||
* @return bool True on success, False otherwise | |||||
*/ | |||||
public function set_folder_type($folder, $type = 'mail') | |||||
{ | |||||
// NOP: Used by kolab_folders, kolab_activesync, kolab_delegation | |||||
return false; | |||||
} | |||||
/** | |||||
* Check subscription status of this folder | |||||
* | |||||
* @param string $folder Folder name | |||||
* @param bool $temp Include temporary/session subscriptions | |||||
* | |||||
* @return bool True if subscribed, false if not | |||||
*/ | |||||
public function folder_is_subscribed($folder, $temp = false) | |||||
{ | |||||
// NOP | |||||
return true; | |||||
} | |||||
/** | |||||
* Change subscription status of this folder | |||||
* | |||||
* @param string $folder Folder name | |||||
* @param bool $temp Only subscribe temporarily for the current session | |||||
* | |||||
* @return True on success, false on error | |||||
*/ | |||||
public function folder_subscribe($folder, $temp = false) | |||||
{ | |||||
// NOP | |||||
return true; | |||||
} | |||||
/** | |||||
* Change subscription status of this folder | |||||
* | |||||
* @param string $folder Folder name | |||||
* @param bool $temp Only remove temporary subscription | |||||
* | |||||
* @return True on success, false on error | |||||
*/ | |||||
public function folder_unsubscribe($folder, $temp = false) | |||||
{ | |||||
// NOP | |||||
return false; | |||||
} | |||||
/** | |||||
* Check activation status of this folder | |||||
* | |||||
* @param string $folder Folder name | |||||
* | |||||
* @return bool True if active, false if not | |||||
*/ | |||||
public function folder_is_active($folder) | |||||
{ | |||||
// TODO | |||||
return true; | |||||
} | |||||
/** | |||||
* Change activation status of this folder | |||||
* | |||||
* @param string $folder Folder name | |||||
* | |||||
* @return True on success, false on error | |||||
*/ | |||||
public function folder_activate($folder) | |||||
{ | |||||
return true; | |||||
} | |||||
/** | |||||
* Change activation status of this folder | |||||
* | |||||
* @param string $folder Folder name | |||||
* | |||||
* @return True on success, false on error | |||||
*/ | |||||
public function folder_deactivate($folder) | |||||
{ | |||||
return false; | |||||
} | |||||
/** | |||||
* Creates default folder of specified type | |||||
* To be run when none of subscribed folders (of specified type) is found | |||||
* | |||||
* @param string $type Folder type | |||||
* @param string $props Folder properties (color, etc) | |||||
* | |||||
* @return string Folder name | |||||
*/ | |||||
public function create_default_folder($type, $props = []) | |||||
{ | |||||
// TODO: For kolab_addressbook?? | |||||
return ''; | |||||
} | |||||
/** | |||||
* Returns a list of IMAP folders shared by the given user | |||||
* | |||||
* @param array User entry from LDAP | |||||
* @param string Data type to list folders for (contact,event,task,journal,file,note,mail,configuration) | |||||
* @param int 1 - subscribed folders only, 0 - all folders, 2 - all non-active | |||||
* @param array Will be filled with folder-types data | |||||
* | |||||
* @return array List of folders | |||||
*/ | |||||
public function list_user_folders($user, $type, $subscribed = 0, &$folderdata = []) | |||||
{ | |||||
// TODO | |||||
return []; | |||||
} | |||||
/** | |||||
* Get a list of (virtual) top-level folders from the other users namespace | |||||
* | |||||
* @param string Data type to list folders for (contact,event,task,journal,file,note,mail,configuration) | |||||
* @param bool Enable to return subscribed folders only (null to use configured subscription mode) | |||||
* | |||||
* @return array List of kolab_storage_folder_user objects | |||||
*/ | |||||
public function get_user_folders($type, $subscribed) | |||||
{ | |||||
// TODO | |||||
return []; | |||||
} | |||||
/** | |||||
* Handler for user_delete plugin hooks | |||||
* | |||||
* Remove all cache data from the local database related to the given user. | |||||
*/ | |||||
public static function delete_user_folders($args) | |||||
{ | |||||
$db = rcmail::get_instance()->get_dbh(); | |||||
$table = $db->table_name('kolab_folders', true); | |||||
$prefix = 'dav://' . urlencode($args['username']) . '@' . $args['host'] . '/%'; | |||||
$db->query("DELETE FROM $table WHERE `resource` LIKE ?", $prefix); | |||||
} | |||||
/** | |||||
* Get folder METADATA for all supported keys | |||||
* Do this in one go for better caching performance | |||||
*/ | |||||
public function folder_metadata($folder) | |||||
{ | |||||
// TODO ? | |||||
return []; | |||||
} | |||||
} |