Check (expected) folder type and disable access to folder contents or cache if invalid (#4378)

This commit is contained in:
Thomas Bruederli 2015-01-29 16:48:42 +01:00
parent 44216168f1
commit 038e269d51
3 changed files with 80 additions and 27 deletions

View file

@ -154,7 +154,7 @@ class kolab_storage
if (self::setup()) { if (self::setup()) {
foreach ((array)self::list_folders('', '*', $type, $subscribed, $folderdata) as $foldername) { foreach ((array)self::list_folders('', '*', $type, $subscribed, $folderdata) as $foldername) {
$folders[$foldername] = new kolab_storage_folder($foldername, $folderdata[$foldername]); $folders[$foldername] = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]);
} }
} }
@ -171,7 +171,7 @@ class kolab_storage
{ {
if (self::setup()) { if (self::setup()) {
foreach ((array)self::list_folders('', '*', $type . '.default', false, $folderdata) as $foldername) { foreach ((array)self::list_folders('', '*', $type . '.default', false, $folderdata) as $foldername) {
return new kolab_storage_folder($foldername, $folderdata[$foldername]); return new kolab_storage_folder($foldername, $type, $folderdata[$foldername]);
} }
} }
@ -203,11 +203,11 @@ class kolab_storage
{ {
self::setup(); self::setup();
$folder = null; $folder = null;
foreach ((array)self::list_folders('', '*', $type) as $foldername) { foreach ((array)self::list_folders('', '*', $type, null, $folderdata) as $foldername) {
if (!$folder) if (!$folder)
$folder = new kolab_storage_folder($foldername); $folder = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]);
else else
$folder->set_folder($foldername); $folder->set_folder($foldername, $type, $folderdata[$foldername]);
if ($object = $folder->get_object($uid, '*')) if ($object = $folder->get_object($uid, '*'))
return $object; return $object;
@ -230,11 +230,11 @@ class kolab_storage
$folder = null; $folder = null;
$result = array(); $result = array();
foreach ((array)self::list_folders('', '*', $type) as $foldername) { foreach ((array)self::list_folders('', '*', $type, null, $folderdata) as $foldername) {
if (!$folder) if (!$folder)
$folder = new kolab_storage_folder($foldername); $folder = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]);
else else
$folder->set_folder($foldername); $folder->set_folder($foldername, $type, $folderdata[$foldername]);
foreach ($folder->select($query, '*') as $object) { foreach ($folder->select($query, '*') as $object) {
$result[] = $object; $result[] = $object;
@ -901,7 +901,7 @@ class kolab_storage
!self::folder_is_subscribed($foldername, true) && !self::folder_is_subscribed($foldername, true) &&
!in_array(self::$imap->folder_namespace($foldername), (array)$exclude_ns) !in_array(self::$imap->folder_namespace($foldername), (array)$exclude_ns)
) { ) {
$folders[] = new kolab_storage_folder($foldername, $folderdata[$foldername]); $folders[] = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]);
} }
} }
@ -974,7 +974,7 @@ class kolab_storage
$parent_parent = join($delim, $path); $parent_parent = join($delim, $path);
if (!$refs[$parent]) { if (!$refs[$parent]) {
if ($folder->type && self::folder_type($parent) == $folder->type) { if ($folder->type && self::folder_type($parent) == $folder->type) {
$refs[$parent] = new kolab_storage_folder($parent, $folder->type); $refs[$parent] = new kolab_storage_folder($parent, $folder->type, $folder->type);
$refs[$parent]->parent = $parent_parent; $refs[$parent]->parent = $parent_parent;
} }
else if ($parent_parent == $other_ns) { else if ($parent_parent == $other_ns) {
@ -1542,7 +1542,7 @@ class kolab_storage
foreach ($folders as $userfolder) { foreach ($folders as $userfolder) {
foreach ((array)self::list_folders($userfolder->name . $delimiter, '*', $type, false, $folderdata) as $foldername) { foreach ((array)self::list_folders($userfolder->name . $delimiter, '*', $type, false, $folderdata) as $foldername) {
if (!$folders[$foldername]) { if (!$folders[$foldername]) {
$folders[$foldername] = new kolab_storage_folder($foldername, $folderdata[$foldername]); $folders[$foldername] = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]);
$userfolder->children[] = $folders[$foldername]; $userfolder->children[] = $folders[$foldername];
} }
} }

View file

@ -80,6 +80,7 @@ class kolab_storage_cache
$this->db = $rcmail->get_dbh(); $this->db = $rcmail->get_dbh();
$this->imap = $rcmail->get_storage(); $this->imap = $rcmail->get_storage();
$this->enabled = $rcmail->config->get('kolab_cache', false); $this->enabled = $rcmail->config->get('kolab_cache', false);
$this->folders_table = $this->db->table_name('kolab_folders');
if ($this->enabled) { if ($this->enabled) {
// always read folder cache and lock state from DB master // always read folder cache and lock state from DB master
@ -98,8 +99,7 @@ class kolab_storage_cache
*/ */
public function select_by_id($folder_id) public function select_by_id($folder_id)
{ {
$folders_table = $this->db->table_name('kolab_folders', true); $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT * FROM `{$this->cache_table}` WHERE `folder_id` = ?", $folder_id));
$sql_arr = $this->db->fetch_assoc($this->db->query("SELECT * FROM $folders_table WHERE `folder_id` = ?", $folder_id));
if ($sql_arr) { if ($sql_arr) {
$this->metadata = $sql_arr; $this->metadata = $sql_arr;
$this->folder_id = $sql_arr['folder_id']; $this->folder_id = $sql_arr['folder_id'];
@ -120,14 +120,13 @@ class kolab_storage_cache
{ {
$this->folder = $storage_folder; $this->folder = $storage_folder;
if (empty($this->folder->name)) { if (empty($this->folder->name) || !$this->folder->valid) {
$this->ready = false; $this->ready = false;
return; return;
} }
// compose fully qualified ressource uri for this instance // compose fully qualified ressource uri for this instance
$this->resource_uri = $this->folder->get_resource_uri(); $this->resource_uri = $this->folder->get_resource_uri();
$this->folders_table = $this->db->table_name('kolab_folders');
$this->cache_table = $this->db->table_name('kolab_cache_' . $this->folder->type); $this->cache_table = $this->db->table_name('kolab_cache_' . $this->folder->type);
$this->ready = $this->enabled && !empty($this->folder->type); $this->ready = $this->enabled && !empty($this->folder->type);
$this->folder_id = null; $this->folder_id = null;

View file

@ -30,14 +30,22 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public $cache; public $cache;
private $type_annotation; /**
* Indicate validity status
* @var boolean
*/
public $valid = false;
private $resource_uri; private $resource_uri;
/** /**
* Default constructor * Default constructor
*
* @param string The folder name/path
* @param string Expected folder type
*/ */
function __construct($name, $type = null) function __construct($name, $type = null, $type_annotation = null)
{ {
parent::__construct($name); parent::__construct($name);
$this->imap->set_options(array('skip_deleted' => true)); $this->imap->set_options(array('skip_deleted' => true));
@ -49,28 +57,31 @@ class kolab_storage_folder extends kolab_storage_folder_api
* Set the IMAP folder this instance connects to * Set the IMAP folder this instance connects to
* *
* @param string The folder name/path * @param string The folder name/path
* @param string Expected folder type
* @param string Optional folder type if known * @param string Optional folder type if known
*/ */
public function set_folder($name, $type = null) public function set_folder($name, $type = null, $type_annotation = null)
{ {
$this->type_annotation = $type ? $type : kolab_storage::folder_type($name); if (empty($type_annotation)) {
$type_annotation = kolab_storage::folder_type($name);
}
$oldtype = $this->type; $oldtype = $this->type;
list($this->type, $suffix) = explode('.', $this->type_annotation); list($this->type, $suffix) = explode('.', $type_annotation);
$this->default = $suffix == 'default'; $this->default = $suffix == 'default';
$this->subtype = $this->default ? '' : $suffix; $this->subtype = $this->default ? '' : $suffix;
$this->name = $name; $this->name = $name;
$this->id = kolab_storage::folder_id($name); $this->id = kolab_storage::folder_id($name);
$this->valid = !empty($this->type) && $this->type != 'mail' && (!$type || $this->type == $type);
// reset cached object properties // reset cached object properties
$this->owner = $this->namespace = $this->resource_uri = $this->info = $this->idata = null; $this->owner = $this->namespace = $this->resource_uri = $this->info = $this->idata = null;
// get a new cache instance of folder type changed // get a new cache instance if folder type changed
if (!$this->cache || $type != $oldtype) if (!$this->cache || $this->type != $oldtype)
$this->cache = kolab_storage_cache::factory($this); $this->cache = kolab_storage_cache::factory($this);
$this->imap->set_folder($this->name); $this->imap->set_folder($this->name);
$this->cache->set_folder($this);
} }
@ -204,6 +215,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function count($query = null) public function count($query = null)
{ {
if (!$this->valid) {
return 0;
}
// synchronize cache first // synchronize cache first
$this->cache->synchronize(); $this->cache->synchronize();
@ -221,6 +236,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
{ {
if (!$type) $type = $this->type; if (!$type) $type = $this->type;
if (!$this->valid) {
return array();
}
// synchronize caches // synchronize caches
$this->cache->synchronize(); $this->cache->synchronize();
@ -238,9 +257,14 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function select($query = array()) public function select($query = array())
{ {
if (!$this->valid) {
return array();
}
// check query argument // check query argument
if (empty($query)) if (empty($query)) {
return $this->get_objects(); return $this->get_objects();
}
// synchronize caches // synchronize caches
$this->cache->synchronize(); $this->cache->synchronize();
@ -258,6 +282,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function get_uids($query = array()) public function get_uids($query = array())
{ {
if (!$this->valid) {
return array();
}
// synchronize caches // synchronize caches
$this->cache->synchronize(); $this->cache->synchronize();
@ -319,6 +347,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function get_object($uid, $type = null) public function get_object($uid, $type = null)
{ {
if (!$this->valid) {
return false;
}
// synchronize caches // synchronize caches
$this->cache->synchronize(); $this->cache->synchronize();
@ -348,7 +380,7 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function get_attachment($uid, $part, $mailbox = null, $print = false, $fp = null, $skip_charset_conv = false) public function get_attachment($uid, $part, $mailbox = null, $print = false, $fp = null, $skip_charset_conv = false)
{ {
if ($msguid = ($mailbox ? $uid : $this->cache->uid2msguid($uid))) { if ($this->valid && ($msguid = ($mailbox ? $uid : $this->cache->uid2msguid($uid)))) {
$this->imap->set_folder($mailbox ? $mailbox : $this->name); $this->imap->set_folder($mailbox ? $mailbox : $this->name);
if (substr($part, 0, 2) == 'i:') { if (substr($part, 0, 2) == 'i:') {
@ -392,6 +424,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function read_object($msguid, $type = null, $folder = null) public function read_object($msguid, $type = null, $folder = null)
{ {
if (!$this->valid) {
return false;
}
if (!$type) $type = $this->type; if (!$type) $type = $this->type;
if (!$folder) $folder = $this->name; if (!$folder) $folder = $this->name;
@ -537,6 +573,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function save(&$object, $type = null, $uid = null) public function save(&$object, $type = null, $uid = null)
{ {
if (!$this->valid) {
return false;
}
if (!$type) if (!$type)
$type = $this->type; $type = $this->type;
@ -732,6 +772,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function delete($object, $expunge = true) public function delete($object, $expunge = true)
{ {
if (!$this->valid) {
return false;
}
$msguid = is_array($object) ? $object['_msguid'] : $this->cache->uid2msguid($object); $msguid = is_array($object) ? $object['_msguid'] : $this->cache->uid2msguid($object);
$success = false; $success = false;
@ -759,6 +803,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function delete_all() public function delete_all()
{ {
if (!$this->valid) {
return false;
}
$this->cache->purge(); $this->cache->purge();
$this->cache->bypass(true); $this->cache->bypass(true);
$result = $this->imap->clear_folder($this->name); $result = $this->imap->clear_folder($this->name);
@ -776,6 +824,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function undelete($uid) public function undelete($uid)
{ {
if (!$this->valid) {
return false;
}
if ($msguid = $this->cache->uid2msguid($uid, true)) { if ($msguid = $this->cache->uid2msguid($uid, true)) {
$this->cache->bypass(true); $this->cache->bypass(true);
$result = $this->imap->set_flag($msguid, 'UNDELETED', $this->name); $result = $this->imap->set_flag($msguid, 'UNDELETED', $this->name);
@ -799,6 +851,10 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
public function move($uid, $target_folder) public function move($uid, $target_folder)
{ {
if (!$this->valid) {
return false;
}
if (is_string($target_folder)) if (is_string($target_folder))
$target_folder = kolab_storage::get_folder($target_folder); $target_folder = kolab_storage::get_folder($target_folder);
@ -1054,8 +1110,6 @@ class kolab_storage_folder extends kolab_storage_folder_api
*/ */
private function trigger_url($url, $auth_user = null, $auth_passwd = null) private function trigger_url($url, $auth_user = null, $auth_passwd = null)
{ {
require_once('HTTP/Request2.php');
try { try {
$request = libkolab::http_request($url); $request = libkolab::http_request($url);