From: Michael M Slusarz Date: Thu, 9 Jul 2009 21:03:04 +0000 (-0600) Subject: PHP 5/Horde 4 coding conventions X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=a1ac2b66ae4be012313396566d7c42b548134d2c;p=horde.git PHP 5/Horde 4 coding conventions --- diff --git a/imp/lib/Quota.php b/imp/lib/Quota.php index f49648f57..c5e1a6a15 100644 --- a/imp/lib/Quota.php +++ b/imp/lib/Quota.php @@ -46,13 +46,13 @@ class IMP_Quota static public function singleton($driver, $params = array()) { ksort($params); - $signature = md5(serialize(array($driver, $params))); + $sig = hash('md5', serialize(array($driver, $params))); - if (!isset(self::$_instances[$signature])) { - self::$_instances[$signature] = IMP_Quota::getInstance($driver, $params); + if (!isset(self::$_instances[$sig])) { + self::$_instances[$sig] = IMP_Quota::getInstance($driver, $params); } - return self::$_instances[$signature]; + return self::$_instances[$sig]; } /** @@ -68,7 +68,7 @@ class IMP_Quota static public function getInstance($driver, $params = array()) { $driver = basename($driver); - $class = 'IMP_Quota_' . $driver; + $class = 'IMP_Quota_' . ucfirst($driver); if (class_exists($class)) { return new $class($params); @@ -156,4 +156,5 @@ class IMP_Quota return array($calc, $unit); } + } diff --git a/imp/lib/Quota/Command.php b/imp/lib/Quota/Command.php new file mode 100644 index 000000000..8153ff862 --- /dev/null +++ b/imp/lib/Quota/Command.php @@ -0,0 +1,92 @@ + Path to the quota binary - REQUIRED + * 'grep_path' => Path to the grep binary - REQUIRED + * 'partition' => If all user mailboxes are on a single partition, the + * partition label. By default, quota will determine + * quota information using the user's home directory value. + * + * Copyright 2002-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Eric Rostetter + * @package IMP_Quota + */ +class IMP_Quota_Command extends IMP_Quota +{ + /** + * Constructor. + * + * @param array $params Hash containing connection parameters. + */ + protected function __construct($params = array()) + { + $params = array_merge(array( + 'quota_path' => 'quota', + 'grep_path' => 'grep', + 'partition' => null + ), $params); + + parent::__construct($params); + } + + /** + * Get the disk block size, if possible. + * + * We try to find out the disk block size from stat(). If not + * available, stat() should return -1 for this value, in which + * case we default to 1024 (for historical reasons). There are a + * large number of reasons this may fail, such as OS support, + * SELinux interference, the file being > 2 GB in size, the file + * we're referring to not being readable, etc. + * + * @return integer The disk block size. + */ + protected function _blockSize() + { + $results = stat(__FILE__); + return ($results['blksize'] > 1) + ? $results['blksize'] + : 1024; + } + + /** + * Get quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + if (empty($this->_params['partition'])) { + $passwd_array = posix_getpwnam($_SESSION['imp']['user']); + list($junk, $search_string, $junk) = explode('/', $passwd_array['dir']); + } else { + $search_string = $this->_params['partition']; + } + $cmdline = $this->_params['quota_path'] . ' -u ' . $_SESSION['imp']['user'] . ' | ' . $this->_params['grep_path'] . ' ' . $search_string; + exec($cmdline, $quota_data, $return_code); + if (($return_code == 0) && (count($quota_data) == 1)) { + $quota = split("[[:blank:]]+", trim($quota_data[0])); + $blocksize = $this->_blockSize(); + return array('usage' => $quota[1] * $blocksize, + 'limit' => $quota[2] * $blocksize); + } + + throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); + } + +} diff --git a/imp/lib/Quota/Hook.php b/imp/lib/Quota/Hook.php new file mode 100644 index 000000000..7386f7020 --- /dev/null +++ b/imp/lib/Quota/Hook.php @@ -0,0 +1,43 @@ + Array of parameters to pass to the quota function. + * + * Copyright 2002-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Michael Redinger + * @package IMP_Quota + */ +class IMP_Quota_Hook extends IMP_Quota +{ + /** + * Get quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + $quota = Horde::callHook('_imp_hook_quota', $this->_params, 'imp'); + + if (count($quota) != 2) { + Horde::logMessage('Incorrect number of return values from quota hook.', __FILE__, __LINE__, PEAR_LOG_ERR); + throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); + } + + return array('usage' => $quota[0], 'limit' => $quota[1]); + } + +} diff --git a/imp/lib/Quota/Imap.php b/imp/lib/Quota/Imap.php new file mode 100644 index 000000000..55d6ba7ae --- /dev/null +++ b/imp/lib/Quota/Imap.php @@ -0,0 +1,35 @@ + + * @package IMP_Quota + */ +class IMP_Quota_Imap extends IMP_Quota +{ + /** + * Get quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + try { + $quota = $GLOBALS['imp_imap']->ob->getQuotaRoot($GLOBALS['imp_search']->isSearchMbox($GLOBALS['imp_mbox']['mailbox']) ? 'INBOX' : $GLOBALS['imp_mbox']['mailbox']); + } catch (Horde_Imap_Client_Exception $e) { + throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); + } + + $quota_val = reset($quota); + return array('usage' => $quota['storage']['usage'] * 1024, 'limit' => $quota['storage']['limit'] * 1024); + } + +} diff --git a/imp/lib/Quota/Logfile.php b/imp/lib/Quota/Logfile.php new file mode 100644 index 000000000..d8e2d59fd --- /dev/null +++ b/imp/lib/Quota/Logfile.php @@ -0,0 +1,87 @@ + + * 'quota' => array( + * 'driver' => 'logfile', + * 'params' => array( + * 'logfile' => '/path/to/log/file', + * 'taillines' => 10, + * 'FTPmail' => 'FTP', + * 'beginocc' => 'usage = ', + * 'midocc' => ' of ', + * 'endocc' => ' bytes' + * ) + * ); + * + * logfile - The path/to/filename of the log file to use. + * taillines - The number of lines to look at in the tail of the logfile. + * FTPmail - If you want to show what FTP space is available (IMAP folder) + * or what mail space is available (INBOX). + * Defines the search string to username: + * FTPmail to identify the line with QUOTA info. + * beginocc - String that designates the characters before the usage + * number. + * midocc - String between usage and total storage space. + * endocc - String after the storage number. + * + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Tim Gorter + * @package IMP_Quota + */ +class IMP_Quota_Logfile extends IMP_Quota +{ + /** + * Constructor + * + * @param array $params Hash containing connection parameters. + */ + protected function __construct($params = array()) + { + parent::__construct(array_merge(array( + 'logfile' => '', + 'taillines' => 10, + 'FTPmail' => 'FTP', + 'beginocc' => 'usage = ', + 'midocc' => ' of ', + 'endocc' => ' bytes' + ), $params)); + } + + /** + * Get quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + if (!is_file($this->_params['logfile'])) { + throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); + } + + $full = file($this->_params['logfile']); + for (; $this->_params['taillines'] > 0; --$this->_params['taillines']) { + $tail[] = $full[count($full) - $this->_params['taillines']]; + } + + $uname = $_SESSION['imp']['user']; + $FTPmail = $this->_params['FTPmail']; + $virtline = preg_grep("[$uname: $FTPmail]", $tail); + $virtline = array_values($virtline); + $usage = substr($virtline[0], strpos($virtline[0], $this->_params['beginocc']) + strlen($this->_params['beginocc']), strpos($virtline[0], $this->_params['midocc'])); + $storage = substr($virtline[0], strpos($virtline[0], $this->_params['midocc']) + strlen($this->_params['midocc']), strpos($virtline[0], $this->_params['endocc'])); + + return array('usage' => $usage, 'limit' => $storage); + } + +} diff --git a/imp/lib/Quota/Maildir.php b/imp/lib/Quota/Maildir.php new file mode 100644 index 000000000..3a30788d9 --- /dev/null +++ b/imp/lib/Quota/Maildir.php @@ -0,0 +1,112 @@ + + * 'quota' => array( + * 'driver' => 'maildir', + * 'params' => array( + * 'path' => '/path/to/users/Maildir' + * // TODO: Add config param for storage vs message quota + * ) + * ); + * + * path - The path to the user's Maildir directory. You may use the + * two-character sequence "~U" to represent the user's account name, + * and the actual username will be substituted in that location. + * E.g., '/home/~U/Maildir/' or '/var/mail/~U/Maildir/' + * + * + * Copyright 2007-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Eric Rostetter + * @package IMP_Quota + */ +class IMP_Quota_Maildir extends IMP_Quota +{ + /** + * Constructor. + * + * @param array $params Hash containing connection parameters. + */ + protected function __construct($params = array()) + { + parent::__construct(array_merge(array('path' => ''), $params)); + } + + /** + * Returns quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + $storage_limit = $message_limit = $storage_used = $message_used = 0; + + // Get the full path to the quota file. + $full = $this->_params['path'] . '/maildirsize'; + + // Substitute the username in the string if needed. + $uname = $_SESSION['imp']['user']; + $full = str_replace('~U', $uname, $full); + + // Read in the quota file and parse it, if possible. + if (!is_file($full)) { + throw new Horde_Exception(_("Unable to retrieve quota")); + } + + // Read in maildir quota file. + $lines = file($full); + + // Parse the lines. + foreach ($lines as $line_number => $line) { + if ($line_number == 0) { + // First line, quota header. + $line = preg_replace('/[ \t\n\r\0\x0B]/', '', $line); + list($v1, $t1, $v2, $t2) = sscanf($line, '%ld%[CS],%ld%[CS]'); + if (is_null($v1) || is_null($t1)) { + $v1 = 0; + } + if (is_null($v2) || is_null($t2)) { + $v2 = 0; + } + + if ($t1 == 'S') { + $storage_limit = $v1; + } + if ($t1 == 'C') { + $message_limit = $v1; + } + if ($t2 == 'S') { + $storage_limit = $v2; + } + if ($t2 == 'C') { + $message_limit = $v2; + } + } else { + // Any line other than the first line. + // The quota used is the sum of all lines found. + list($storage, $message) = sscanf(trim($line), '%ld %d'); + if (!is_null($storage)) { + $storage_used += $storage; + } + if (!is_null($message)) { + $message_used += $message; + } + } + } + + return array('usage' => $storage_used, 'limit' => $storage_limit); + } + +} diff --git a/imp/lib/Quota/Mdaemon.php b/imp/lib/Quota/Mdaemon.php new file mode 100644 index 000000000..6fc13c4da --- /dev/null +++ b/imp/lib/Quota/Mdaemon.php @@ -0,0 +1,111 @@ + + * 'app_location' -- TODO + * + * + * Copyright 2002-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Mike Cochrane + * @package IMP_Quota + */ +class IMP_Quota_Mdaemon extends IMP_Quota +{ + /** + * Get quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + $userDetails = $this->_getUserDetails($_SESSION['imp']['user'], $_SESSION['imp']['maildomain']); + + if ($userDetails !== false) { + $userHome = trim(substr($userDetails, 105, 90)); + $total = intval(substr($userDetails, 229, 6)) * 1024; + + if ($total == 0) { + return array('usage' => 0, 'limit' => 0); + } + + if (($taken = $this->_mailboxSize($userHome)) !== false) { + return array('usage' => $taken, 'limit' => $total); + } + } + + throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); + } + + /** + * Get the size of a mailbox + * + * @param string $path The full path of the mailbox to fetch the quota + * for including trailing backslash. + * + * @return mixed The number of bytes in the mailbox (integer) or false + * (boolean) on error. + */ + protected function _mailboxSize($path) + { + $contents = file_get_contents($path . '\imap.mrk'); + + $pointer = 36; + $size = 0; + while ($pointer < strlen($contents)) { + $details = unpack('a17Filename/a11Crap/VSize', substr($contents, $pointer, 36)); + $size += $details['Size']; + $pointer += 36; + } + + /* Recursivly check subfolders. */ + $d = dir($path); + while (($entry = $d->read()) !== false) { + if (($entry != '.') && + ($entry != '..') && + (substr($entry, -5, 5) == '.IMAP')) { + $size += $this->_mailboxSize($path . $entry . '\\'); + } + } + $d->close(); + + return $size; + } + + /** + * Retrieve relevant line from userlist.dat. + * + * @param string $user The username for which to retrieve detals. + * @param string $realm The realm (domain) for the user. + * + * @return mixed Line from userlist.dat (string) or false (boolean). + */ + protected function _getUserDetails($user, $realm) + { + $searchString = str_pad($realm, 45) . str_pad($user, 30); + + if (!($fp = fopen($this->_params['app_location'] . '/userlist.dat', 'rb'))) { + return false; + } + + while (!feof($fp)) { + $line = fgets($fp, 4096); + if (substr($line, 0, strlen($searchString)) == $searchString) { + fclose($fp); + return $line; + } + } + fclose($fp); + + return false; + } + +} diff --git a/imp/lib/Quota/Mercury32.php b/imp/lib/Quota/Mercury32.php new file mode 100644 index 000000000..5e55aaecb --- /dev/null +++ b/imp/lib/Quota/Mercury32.php @@ -0,0 +1,71 @@ + + * 'quota' => array( + * 'driver' => 'mercury32', + * 'params' => array( + * 'mail_user_folder' => 'c:/mercry/mail' + * ) + * ); + * + * 'mail_user_folder' -- The path to folder mail mercury + * + * + ***************************************************************************** + * PROBLEM TO ACCESS NETWORK DIRECOTRY + ***************************************************************************** + * Matt Grimm + * 06-Jun-2003 10:25 + * + * Thought I could help clarify something with accessing network shares on a + * Windows network (2000 in this case), running PHP 4.3.2 under Apache 2.0.44. + * However you are logged into the Windows box, your Apache service must be + * running under an account which has access to the share. The easiest (and + * probably least safe) way for me was to change the user for the Apache + * service to the computer administrator (do this in the service properties, + * under the "Log On" tab). After restarting Apache, I could access mapped + * drives by their assigned drive letter ("z:\\") or regular shares by their + * UNC path ("\\\\shareDrive\\shareDir"). + ***************************************************************************** + * + * Copyright 2002-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Frank Lupo + * @package IMP_Quota + */ +class IMP_Quota_Mercury32 extends IMP_Quota +{ + /** + * Get quota information (used/allocated), in bytes. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + */ + public function getQuota() + { + $quota = null; + + $dir_path = $this->_params['mail_user_folder'] . '/' . $_SESSION['imp']['user'] . '/'; + if ($dir = @opendir($dir_path)) { + while (($file = readdir($dir)) !== false) { + $quota += filesize($dir_path . $file); + } + closedir($dir); + + if (!is_null($quota)) { + return array('usage' => $quota, 'limit' => 0); + } + } + + throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); + } + +} diff --git a/imp/lib/Quota/Sql.php b/imp/lib/Quota/Sql.php new file mode 100644 index 000000000..a0a44d333 --- /dev/null +++ b/imp/lib/Quota/Sql.php @@ -0,0 +1,133 @@ + + * phptype -- Database type to connect to + * hostspec -- Database host + * username -- User name for DB connection + * password -- Password for DB connection + * database -- Database name + * query_quota -- SQL query which returns single row/column with user quota + * (in bytes). %u is replaced with current user name, %U with + * the user name without the domain part, %d with the domain. + * query_used -- SQL query which returns single row/column with user used + * space (in bytes). Placeholders are the same like in + * query_quota. + * + * + * Example how to reuse Horde's global SQL configuration: + * + * 'quota' => array( + * 'driver' => 'sql', + * 'params' => array_merge( + * $GLOBALS['conf']['sql'], + * array( + * 'query_quota' => 'SELECT quota FROM quotas WHERE user = ?', + * 'query_used' => 'SELECT used FROM quotas WHERE user = ?' + * ) + * ) + * ), + * + * + * Copyright 2006-2007 Tomas Simonaitis + * Copyright 2006-2009 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Tomas Simonaitis + * @author Jan Schneider + * @package IMP_Quota + */ +class IMP_Quota_Sql extends IMP_Quota +{ + /** + * SQL connection object. + * + * @var DB + */ + protected $_db; + + /** + * Connects to the database + * + * @throws Horde_Exception + */ + protected function _connect() + { + if ($this->_db) { + return; + } + + $this->_db = DB::connect($this->_params, + array('persistent' => !empty($this->_params['persistent']), + 'ssl' => !empty($this->_params['ssl']))); + if ($this->_db instanceof PEAR_Error) { + throw new Horde_Exception(_("Unable to connect to SQL server.")); + } + } + + /** + * Returns quota information. + * + * @return array An array with the following keys: + * 'limit' = Maximum quota allowed + * 'usage' = Currently used portion of quota (in bytes) + * @throws Horde_Exception + */ + public function getQuota() + { + $this->_connect(); + + $user = $_SESSION['imp']['user']; + $quota = array('limit' => 0, 'usage' => 0); + + if (!empty($this->_params['query_quota'])) { + @list($bare_user, $domain) = explode('@', $user, 2); + $query = str_replace(array('?', '%u', '%U', '%d'), + array($this->_db->quote($user), + $this->_db->quote($user), + $this->_db->quote($bare_user), + $this->_db->quote($domain)), + $this->_params['query_quota']); + $result = $this->_db->query($query); + if ($result instanceof PEAR_Error) { + throw new Horde_Exception($result); + } + + $row = $result->fetchRow(DB_FETCHMODE_ASSOC); + if (is_array($row)) { + $quota['limit'] = current($row); + } + } else { + Horde::logMessage('IMP_Quota_Sql: query_quota SQL query not set', __FILE__, __LINE__, PEAR_LOG_DEBUG); + } + + if (!empty($this->_params['query_used'])) { + @list($bare_user, $domain) = explode('@', $user, 2); + $query = str_replace(array('?', '%u', '%U', '%d'), + array($this->_db->quote($user), + $this->_db->quote($user), + $this->_db->quote($bare_user), + $this->_db->quote($domain)), + $this->_params['query_used']); + $result = $this->_db->query($query); + if ($result instanceof PEAR_Error) { + throw new Horde_Exception($result); + } + + $row = $result->fetchRow(DB_FETCHMODE_ASSOC); + if (is_array($row)) { + $quota['usage'] = current($row); + } + } else { + Horde::logMessage('IMP_Quota_Sql: query_used SQL query not set', __FILE__, __LINE__, PEAR_LOG_DEBUG); + } + + return $quota; + } + +} diff --git a/imp/lib/Quota/command.php b/imp/lib/Quota/command.php deleted file mode 100644 index ac0b44eff..000000000 --- a/imp/lib/Quota/command.php +++ /dev/null @@ -1,90 +0,0 @@ - Path to the quota binary - REQUIRED - * 'grep_path' => Path to the grep binary - REQUIRED - * 'partition' => If all user mailboxes are on a single partition, the - * partition label. By default, quota will determine - * quota information using the user's home directory value. - * - * Copyright 2002-2009 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Eric Rostetter - * @package IMP_Quota - */ -class IMP_Quota_command extends IMP_Quota -{ - /** - * Constructor - * - * @param array $params Hash containing connection parameters. - */ - protected function __construct($params = array()) - { - $params = array_merge(array('quota_path' => 'quota', - 'grep_path' => 'grep', - 'partition' => null), - $params); - parent::__construct($params); - } - - /** - * Get the disk block size, if possible. - * - * We try to find out the disk block size from stat(). If not - * available, stat() should return -1 for this value, in which - * case we default to 1024 (for historical reasons). There are a - * large number of reasons this may fail, such as OS support, - * SELinux interference, the file being > 2 GB in size, the file - * we're referring to not being readable, etc. - * - * @return integer The disk block size. - */ - protected function _blockSize() - { - $results = stat(__FILE__); - return ($results['blksize'] > 1) - ? $results['blksize'] - : 1024; - } - - /** - * Get quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - if (empty($this->_params['partition'])) { - $passwd_array = posix_getpwnam($_SESSION['imp']['user']); - list($junk, $search_string, $junk) = explode('/', $passwd_array['dir']); - } else { - $search_string = $this->_params['partition']; - } - $cmdline = $this->_params['quota_path'] . ' -u ' . $_SESSION['imp']['user'] . ' | ' . $this->_params['grep_path'] . ' ' . $search_string; - exec($cmdline, $quota_data, $return_code); - if (($return_code == 0) && (count($quota_data) == 1)) { - $quota = split("[[:blank:]]+", trim($quota_data[0])); - $blocksize = $this->_blockSize(); - return array('usage' => $quota[1] * $blocksize, - 'limit' => $quota[2] * $blocksize); - } - - throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); - } - -} diff --git a/imp/lib/Quota/hook.php b/imp/lib/Quota/hook.php deleted file mode 100644 index 1941be6c6..000000000 --- a/imp/lib/Quota/hook.php +++ /dev/null @@ -1,43 +0,0 @@ - Array of parameters to pass to the quota function. - * - * Copyright 2002-2009 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Michael Redinger - * @package IMP_Quota - */ -class IMP_Quota_hook extends IMP_Quota -{ - /** - * Get quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - $quota = Horde::callHook('_imp_hook_quota', $this->_params, 'imp'); - - if (count($quota) != 2) { - Horde::logMessage('Incorrect number of return values from quota hook.', __FILE__, __LINE__, PEAR_LOG_ERR); - throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); - } - - return array('usage' => $quota[0], 'limit' => $quota[1]); - } - -} diff --git a/imp/lib/Quota/imap.php b/imp/lib/Quota/imap.php deleted file mode 100644 index 6a30daf87..000000000 --- a/imp/lib/Quota/imap.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @package IMP_Quota - */ -class IMP_Quota_imap extends IMP_Quota -{ - /** - * Get quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - try { - $quota = $GLOBALS['imp_imap']->ob->getQuotaRoot($GLOBALS['imp_search']->isSearchMbox($GLOBALS['imp_mbox']['mailbox']) ? 'INBOX' : $GLOBALS['imp_mbox']['mailbox']); - } catch (Horde_Imap_Client_Exception $e) { - throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); - } - - $quota_val = reset($quota); - return array('usage' => $quota['storage']['usage'] * 1024, 'limit' => $quota['storage']['limit'] * 1024); - } - -} diff --git a/imp/lib/Quota/logfile.php b/imp/lib/Quota/logfile.php deleted file mode 100644 index 00a0df16f..000000000 --- a/imp/lib/Quota/logfile.php +++ /dev/null @@ -1,85 +0,0 @@ - array( - * 'driver' => 'logfile', - * 'params' => array( - * 'logfile' => '/path/to/log/file', - * 'taillines' => 10, - * 'FTPmail' => 'FTP', - * 'beginocc' => 'usage = ', - * 'midocc' => ' of ', - * 'endocc' => ' bytes' - * ) - * ); - * - * logfile - The path/to/filename of the log file to use. - * taillines - The number of lines to look at in the tail of the logfile. - * FTPmail - If you want to show what FTP space is available (IMAP folder) - * or what mail space is available (INBOX). - * Defines the search string to username: - * FTPmail to identify the line with QUOTA info. - * beginocc - String that designates the characters before the usage - * number. - * midocc - String between usage and total storage space. - * endocc - String after the storage number. - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Tim Gorter - * @package IMP_Quota - */ -class IMP_Quota_logfile extends IMP_Quota -{ - /** - * Constructor - * - * @param array $params Hash containing connection parameters. - */ - protected function __construct($params = array()) - { - parent::__construct(array_merge(array( - 'logfile' => '', - 'taillines' => 10, - 'FTPmail' => 'FTP', - 'beginocc' => 'usage = ', - 'midocc' => ' of ', - 'endocc' => ' bytes' - ), $params)); - } - - /** - * Get quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - if (!is_file($this->_params['logfile'])) { - throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); - } - - $full = file($this->_params['logfile']); - for (; $this->_params['taillines'] > 0; --$this->_params['taillines']) { - $tail[] = $full[count($full) - $this->_params['taillines']]; - } - - $uname = $_SESSION['imp']['user']; - $FTPmail = $this->_params['FTPmail']; - $virtline = preg_grep("[$uname: $FTPmail]", $tail); - $virtline = array_values($virtline); - $usage = substr($virtline[0], strpos($virtline[0], $this->_params['beginocc']) + strlen($this->_params['beginocc']), strpos($virtline[0], $this->_params['midocc'])); - $storage = substr($virtline[0], strpos($virtline[0], $this->_params['midocc']) + strlen($this->_params['midocc']), strpos($virtline[0], $this->_params['endocc'])); - - return array('usage' => $usage, 'limit' => $storage); - } - -} diff --git a/imp/lib/Quota/maildir.php b/imp/lib/Quota/maildir.php deleted file mode 100644 index 804067bea..000000000 --- a/imp/lib/Quota/maildir.php +++ /dev/null @@ -1,110 +0,0 @@ - array( - * 'driver' => 'maildir', - * 'params' => array( - * 'path' => '/path/to/users/Maildir' - * // TODO: Add config param for storage vs message quota - * ) - * ); - * - * path - The path to the user's Maildir directory. You may use the - * two-character sequence "~U" to represent the user's account name, - * and the actual username will be substituted in that location. - * E.g., '/home/~U/Maildir/' or '/var/mail/~U/Maildir/' - * - * Copyright 2007-2009 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Eric Rostetter - * @package IMP_Quota - */ -class IMP_Quota_Maildir extends IMP_Quota -{ - /** - * Constructor. - * - * @param array $params Hash containing connection parameters. - */ - protected function __construct($params = array()) - { - parent::__construct(array_merge(array('path' => ''), $params)); - } - - /** - * Returns quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - $storage_limit = $message_limit = $storage_used = $message_used = 0; - - // Get the full path to the quota file. - $full = $this->_params['path'] . '/maildirsize'; - - // Substitute the username in the string if needed. - $uname = $_SESSION['imp']['user']; - $full = str_replace('~U', $uname, $full); - - // Read in the quota file and parse it, if possible. - if (!is_file($full)) { - throw new Horde_Exception(_("Unable to retrieve quota")); - } - - // Read in maildir quota file. - $lines = file($full); - - // Parse the lines. - foreach ($lines as $line_number => $line) { - if ($line_number == 0) { - // First line, quota header. - $line = preg_replace('/[ \t\n\r\0\x0B]/', '', $line); - list($v1, $t1, $v2, $t2) = sscanf($line, '%ld%[CS],%ld%[CS]'); - if (is_null($v1) || is_null($t1)) { - $v1 = 0; - } - if (is_null($v2) || is_null($t2)) { - $v2 = 0; - } - - if ($t1 == 'S') { - $storage_limit = $v1; - } - if ($t1 == 'C') { - $message_limit = $v1; - } - if ($t2 == 'S') { - $storage_limit = $v2; - } - if ($t2 == 'C') { - $message_limit = $v2; - } - } else { - // Any line other than the first line. - // The quota used is the sum of all lines found. - list($storage, $message) = sscanf(trim($line), '%ld %d'); - if (!is_null($storage)) { - $storage_used += $storage; - } - if (!is_null($message)) { - $message_used += $message; - } - } - } - - return array('usage' => $storage_used, 'limit' => $storage_limit); - } - -} diff --git a/imp/lib/Quota/mdaemon.php b/imp/lib/Quota/mdaemon.php deleted file mode 100644 index 7dde77e5d..000000000 --- a/imp/lib/Quota/mdaemon.php +++ /dev/null @@ -1,109 +0,0 @@ - - * @package IMP_Quota - */ -class IMP_Quota_mdaemon extends IMP_Quota -{ - /** - * Get quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - $userDetails = $this->_getUserDetails($_SESSION['imp']['user'], $_SESSION['imp']['maildomain']); - - if ($userDetails !== false) { - $userHome = trim(substr($userDetails, 105, 90)); - $total = intval(substr($userDetails, 229, 6)) * 1024; - - if ($total == 0) { - return array('usage' => 0, 'limit' => 0); - } - - if (($taken = $this->_mailboxSize($userHome)) !== false) { - return array('usage' => $taken, 'limit' => $total); - } - } - - throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); - } - - /** - * Get the size of a mailbox - * - * @param string $path The full path of the mailbox to fetch the quota - * for including trailing backslash. - * - * @return mixed The number of bytes in the mailbox (integer) or false - * (boolean) on error. - */ - protected function _mailboxSize($path) - { - $contents = file_get_contents($path . '\imap.mrk'); - - $pointer = 36; - $size = 0; - while ($pointer < strlen($contents)) { - $details = unpack('a17Filename/a11Crap/VSize', substr($contents, $pointer, 36)); - $size += $details['Size']; - $pointer += 36; - } - - /* Recursivly check subfolders. */ - $d = dir($path); - while (($entry = $d->read()) !== false) { - if (($entry != '.') && - ($entry != '..') && - (substr($entry, -5, 5) == '.IMAP')) { - $size += $this->_mailboxSize($path . $entry . '\\'); - } - } - $d->close(); - - return $size; - } - - /** - * Retrieve relevant line from userlist.dat. - * - * @param string $user The username for which to retrieve detals. - * @param string $realm The realm (domain) for the user. - * - * @return mixed Line from userlist.dat (string) or false (boolean). - */ - protected function _getUserDetails($user, $realm) - { - $searchString = str_pad($realm, 45) . str_pad($user, 30); - - if (!($fp = fopen($this->_params['app_location'] . '/userlist.dat', 'rb'))) { - return false; - } - - while (!feof($fp)) { - $line = fgets($fp, 4096); - if (substr($line, 0, strlen($searchString)) == $searchString) { - fclose($fp); - return $line; - } - } - fclose($fp); - - return false; - } - -} diff --git a/imp/lib/Quota/mercury32.php b/imp/lib/Quota/mercury32.php deleted file mode 100644 index 001d47e2d..000000000 --- a/imp/lib/Quota/mercury32.php +++ /dev/null @@ -1,69 +0,0 @@ - array( - * 'driver' => 'mercury32', - * 'params' => array( - * 'mail_user_folder' => 'c:/mercry/mail' - * ) - * ); - * - * 'mail_user_folder' -- The path to folder mail mercury - * - ***************************************************************************** - * PROBLEM TO ACCESS NETWORK DIRECOTRY - ***************************************************************************** - * Matt Grimm - * 06-Jun-2003 10:25 - * - * Thought I could help clarify something with accessing network shares on a - * Windows network (2000 in this case), running PHP 4.3.2 under Apache 2.0.44. - * However you are logged into the Windows box, your Apache service must be - * running under an account which has access to the share. The easiest (and - * probably least safe) way for me was to change the user for the Apache - * service to the computer administrator (do this in the service properties, - * under the "Log On" tab). After restarting Apache, I could access mapped - * drives by their assigned drive letter ("z:\\") or regular shares by their - * UNC path ("\\\\shareDrive\\shareDir"). - ***************************************************************************** - * - * Copyright 2002-2009 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Frank Lupo - * @package IMP_Quota - */ -class IMP_Quota_mercury32 extends IMP_Quota -{ - /** - * Get quota information (used/allocated), in bytes. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - */ - public function getQuota() - { - $quota = null; - - $dir_path = $this->_params['mail_user_folder'] . '/' . $_SESSION['imp']['user'] . '/'; - if ($dir = @opendir($dir_path)) { - while (($file = readdir($dir)) !== false) { - $quota += filesize($dir_path . $file); - } - closedir($dir); - - if (!is_null($quota)) { - return array('usage' => $quota, 'limit' => 0); - } - } - - throw new Horde_Exception(_("Unable to retrieve quota"), 'horde.error'); - } - -} diff --git a/imp/lib/Quota/sql.php b/imp/lib/Quota/sql.php deleted file mode 100644 index 5e8eef4c2..000000000 --- a/imp/lib/Quota/sql.php +++ /dev/null @@ -1,141 +0,0 @@ - - * phptype -- Database type to connect to - * hostspec -- Database host - * username -- User name for DB connection - * password -- Password for DB connection - * database -- Database name - * query_quota -- SQL query which returns single row/column with user quota - * (in bytes). %u is replaced with current user name, %U with - * the user name without the domain part, %d with the domain. - * query_used -- SQL query which returns single row/column with user used - * space (in bytes). Placeholders are the same like in - * query_quota. - * - * - * Example how to reuse Horde's global SQL configuration: - * - * 'quota' => array( - * 'driver' => 'sql', - * 'params' => array_merge( - * $GLOBALS['conf']['sql'], - * array( - * 'query_quota' => 'SELECT quota FROM quotas WHERE user = ?', - * 'query_used' => 'SELECT used FROM quotas WHERE user = ?' - * ) - * ) - * ), - * - * - * Copyright 2006-2007 Tomas Simonaitis - * Copyright 2006-2009 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Tomas Simonaitis - * @author Jan Schneider - * @package IMP_Quota - */ -class IMP_Quota_sql extends IMP_Quota -{ - /** - * SQL connection object. - * - * @var DB - */ - protected $_db; - - /** - * State of SQL connection. - * - * @var boolean - */ - protected $_connected = false; - - /** - * Connects to the database - * - * @throws Horde_Exception - */ - protected function _connect() - { - if (!$this->_connected) { - $this->_db = DB::connect($this->_params, - array('persistent' => !empty($this->_params['persistent']), - 'ssl' => !empty($this->_params['ssl']))); - if ($this->_db instanceof PEAR_Error) { - throw new Horde_Exception(_("Unable to connect to SQL server.")); - } - - $this->_connected = true; - } - - return true; - } - - /** - * Returns quota information. - * - * @return array An array with the following keys: - * 'limit' = Maximum quota allowed - * 'usage' = Currently used portion of quota (in bytes) - * @throws Horde_Exception - */ - public function getQuota() - { - $conn = $this->_connect(); - $user = $_SESSION['imp']['user']; - $quota = array('limit' => 0, 'usage' => 0); - - if (!empty($this->_params['query_quota'])) { - @list($bare_user, $domain) = explode('@', $user, 2); - $query = str_replace(array('?', '%u', '%U', '%d'), - array($this->_db->quote($user), - $this->_db->quote($user), - $this->_db->quote($bare_user), - $this->_db->quote($domain)), - $this->_params['query_quota']); - $result = $this->_db->query($query); - if (is_a($result, 'PEAR_Error')) { - throw new Horde_Exception($result); - } - - $row = $result->fetchRow(DB_FETCHMODE_ASSOC); - if (is_array($row)) { - $quota['limit'] = current($row); - } - } else { - Horde::logMessage('IMP_Quota_sql: query_quota SQL query not set', __FILE__, __LINE__, PEAR_LOG_DEBUG); - } - - if (!empty($this->_params['query_used'])) { - @list($bare_user, $domain) = explode('@', $user, 2); - $query = str_replace(array('?', '%u', '%U', '%d'), - array($this->_db->quote($user), - $this->_db->quote($user), - $this->_db->quote($bare_user), - $this->_db->quote($domain)), - $this->_params['query_used']); - $result = $this->_db->query($query); - if (is_a($result, 'PEAR_Error')) { - throw new Horde_Exception($result); - } - - $row = $result->fetchRow(DB_FETCHMODE_ASSOC); - if (is_array($row)) { - $quota['usage'] = current($row); - } - } else { - Horde::logMessage('IMP_Quota_sql: query_used SQL query not set', __FILE__, __LINE__, PEAR_LOG_DEBUG); - } - - return $quota; - } - -} diff --git a/imp/lib/Sentmail.php b/imp/lib/Sentmail.php index 03e63c276..565c18cb0 100644 --- a/imp/lib/Sentmail.php +++ b/imp/lib/Sentmail.php @@ -43,8 +43,7 @@ class IMP_Sentmail $params = Horde::getDriverConfig('sentmail', $driver); } - $driver = basename($driver); - $class = 'IMP_Sentmail_' . $driver; + $class = 'IMP_Sentmail_' . ucfirst(basename($driver)); if (class_exists($class)) { try { @@ -60,7 +59,7 @@ class IMP_Sentmail * * @throws Horde_Exception */ - public function __construct($params = array()) + protected function __construct($params = array()) { $this->_params = $params; } diff --git a/imp/lib/Sentmail/Sql.php b/imp/lib/Sentmail/Sql.php new file mode 100644 index 000000000..467389234 --- /dev/null +++ b/imp/lib/Sentmail/Sql.php @@ -0,0 +1,216 @@ + + * 'phptype' The database type (e.g. 'pgsql', 'mysql', etc.). + * 'table' The name of the foo table in 'database'. + * + * Required by some database implementations:
+ *      'database'      The name of the database.
+ *      'hostspec'      The hostname of the database server.
+ *      'protocol'      The communication protocol ('tcp', 'unix', etc.).
+ *      'username'      The username with which to connect to the database.
+ *      'password'      The password associated with 'username'.
+ *      'options'       Additional options to pass to the database.
+ *      'tty'           The TTY on which to connect to the database.
+ *      'port'          The port on which to connect to the database.
+ * + * The table structure can be created by the scripts/sql/imp_sentmail.sql + * script. + * + * @author Jan Schneider + * @package IMP + */ +class IMP_Sentmail_Sql extends IMP_Sentmail +{ + /** + * Handle for the current database connection. + * + * @var DB + */ + protected $_db; + + /** + * Constructor. + * + * @param array $params A hash containing connection parameters. + * + * @throws Horde_Exception + */ + protected function __construct($params = array()) + { + parent::__construct($params); + + Horde::assertDriverConfig($this->_params, 'storage', array('phptype', 'table')); + + if (!isset($this->_params['database'])) { + $this->_params['database'] = ''; + } + if (!isset($this->_params['username'])) { + $this->_params['username'] = ''; + } + if (!isset($this->_params['hostspec'])) { + $this->_params['hostspec'] = ''; + } + + /* Connect to the SQL server using the supplied parameters. */ + $this->_db = DB::connect($this->_params, + array('persistent' => !empty($this->_params['persistent']), + 'ssl' => !empty($this->_params['ssl']))); + if ($this->_db instanceof PEAR_Error) { + throw new Horde_Exception($this->_db); + } + + /* Set DB portability options. */ + switch ($this->_db->phptype) { + case 'mssql': + $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM); + break; + + default: + $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); + } + } + + /** + * Logs an attempt to send a message per recipient. + * + * @param string $action Why the message was sent, i.e. "new", + * "reply", "forward", etc. + * @param string $message_id The Message-ID. + * @param string $recipients A message recipient. + * @param boolean $success Whether the attempt was successful. + */ + protected function _log($action, $message_id, $recipient, $success) + { + /* Build the SQL query. */ + $query = sprintf('INSERT INTO %s (sentmail_id, sentmail_who, sentmail_ts, sentmail_messageid, sentmail_action, sentmail_recipient, sentmail_success) VALUES (?, ?, ?, ?, ?, ?, ?)', + $this->_params['table']); + $values = array($this->_db->nextId($this->_params['table']), + Horde_Auth::getAuth(), + time(), + $message_id, + $action, + $recipient, + (int)$success); + + /* Log the query at a DEBUG log level. */ + Horde::logMessage(sprintf('IMP_Sentmail_sql::_log(): %s', $query), + __FILE__, __LINE__, PEAR_LOG_DEBUG); + + /* Execute the query. */ + $result = $this->_db->query($query, $values); + + /* Log errors. */ + if ($result instanceof PEAR_Error) { + Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); + } + } + + /** + * Returns the most favourite recipients. + * + * @param integer $limit Return this number of recipients. + * @param array $filter A list of messages types that should be returned. + * A value of null returns all message types. + * + * @return array A list with the $limit most favourite recipients. + * @throws Horde_Exception + */ + public function favouriteRecipients($limit, + $filter = array('new', 'forward', 'reply', 'redirect')) + { + /* Build the SQL query. */ + $where = ''; + if (!empty($filter)) { + $filter = array_map(array($this->_db, 'quote'), $filter); + $where = sprintf(' AND sentmail_action in (%s)', + implode(', ', $filter)); + } + $query = sprintf('SELECT sentmail_recipient, count(*) AS sentmail_count FROM %s WHERE sentmail_who = %s AND sentmail_success = 1%s GROUP BY sentmail_recipient ORDER BY sentmail_count DESC LIMIT %d', + $this->_params['table'], + $this->_db->quote(Horde_Auth::getAuth()), + $where, + $limit); + + /* Log the query at a DEBUG log level. */ + Horde::logMessage(sprintf('IMP_Sentmail_sql::favouriteRecipients(): %s', $query), + __FILE__, __LINE__, PEAR_LOG_DEBUG); + + /* Execute the query. */ + $recipients = $this->_db->getAll($query); + if ($recipients instanceof PEAR_Error) { + Horde::logMessage($recipients, __FILE__, __LINE__, PEAR_LOG_ERR); + throw new Horde_Exception($recipients); + } + + /* Extract email addresses. */ + $favourites = array(); + foreach ($recipients as $recipient) { + $favourites[] = $recipient[0]; + } + + return $favourites; + } + + /** + * Returns the number of recipients within a certain time period. + * + * @param integer $hours Time period in hours. + * @param boolean $user Return the number of recipients for the current + * user? + * + * @return integer The number of recipients in the given time period. + * @throws Horde_Exception + */ + public function numberOfRecipients($hours, $user = false) + { + /* Build the SQL query. */ + $query = sprintf('SELECT COUNT(*) FROM %s WHERE sentmail_ts > ?', + $this->_params['table']); + if ($user) { + $query .= sprintf(' AND sentmail_who = %s', $this->_db->quote(Horde_Auth::getAuth())); + } + + /* Log the query at a DEBUG log level. */ + Horde::logMessage(sprintf('IMP_Sentmail_sql::numberOfRecipients(): %s', $query), + __FILE__, __LINE__, PEAR_LOG_DEBUG); + + /* Execute the query. */ + $recipients = $this->_db->getOne($query, array(time() - $hours * 3600)); + if ($recipients instanceof PEAR_Error) { + Horde::logMessage($recipients, __FILE__, __LINE__, PEAR_LOG_ERR); + throw new Horde_Exception($recipients); + } + + return $recipients; + } + + /** + * Deletes all log entries older than a certain date. + * + * @param integer $before Unix timestamp before that all log entries + * should be deleted. + * + * @throw Horde_Exception + */ + protected function _deleteOldEntries($before) + { + /* Build the SQL query. */ + $query = sprintf('DELETE FROM %s WHERE sentmail_ts < ?', + $this->_params['table']); + + /* Log the query at a DEBUG log level. */ + Horde::logMessage(sprintf('IMP_Sentmail_sql::_deleteOldEntries(): %s', $query), + __FILE__, __LINE__, PEAR_LOG_DEBUG); + + /* Execute the query. */ + $result = $this->_db->query($query, array($before)); + if ($result instanceof PEAR_Error) { + Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); + throw new Horde_Exception($result); + } + } + +} diff --git a/imp/lib/Sentmail/sql.php b/imp/lib/Sentmail/sql.php deleted file mode 100644 index e8d1417fa..000000000 --- a/imp/lib/Sentmail/sql.php +++ /dev/null @@ -1,216 +0,0 @@ - - * 'phptype' The database type (e.g. 'pgsql', 'mysql', etc.). - * 'table' The name of the foo table in 'database'. - * - * Required by some database implementations:
- *      'database'      The name of the database.
- *      'hostspec'      The hostname of the database server.
- *      'protocol'      The communication protocol ('tcp', 'unix', etc.).
- *      'username'      The username with which to connect to the database.
- *      'password'      The password associated with 'username'.
- *      'options'       Additional options to pass to the database.
- *      'tty'           The TTY on which to connect to the database.
- *      'port'          The port on which to connect to the database.
- * - * The table structure can be created by the scripts/sql/imp_sentmail.sql - * script. - * - * @author Jan Schneider - * @package IMP - */ -class IMP_Sentmail_sql extends IMP_Sentmail -{ - /** - * Handle for the current database connection. - * - * @var DB - */ - protected $_db; - - /** - * Constructor. - * - * @param array $params A hash containing connection parameters. - * - * @throws Horde_Exception - */ - function __construct($params = array()) - { - parent::__construct($params); - - Horde::assertDriverConfig($this->_params, 'storage', array('phptype', 'table')); - - if (!isset($this->_params['database'])) { - $this->_params['database'] = ''; - } - if (!isset($this->_params['username'])) { - $this->_params['username'] = ''; - } - if (!isset($this->_params['hostspec'])) { - $this->_params['hostspec'] = ''; - } - - /* Connect to the SQL server using the supplied parameters. */ - $this->_db = DB::connect($this->_params, - array('persistent' => !empty($this->_params['persistent']), - 'ssl' => !empty($this->_params['ssl']))); - if (is_a($this->_db, 'PEAR_Error')) { - throw new Horde_Exception($this->_db); - } - - /* Set DB portability options. */ - switch ($this->_db->phptype) { - case 'mssql': - $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM); - break; - - default: - $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); - } - } - - /** - * Logs an attempt to send a message per recipient. - * - * @param string $action Why the message was sent, i.e. "new", - * "reply", "forward", etc. - * @param string $message_id The Message-ID. - * @param string $recipients A message recipient. - * @param boolean $success Whether the attempt was successful. - */ - protected function _log($action, $message_id, $recipient, $success) - { - /* Build the SQL query. */ - $query = sprintf('INSERT INTO %s (sentmail_id, sentmail_who, sentmail_ts, sentmail_messageid, sentmail_action, sentmail_recipient, sentmail_success) VALUES (?, ?, ?, ?, ?, ?, ?)', - $this->_params['table']); - $values = array($this->_db->nextId($this->_params['table']), - Horde_Auth::getAuth(), - time(), - $message_id, - $action, - $recipient, - (int)$success); - - /* Log the query at a DEBUG log level. */ - Horde::logMessage(sprintf('IMP_Sentmail_sql::_log(): %s', $query), - __FILE__, __LINE__, PEAR_LOG_DEBUG); - - /* Execute the query. */ - $result = $this->_db->query($query, $values); - - /* Log errors. */ - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); - } - } - - /** - * Returns the most favourite recipients. - * - * @param integer $limit Return this number of recipients. - * @param array $filter A list of messages types that should be returned. - * A value of null returns all message types. - * - * @return array A list with the $limit most favourite recipients. - * @throws Horde_Exception - */ - public function favouriteRecipients($limit, - $filter = array('new', 'forward', 'reply', 'redirect')) - { - /* Build the SQL query. */ - $where = ''; - if (!empty($filter)) { - $filter = array_map(array($this->_db, 'quote'), $filter); - $where = sprintf(' AND sentmail_action in (%s)', - implode(', ', $filter)); - } - $query = sprintf('SELECT sentmail_recipient, count(*) AS sentmail_count FROM %s WHERE sentmail_who = %s AND sentmail_success = 1%s GROUP BY sentmail_recipient ORDER BY sentmail_count DESC LIMIT %d', - $this->_params['table'], - $this->_db->quote(Horde_Auth::getAuth()), - $where, - $limit); - - /* Log the query at a DEBUG log level. */ - Horde::logMessage(sprintf('IMP_Sentmail_sql::favouriteRecipients(): %s', $query), - __FILE__, __LINE__, PEAR_LOG_DEBUG); - - /* Execute the query. */ - $recipients = $this->_db->getAll($query); - if (is_a($recipients, 'PEAR_Error')) { - Horde::logMessage($recipients, __FILE__, __LINE__, PEAR_LOG_ERR); - throw new Horde_Exception($recipients); - } - - /* Extract email addresses. */ - $favourites = array(); - foreach ($recipients as $recipient) { - $favourites[] = $recipient[0]; - } - - return $favourites; - } - - /** - * Returns the number of recipients within a certain time period. - * - * @param integer $hours Time period in hours. - * @param boolean $user Return the number of recipients for the current - * user? - * - * @return integer The number of recipients in the given time period. - * @throws Horde_Exception - */ - public function numberOfRecipients($hours, $user = false) - { - /* Build the SQL query. */ - $query = sprintf('SELECT COUNT(*) FROM %s WHERE sentmail_ts > ?', - $this->_params['table']); - if ($user) { - $query .= sprintf(' AND sentmail_who = %s', $this->_db->quote(Horde_Auth::getAuth())); - } - - /* Log the query at a DEBUG log level. */ - Horde::logMessage(sprintf('IMP_Sentmail_sql::numberOfRecipients(): %s', $query), - __FILE__, __LINE__, PEAR_LOG_DEBUG); - - /* Execute the query. */ - $recipients = $this->_db->getOne($query, array(time() - $hours * 3600)); - if (is_a($recipients, 'PEAR_Error')) { - Horde::logMessage($recipients, __FILE__, __LINE__, PEAR_LOG_ERR); - throw new Horde_Exception($recipients); - } - - return $recipients; - } - - /** - * Deletes all log entries older than a certain date. - * - * @param integer $before Unix timestamp before that all log entries - * should be deleted. - * - * @throw Horde_Exception - */ - protected function _deleteOldEntries($before) - { - /* Build the SQL query. */ - $query = sprintf('DELETE FROM %s WHERE sentmail_ts < ?', - $this->_params['table']); - - /* Log the query at a DEBUG log level. */ - Horde::logMessage(sprintf('IMP_Sentmail_sql::_deleteOldEntries(): %s', $query), - __FILE__, __LINE__, PEAR_LOG_DEBUG); - - /* Execute the query. */ - $result = $this->_db->query($query, array($before)); - if (is_a($result, 'PEAR_Error')) { - Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); - throw new Horde_Exception($result); - } - } - -}