Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2527798
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/plugins/redundant_attachments/config.inc.php.dist b/plugins/redundant_attachments/config.inc.php.dist
index 6c317ead1..a0be3755e 100644
--- a/plugins/redundant_attachments/config.inc.php.dist
+++ b/plugins/redundant_attachments/config.inc.php.dist
@@ -1,13 +1,13 @@
<?php
// By default this plugin stores attachments in filesystem
// and copies them into sql database.
// In environments with replicated database it is possible
// to use memcache as a fallback when write-master is unavailable.
$rcmail_config['redundant_attachments_memcache'] = false;
-// When memcache is used, attachment data expires after
-// specied TTL time in seconds (max.2592000). Default is 12 hours.
-$rcmail_config['redundant_attachments_memcache_ttl'] = 12 * 60 * 60;
+// Attachment data expires after specied TTL time in seconds (max.2592000).
+// Default is 12 hours.
+$rcmail_config['redundant_attachments_cache_ttl'] = 12 * 60 * 60;
?>
diff --git a/plugins/redundant_attachments/redundant_attachments.php b/plugins/redundant_attachments/redundant_attachments.php
index 4ebc8dad7..c0affad3c 100644
--- a/plugins/redundant_attachments/redundant_attachments.php
+++ b/plugins/redundant_attachments/redundant_attachments.php
@@ -1,232 +1,233 @@
<?php
/**
* Redundant attachments
*
* This plugin provides a redundant storage for temporary uploaded
* attachment files. They are stored in both the database backend
* as well as on the local file system.
*
* It provides also memcache store as a fallback (see config file).
*
* This plugin relies on the core filesystem_attachments plugin
* and combines it with the functionality of the database_attachments plugin.
*
* @author Thomas Bruederli <roundcube@gmail.com>
* @author Aleksander Machniak <machniak@kolabsys.com>
*
* Copyright (C) 2011, The Roundcube Dev Team
* Copyright (C) 2011, Kolab Systems AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
require_once(RCUBE_PLUGINS_DIR . 'filesystem_attachments/filesystem_attachments.php');
class redundant_attachments extends filesystem_attachments
{
// A prefix for the cache key used in the session and in the key field of the cache table
private $prefix = "ATTACH";
// rcube_cache instance for SQL DB
private $cache;
// rcube_cache instance for memcache
private $mem_cache;
private $loaded;
/**
* Default constructor
*/
function init()
{
parent::init();
}
/**
* Loads plugin configuration and initializes cache object(s)
*/
private function _load_drivers()
{
if ($this->loaded) {
return;
}
$rcmail = rcmail::get_instance();
// load configuration
$this->load_config();
+ $ttl = 12 * 60 * 60; // 12 hours
+ $ttl = $rcmail->config->get('redundant_attachments_cache_ttl', $ttl);
+
// Init SQL cache (disable cache data serialization)
- $this->cache = $rcmail->get_cache($this->prefix, 'db', 0, false);
+ $this->cache = $rcmail->get_cache($this->prefix, 'db', $ttl, false);
// Init memcache (fallback) cache
if ($rcmail->config->get('redundant_attachments_memcache')) {
- $ttl = 12 * 60 * 60; // 12 hours
- $ttl = (int) $rcmail->config->get('redundant_attachments_memcache_ttl', $ttl);
$this->mem_cache = $rcmail->get_cache($this->prefix, 'memcache', $ttl, false);
}
$this->loaded = true;
}
/**
* Helper method to generate a unique key for the given attachment file
*/
private function _key($args)
{
$uname = $args['path'] ? $args['path'] : $args['name'];
return $args['group'] . md5(mktime() . $uname . $_SESSION['user_id']);
}
/**
* Save a newly uploaded attachment
*/
function upload($args)
{
$args = parent::upload($args);
$this->_load_drivers();
$key = $this->_key($args);
$data = base64_encode(file_get_contents($args['path']));
$status = $this->cache->write($key, $data);
if (!$status && $this->mem_cache) {
$status = $this->mem_cache->write($key, $data);
}
if ($status) {
$args['id'] = $key;
$args['status'] = true;
}
return $args;
}
/**
* Save an attachment from a non-upload source (draft or forward)
*/
function save($args)
{
$args = parent::save($args);
$this->_load_drivers();
if ($args['path'])
$args['data'] = file_get_contents($args['path']);
$key = $this->_key($args);
$data = base64_encode($args['data']);
$status = $this->cache->write($key, $data);
if (!$status && $this->mem_cache) {
$status = $this->mem_cache->write($key, $data);
}
if ($status) {
$args['id'] = $key;
$args['status'] = true;
}
return $args;
}
/**
* Remove an attachment from storage
* This is triggered by the remove attachment button on the compose screen
*/
function remove($args)
{
parent::remove($args);
$this->_load_drivers();
$status = $this->cache->remove($args['id']);
if (!$status && $this->mem_cache) {
$status = $this->cache->remove($args['id']);
}
// we cannot trust the result of any of the methods above
// assume true, attachments will be removed on cleanup
$args['status'] = true;
return $args;
}
/**
* When composing an html message, image attachments may be shown
* For this plugin, $this->get() will check the file and
* return it's contents
*/
function display($args)
{
return $this->get($args);
}
/**
* When displaying or sending the attachment the file contents are fetched
* using this method. This is also called by the attachment_display hook.
*/
function get($args)
{
// attempt to get file from local file system
$args = parent::get($args);
if ($args['path'] && ($args['status'] = file_exists($args['path'])))
return $args;
$this->_load_drivers();
// fetch from database if not found on FS
$data = $this->cache->read($args['id']);
// fetch from memcache if not found on FS and DB
if (($data === false || $data === null) && $this->mem_cache) {
$data = $this->mem_cache->read($args['id']);
}
if ($data) {
$args['data'] = base64_decode($data);
$args['status'] = true;
}
return $args;
}
/**
* Delete all temp files associated with this user
*/
function cleanup($args)
{
$this->_load_drivers();
if ($this->cache) {
$this->cache->remove($args['group'], true);
}
if ($this->mem_cache) {
$this->mem_cache->remove($args['group'], true);
}
parent::cleanup($args);
$args['status'] = true;
return $args;
}
}
diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php
index bd97583c3..18055f77d 100644
--- a/program/lib/Roundcube/rcube_config.php
+++ b/program/lib/Roundcube/rcube_config.php
@@ -1,453 +1,454 @@
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2008-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Class to read configuration settings |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
/**
* Configuration class for Roundcube
*
* @package Framework
* @subpackage Core
*/
class rcube_config
{
const DEFAULT_SKIN = 'larry';
private $prop = array();
private $errors = array();
private $userprefs = array();
/**
* Renamed options
*
* @var array
*/
private $legacy_props = array(
// new name => old name
'default_folders' => 'default_imap_folders',
'mail_pagesize' => 'pagesize',
'addressbook_pagesize' => 'pagesize',
'reply_mode' => 'top_posting',
'refresh_interval' => 'keep_alive',
'min_refresh_interval' => 'min_keep_alive',
'messages_cache_ttl' => 'message_cache_lifetime',
+ 'redundant_attachments_cache_ttl' => 'redundant_attachments_memcache_ttl',
);
/**
* Object constructor
*/
public function __construct()
{
$this->load();
// Defaults, that we do not require you to configure,
// but contain information that is used in various
// locations in the code:
$this->set('contactlist_fields', array('name', 'firstname', 'surname', 'email'));
}
/**
* Load config from local config file
*
* @todo Remove global $CONFIG
*/
private function load()
{
// load main config file
if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'main.inc.php'))
$this->errors[] = 'main.inc.php was not found.';
// load database config
if (!$this->load_from_file(RCUBE_CONFIG_DIR . 'db.inc.php'))
$this->errors[] = 'db.inc.php was not found.';
// load host-specific configuration
$this->load_host_config();
// set skin (with fallback to old 'skin_path' property)
if (empty($this->prop['skin'])) {
if (!empty($this->prop['skin_path'])) {
$this->prop['skin'] = str_replace('skins/', '', unslashify($this->prop['skin_path']));
}
else {
$this->prop['skin'] = self::DEFAULT_SKIN;
}
}
// larry is the new default skin :-)
if ($this->prop['skin'] == 'default')
$this->prop['skin'] = self::DEFAULT_SKIN;
// fix paths
$this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : RCUBE_INSTALL_PATH . 'logs';
$this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : RCUBE_INSTALL_PATH . 'temp';
// fix default imap folders encoding
foreach (array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox') as $folder)
$this->prop[$folder] = rcube_charset::convert($this->prop[$folder], RCUBE_CHARSET, 'UTF7-IMAP');
if (!empty($this->prop['default_folders']))
foreach ($this->prop['default_folders'] as $n => $folder)
$this->prop['default_folders'][$n] = rcube_charset::convert($folder, RCUBE_CHARSET, 'UTF7-IMAP');
// set PHP error logging according to config
if ($this->prop['debug_level'] & 1) {
ini_set('log_errors', 1);
if ($this->prop['log_driver'] == 'syslog') {
ini_set('error_log', 'syslog');
}
else {
ini_set('error_log', $this->prop['log_dir'].'/errors');
}
}
// enable display_errors in 'show' level, but not for ajax requests
ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4)));
// set timezone auto settings values
if ($this->prop['timezone'] == 'auto') {
$this->prop['_timezone_value'] = $this->client_timezone();
}
else if (is_numeric($this->prop['timezone']) && ($tz = timezone_name_from_abbr("", $this->prop['timezone'] * 3600, 0))) {
$this->prop['timezone'] = $tz;
}
else if (empty($this->prop['timezone'])) {
$this->prop['timezone'] = 'UTC';
}
// remove deprecated properties
unset($this->prop['dst_active']);
// export config data
$GLOBALS['CONFIG'] = &$this->prop;
}
/**
* Load a host-specific config file if configured
* This will merge the host specific configuration with the given one
*/
private function load_host_config()
{
$fname = null;
if (is_array($this->prop['include_host_config'])) {
$fname = $this->prop['include_host_config'][$_SERVER['HTTP_HOST']];
}
else if (!empty($this->prop['include_host_config'])) {
$fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $_SERVER['HTTP_HOST']) . '.inc.php';
}
if ($fname) {
$this->load_from_file(RCUBE_CONFIG_DIR . $fname);
}
}
/**
* Read configuration from a file
* and merge with the already stored config values
*
* @param string $fpath Full path to the config file to be loaded
* @return booelan True on success, false on failure
*/
public function load_from_file($fpath)
{
if (is_file($fpath) && is_readable($fpath)) {
// use output buffering, we don't need any output here
ob_start();
include($fpath);
ob_end_clean();
if (is_array($rcmail_config)) {
$this->merge($rcmail_config);
return true;
}
}
return false;
}
/**
* Getter for a specific config parameter
*
* @param string $name Parameter name
* @param mixed $def Default value if not set
* @return mixed The requested config value
*/
public function get($name, $def = null)
{
if (isset($this->prop[$name])) {
$result = $this->prop[$name];
}
else {
$result = $def;
}
$rcube = rcube::get_instance();
if ($name == 'timezone' && isset($this->prop['_timezone_value'])) {
$result = $this->prop['_timezone_value'];
}
else if ($name == 'client_mimetypes') {
if ($result == null && $def == null)
$result = 'text/plain,text/html,text/xml,image/jpeg,image/gif,image/png,image/bmp,image/tiff,application/x-javascript,application/pdf,application/x-shockwave-flash';
if ($result && is_string($result))
$result = explode(',', $result);
}
$plugin = $rcube->plugins->exec_hook('config_get', array(
'name' => $name, 'default' => $def, 'result' => $result));
return $plugin['result'];
}
/**
* Setter for a config parameter
*
* @param string $name Parameter name
* @param mixed $value Parameter value
*/
public function set($name, $value)
{
$this->prop[$name] = $value;
}
/**
* Override config options with the given values (eg. user prefs)
*
* @param array $prefs Hash array with config props to merge over
*/
public function merge($prefs)
{
$this->prop = array_merge($this->prop, $prefs, $this->userprefs);
$this->fix_legacy_props();
}
/**
* Merge the given prefs over the current config
* and make sure that they survive further merging.
*
* @param array $prefs Hash array with user prefs
*/
public function set_user_prefs($prefs)
{
// Honor the dont_override setting for any existing user preferences
$dont_override = $this->get('dont_override');
if (is_array($dont_override) && !empty($dont_override)) {
foreach ($dont_override as $key) {
unset($prefs[$key]);
}
}
// convert user's timezone into the new format
if (is_numeric($prefs['timezone']) && ($tz = timezone_name_from_abbr('', $prefs['timezone'] * 3600, 0))) {
$prefs['timezone'] = $tz;
}
// larry is the new default skin :-)
if ($prefs['skin'] == 'default') {
$prefs['skin'] = self::DEFAULT_SKIN;
}
$this->userprefs = $prefs;
$this->prop = array_merge($this->prop, $prefs);
$this->fix_legacy_props();
// override timezone settings with client values
if ($this->prop['timezone'] == 'auto') {
$this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $this->client_timezone() : $this->prop['_timezone_value'];
}
else if (isset($this->prop['_timezone_value']))
unset($this->prop['_timezone_value']);
}
/**
* Getter for all config options
*
* @return array Hash array containg all config properties
*/
public function all()
{
return $this->prop;
}
/**
* Special getter for user's timezone offset including DST
*
* @return float Timezone offset (in hours)
* @deprecated
*/
public function get_timezone()
{
if ($tz = $this->get('timezone')) {
try {
$tz = new DateTimeZone($tz);
return $tz->getOffset(new DateTime('now')) / 3600;
}
catch (Exception $e) {
}
}
return 0;
}
/**
* Return requested DES crypto key.
*
* @param string $key Crypto key name
* @return string Crypto key
*/
public function get_crypto_key($key)
{
// Bomb out if the requested key does not exist
if (!array_key_exists($key, $this->prop)) {
rcube::raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Request for unconfigured crypto key \"$key\""
), true, true);
}
$key = $this->prop[$key];
// Bomb out if the configured key is not exactly 24 bytes long
if (strlen($key) != 24) {
rcube::raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Configured crypto key '$key' is not exactly 24 bytes long"
), true, true);
}
return $key;
}
/**
* Try to autodetect operating system and find the correct line endings
*
* @return string The appropriate mail header delimiter
*/
public function header_delimiter()
{
// use the configured delimiter for headers
if (!empty($this->prop['mail_header_delimiter'])) {
$delim = $this->prop['mail_header_delimiter'];
if ($delim == "\n" || $delim == "\r\n")
return $delim;
else
rcube::raise_error(array(
'code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid mail_header_delimiter setting"
), true, false);
}
$php_os = strtolower(substr(PHP_OS, 0, 3));
if ($php_os == 'win')
return "\r\n";
if ($php_os == 'mac')
return "\r\n";
return "\n";
}
/**
* Return the mail domain configured for the given host
*
* @param string $host IMAP host
* @param boolean $encode If true, domain name will be converted to IDN ASCII
* @return string Resolved SMTP host
*/
public function mail_domain($host, $encode=true)
{
$domain = $host;
if (is_array($this->prop['mail_domain'])) {
if (isset($this->prop['mail_domain'][$host]))
$domain = $this->prop['mail_domain'][$host];
}
else if (!empty($this->prop['mail_domain'])) {
$domain = rcube_utils::parse_host($this->prop['mail_domain']);
}
if ($encode) {
$domain = rcube_utils::idn_to_ascii($domain);
}
return $domain;
}
/**
* Getter for error state
*
* @return mixed Error message on error, False if no errors
*/
public function get_error()
{
return empty($this->errors) ? false : join("\n", $this->errors);
}
/**
* Internal getter for client's (browser) timezone identifier
*/
private function client_timezone()
{
if (isset($_SESSION['timezone']) && is_numeric($_SESSION['timezone'])
&& ($ctz = timezone_name_from_abbr("", $_SESSION['timezone'] * 3600, 0))) {
return $ctz;
}
else if (!empty($_SESSION['timezone'])) {
try {
$tz = timezone_open($_SESSION['timezone']);
return $tz->getName();
}
catch (Exception $e) { /* gracefully ignore */ }
}
// fallback to server's timezone
return date_default_timezone_get();
}
/**
* Convert legacy options into new ones
*/
private function fix_legacy_props()
{
foreach ($this->legacy_props as $new => $old) {
if (isset($this->prop[$old])) {
if (!isset($this->prop[$new])) {
$this->prop[$new] = $this->prop[$old];
}
unset($this->prop[$old]);
}
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jan 31, 1:54 PM (14 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
426319
Default Alt Text
(22 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment