Merge remote-tracking branch 'origin/libkolab-cache-bypass' into dev/kolab-cache-refactoring
This commit is contained in:
commit
6b89e36c4e
4 changed files with 149 additions and 18 deletions
|
@ -339,6 +339,16 @@ class kolab_auth extends rcube_plugin
|
||||||
$ldap = self::ldap();
|
$ldap = self::ldap();
|
||||||
if (!$ldap || !$ldap->ready) {
|
if (!$ldap || !$ldap->ready) {
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
|
$message = sprintf(
|
||||||
|
'Login failure for user %s from %s in session %s (error %s)',
|
||||||
|
$user,
|
||||||
|
rcube_utils::remote_ip(),
|
||||||
|
session_id(),
|
||||||
|
"LDAP not ready"
|
||||||
|
);
|
||||||
|
|
||||||
|
rcube::write_log('userlogins', $message);
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,6 +357,16 @@ class kolab_auth extends rcube_plugin
|
||||||
|
|
||||||
if (empty($record)) {
|
if (empty($record)) {
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
|
$message = sprintf(
|
||||||
|
'Login failure for user %s from %s in session %s (error %s)',
|
||||||
|
$user,
|
||||||
|
rcube_utils::remote_ip(),
|
||||||
|
session_id(),
|
||||||
|
"No user record found"
|
||||||
|
);
|
||||||
|
|
||||||
|
rcube::write_log('userlogins', $message);
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +400,16 @@ class kolab_auth extends rcube_plugin
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
|
$message = sprintf(
|
||||||
|
'Login failure for user %s from %s in session %s (error %s)',
|
||||||
|
$user,
|
||||||
|
rcube_utils::remote_ip(),
|
||||||
|
session_id(),
|
||||||
|
"Unable to bind with '" . $record['dn'] . "'"
|
||||||
|
);
|
||||||
|
|
||||||
|
rcube::write_log('userlogins', $message);
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,6 +451,17 @@ class kolab_auth extends rcube_plugin
|
||||||
|
|
||||||
if (empty($record)) {
|
if (empty($record)) {
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
|
$message = sprintf(
|
||||||
|
'Login failure for user %s (as user %s) from %s in session %s (error %s)',
|
||||||
|
$user,
|
||||||
|
$loginas,
|
||||||
|
rcube_utils::remote_ip(),
|
||||||
|
session_id(),
|
||||||
|
"No user record found for '" . $loginas . "'"
|
||||||
|
);
|
||||||
|
|
||||||
|
rcube::write_log('userlogins', $message);
|
||||||
|
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,9 @@ $rcmail_config['kolab_custom_display_names'] = false;
|
||||||
// See http://pear.php.net/manual/en/package.http.http-request2.config.php
|
// See http://pear.php.net/manual/en/package.http.http-request2.config.php
|
||||||
// for list of supported configuration options (array keys)
|
// for list of supported configuration options (array keys)
|
||||||
$rcmail_config['kolab_http_request'] = array();
|
$rcmail_config['kolab_http_request'] = array();
|
||||||
|
|
||||||
|
// When kolab_cache is enabled Roundcube's messages cache will be redundant
|
||||||
|
// when working on kolab folders. Here we can:
|
||||||
|
// 2 - bypass messages/indexes cache completely
|
||||||
|
// 1 - bypass only messages, but use index cache
|
||||||
|
$rcmail_config['kolab_messages_cache_bypass'] = 0;
|
||||||
|
|
|
@ -137,6 +137,9 @@ class kolab_storage_cache
|
||||||
// lock synchronization for this folder or wait if locked
|
// lock synchronization for this folder or wait if locked
|
||||||
$this->_sync_lock();
|
$this->_sync_lock();
|
||||||
|
|
||||||
|
// disable messages cache if configured to do so
|
||||||
|
$this->bypass(true);
|
||||||
|
|
||||||
// synchronize IMAP mailbox cache
|
// synchronize IMAP mailbox cache
|
||||||
$this->imap->folder_sync($this->folder->name);
|
$this->imap->folder_sync($this->folder->name);
|
||||||
|
|
||||||
|
@ -180,6 +183,8 @@ class kolab_storage_cache
|
||||||
$this->metadata['ctag'] = $this->folder->get_ctag();
|
$this->metadata['ctag'] = $this->folder->get_ctag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->bypass(false);
|
||||||
|
|
||||||
// remove lock
|
// remove lock
|
||||||
$this->_sync_unlock();
|
$this->_sync_unlock();
|
||||||
}
|
}
|
||||||
|
@ -577,8 +582,14 @@ class kolab_storage_cache
|
||||||
if (!$type)
|
if (!$type)
|
||||||
$type = $this->folder->type;
|
$type = $this->folder->type;
|
||||||
|
|
||||||
|
$this->bypass(true);
|
||||||
|
|
||||||
$results = array();
|
$results = array();
|
||||||
foreach ((array)$this->imap->fetch_headers($this->folder->name, $index, false) as $msguid => $headers) {
|
$headers = $this->imap->fetch_headers($this->folder->name, $index, false);
|
||||||
|
|
||||||
|
$this->bypass(false);
|
||||||
|
|
||||||
|
foreach ((array)$headers as $msguid => $headers) {
|
||||||
$object_type = kolab_format::mime2object_type($headers->others['x-kolab-type']);
|
$object_type = kolab_format::mime2object_type($headers->others['x-kolab-type']);
|
||||||
|
|
||||||
// check object type header and abort on mismatch
|
// check object type header and abort on mismatch
|
||||||
|
@ -825,4 +836,60 @@ class kolab_storage_cache
|
||||||
return $this->$name;
|
return $this->$name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bypass Roundcube messages cache.
|
||||||
|
* Roundcube cache duplicates information already stored in kolab_cache.
|
||||||
|
*
|
||||||
|
* @param bool $disable True disables, False enables messages cache
|
||||||
|
*/
|
||||||
|
public function bypass($disable = false)
|
||||||
|
{
|
||||||
|
// if kolab cache is disabled do nothing
|
||||||
|
if (!$this->enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $messages_cache, $cache_bypass;
|
||||||
|
|
||||||
|
if ($messages_cache === null) {
|
||||||
|
$rcmail = rcube::get_instance();
|
||||||
|
$messages_cache = (bool) $rcmail->config->get('messages_cache');
|
||||||
|
$cache_bypass = (int) $rcmail->config->get('kolab_messages_cache_bypass');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($messages_cache) {
|
||||||
|
// handle recurrent (multilevel) bypass() calls
|
||||||
|
if ($disable) {
|
||||||
|
$this->cache_bypassed += 1;
|
||||||
|
if ($this->cache_bypassed > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->cache_bypassed -= 1;
|
||||||
|
if ($this->cache_bypassed > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($cache_bypass) {
|
||||||
|
case 2:
|
||||||
|
// Disable messages cache completely
|
||||||
|
$this->imap->set_messages_caching(!$disable);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// We'll disable messages cache, but keep index cache.
|
||||||
|
// Default mode is both (MODE_INDEX | MODE_MESSAGE)
|
||||||
|
$mode = rcube_imap_cache::MODE_INDEX;
|
||||||
|
|
||||||
|
if (!$disable) {
|
||||||
|
$mode |= rcube_imap_cache::MODE_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->imap->set_messages_caching(true, $mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,7 +353,6 @@ class kolab_storage_folder
|
||||||
return $subscribed ? kolab_storage::folder_subscribe($this->name) : kolab_storage::folder_unsubscribe($this->name);
|
return $subscribed ? kolab_storage::folder_subscribe($this->name) : kolab_storage::folder_unsubscribe($this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get number of objects stored in this folder
|
* Get number of objects stored in this folder
|
||||||
*
|
*
|
||||||
|
@ -510,6 +509,7 @@ class kolab_storage_folder
|
||||||
* @param string The IMAP message UID to fetch
|
* @param string The IMAP message UID to fetch
|
||||||
* @param string The object type expected (use wildcard '*' to accept all types)
|
* @param string The object type expected (use wildcard '*' to accept all types)
|
||||||
* @param string The folder name where the message is stored
|
* @param string The folder name where the message is stored
|
||||||
|
*
|
||||||
* @return mixed Hash array representing the Kolab object, a kolab_format instance or false if not found
|
* @return mixed Hash array representing the Kolab object, a kolab_format instance or false if not found
|
||||||
*/
|
*/
|
||||||
public function read_object($msguid, $type = null, $folder = null)
|
public function read_object($msguid, $type = null, $folder = null)
|
||||||
|
@ -519,31 +519,31 @@ class kolab_storage_folder
|
||||||
|
|
||||||
$this->imap->set_folder($folder);
|
$this->imap->set_folder($folder);
|
||||||
|
|
||||||
$headers = $this->imap->get_message_headers($msguid);
|
$this->cache->bypass(true);
|
||||||
$message = null;
|
$message = new rcube_message($msguid);
|
||||||
|
$this->cache->bypass(false);
|
||||||
|
|
||||||
// Message doesn't exist?
|
// Message doesn't exist?
|
||||||
if (empty($headers)) {
|
if (empty($message->headers)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the X-Kolab-Type header from the XML attachment part if missing
|
// extract the X-Kolab-Type header from the XML attachment part if missing
|
||||||
if (empty($headers->others['x-kolab-type'])) {
|
if (empty($message->headers->others['x-kolab-type'])) {
|
||||||
$message = new rcube_message($msguid);
|
|
||||||
foreach ((array)$message->attachments as $part) {
|
foreach ((array)$message->attachments as $part) {
|
||||||
if (strpos($part->mimetype, kolab_format::KTYPE_PREFIX) === 0) {
|
if (strpos($part->mimetype, kolab_format::KTYPE_PREFIX) === 0) {
|
||||||
$headers->others['x-kolab-type'] = $part->mimetype;
|
$message->headers->others['x-kolab-type'] = $part->mimetype;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fix buggy messages stating the X-Kolab-Type header twice
|
// fix buggy messages stating the X-Kolab-Type header twice
|
||||||
else if (is_array($headers->others['x-kolab-type'])) {
|
else if (is_array($message->headers->others['x-kolab-type'])) {
|
||||||
$headers->others['x-kolab-type'] = reset($headers->others['x-kolab-type']);
|
$message->headers->others['x-kolab-type'] = reset($message->headers->others['x-kolab-type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no object type header found: abort
|
// no object type header found: abort
|
||||||
if (empty($headers->others['x-kolab-type'])) {
|
if (empty($message->headers->others['x-kolab-type'])) {
|
||||||
rcube::raise_error(array(
|
rcube::raise_error(array(
|
||||||
'code' => 600,
|
'code' => 600,
|
||||||
'type' => 'php',
|
'type' => 'php',
|
||||||
|
@ -554,14 +554,13 @@ class kolab_storage_folder
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$object_type = kolab_format::mime2object_type($headers->others['x-kolab-type']);
|
$object_type = kolab_format::mime2object_type($message->headers->others['x-kolab-type']);
|
||||||
$content_type = kolab_format::KTYPE_PREFIX . $object_type;
|
$content_type = kolab_format::KTYPE_PREFIX . $object_type;
|
||||||
|
|
||||||
// check object type header and abort on mismatch
|
// check object type header and abort on mismatch
|
||||||
if ($type != '*' && $object_type != $type)
|
if ($type != '*' && $object_type != $type)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!$message) $message = new rcube_message($msguid);
|
|
||||||
$attachments = array();
|
$attachments = array();
|
||||||
|
|
||||||
// get XML part
|
// get XML part
|
||||||
|
@ -603,7 +602,7 @@ class kolab_storage_folder
|
||||||
}
|
}
|
||||||
|
|
||||||
// check kolab format version
|
// check kolab format version
|
||||||
$format_version = $headers->others['x-kolab-mime-version'];
|
$format_version = $message->headers->others['x-kolab-mime-version'];
|
||||||
if (empty($format_version)) {
|
if (empty($format_version)) {
|
||||||
list($xmltype, $subtype) = explode('.', $object_type);
|
list($xmltype, $subtype) = explode('.', $object_type);
|
||||||
$xmlhead = substr($xml, 0, 512);
|
$xmlhead = substr($xml, 0, 512);
|
||||||
|
@ -757,7 +756,9 @@ class kolab_storage_folder
|
||||||
|
|
||||||
// delete old message
|
// delete old message
|
||||||
if ($result && !empty($object['_msguid']) && !empty($object['_mailbox'])) {
|
if ($result && !empty($object['_msguid']) && !empty($object['_mailbox'])) {
|
||||||
|
$this->cache->bypass(true);
|
||||||
$this->imap->delete_message($object['_msguid'], $object['_mailbox']);
|
$this->imap->delete_message($object['_msguid'], $object['_mailbox']);
|
||||||
|
$this->cache->bypass(false);
|
||||||
$this->cache->set($object['_msguid'], false, $object['_mailbox']);
|
$this->cache->set($object['_msguid'], false, $object['_mailbox']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,6 +853,8 @@ class kolab_storage_folder
|
||||||
$msguid = is_array($object) ? $object['_msguid'] : $this->cache->uid2msguid($object);
|
$msguid = is_array($object) ? $object['_msguid'] : $this->cache->uid2msguid($object);
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
|
$this->cache->bypass(true);
|
||||||
|
|
||||||
if ($msguid && $expunge) {
|
if ($msguid && $expunge) {
|
||||||
$success = $this->imap->delete_message($msguid, $this->name);
|
$success = $this->imap->delete_message($msguid, $this->name);
|
||||||
}
|
}
|
||||||
|
@ -859,6 +862,8 @@ class kolab_storage_folder
|
||||||
$success = $this->imap->set_flag($msguid, 'DELETED', $this->name);
|
$success = $this->imap->set_flag($msguid, 'DELETED', $this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->cache->bypass(false);
|
||||||
|
|
||||||
if ($success) {
|
if ($success) {
|
||||||
$this->cache->set($msguid, false);
|
$this->cache->set($msguid, false);
|
||||||
}
|
}
|
||||||
|
@ -873,7 +878,11 @@ class kolab_storage_folder
|
||||||
public function delete_all()
|
public function delete_all()
|
||||||
{
|
{
|
||||||
$this->cache->purge();
|
$this->cache->purge();
|
||||||
return $this->imap->clear_folder($this->name);
|
$this->cache->bypass(true);
|
||||||
|
$result = $this->imap->clear_folder($this->name);
|
||||||
|
$this->cache->bypass(false);
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -886,7 +895,11 @@ class kolab_storage_folder
|
||||||
public function undelete($uid)
|
public function undelete($uid)
|
||||||
{
|
{
|
||||||
if ($msguid = $this->cache->uid2msguid($uid, true)) {
|
if ($msguid = $this->cache->uid2msguid($uid, true)) {
|
||||||
if ($this->imap->set_flag($msguid, 'UNDELETED', $this->name)) {
|
$this->cache->bypass(true);
|
||||||
|
$result = $this->imap->set_flag($msguid, 'UNDELETED', $this->name);
|
||||||
|
$this->cache->bypass(false);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
return $msguid;
|
return $msguid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -905,7 +918,11 @@ class kolab_storage_folder
|
||||||
public function move($uid, $target_folder)
|
public function move($uid, $target_folder)
|
||||||
{
|
{
|
||||||
if ($msguid = $this->cache->uid2msguid($uid)) {
|
if ($msguid = $this->cache->uid2msguid($uid)) {
|
||||||
if ($this->imap->move_message($msguid, $target_folder, $this->name)) {
|
$this->cache->bypass(true);
|
||||||
|
$result = $this->imap->move_message($msguid, $target_folder, $this->name);
|
||||||
|
$this->cache->bypass(false);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
$this->cache->move($msguid, $uid, $target_folder);
|
$this->cache->move($msguid, $uid, $target_folder);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue