Files
server/usr/share/psa-horde/ingo/lib/Storage/Sql.php
2026-01-07 20:52:11 +01:00

363 lines
14 KiB
PHP

<?php
/**
* Copyright 2012-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @author Jan Schneider <jan@horde.org>
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @category Horde
* @license http://www.horde.org/licenses/apache ASL
* @package Ingo
*/
/**
* Ingo_Storage_Sql implements the Ingo_Storage API to save Ingo data via
* Horde's Horde_Db database abstraction layer.
*
* @author Jan Schneider <jan@horde.org>
* @author Mike Cochrane <mike@graftonhall.co.nz>
* @category Horde
* @license http://www.horde.org/licenses/apache ASL
* @package Ingo
*/
class Ingo_Storage_Sql extends Ingo_Storage
{
/**
* Retrieves the specified data from the storage backend.
*
* @param integer $field The field name of the desired data.
* See lib/Storage.php for the available fields.
* @param boolean $readonly Whether to disable any write operations.
*
* @return Ingo_Storage_Rule|Ingo_Storage_Filters The specified data.
* @throws Ingo_Exception
*/
protected function _retrieve($field, $readonly = false)
{
switch ($field) {
case self::ACTION_BLACKLIST:
case self::ACTION_WHITELIST:
if ($field == self::ACTION_BLACKLIST) {
$ob = new Ingo_Storage_Blacklist();
$filters = $this->retrieve(self::ACTION_FILTERS);
$rule = $filters->findRule($field);
if (isset($rule['action-value'])) {
$ob->setBlacklistFolder($rule['action-value']);
}
} else {
$ob = new Ingo_Storage_Whitelist();
}
$query = sprintf('SELECT list_address FROM %s WHERE list_owner = ? AND list_blacklist = ?',
$this->_params['table_lists']);
$values = array(Ingo::getUser(),
(int)($field == self::ACTION_BLACKLIST));
try {
$addresses = $this->_params['db']->selectValues($query, $values);
} catch (Horde_Db_Exception $e) {
Horde::log($e->getMessage(), 'ERR');
throw new Ingo_Exception($e);
}
if ($field == self::ACTION_BLACKLIST) {
$ob->setBlacklist($addresses);
} else {
$ob->setWhitelist($addresses);
}
break;
case self::ACTION_FILTERS:
$ob = new Ingo_Storage_Filters_Sql($this->_params['db'], $this->_params);
$ob->init($readonly);
break;
case self::ACTION_FORWARD:
$query = sprintf('SELECT * FROM %s WHERE forward_owner = ?',
$this->_params['table_forwards']);
try {
$data = $this->_params['db']->selectOne(
$query, array(Ingo::getUser())
);
$columns = $this->_params['db']->columns(
$this->_params['table_forwards']
);
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
$ob = new Ingo_Storage_Forward();
if (!empty($data)) {
$ob->setForwardAddresses(explode(
"\n",
$columns['forward_addresses']->binaryToString(
$data['forward_addresses']
)
));
$ob->setForwardKeep((bool)$data['forward_keep']);
$ob->setSaved(true);
} elseif ($data = @unserialize($GLOBALS['prefs']->getDefault('forward'))) {
$ob->setForwardAddresses($data['a']);
$ob->setForwardKeep($data['k']);
}
break;
case self::ACTION_VACATION:
$query = sprintf('SELECT * FROM %s WHERE vacation_owner = ?',
$this->_params['table_vacations']);
try {
$data = $this->_params['db']->selectOne(
$query, array(Ingo::getUser())
);
$columns = $this->_params['db']->columns(
$this->_params['table_vacations']
);
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
$ob = new Ingo_Storage_Vacation();
if (!empty($data)) {
$ob->setVacationAddresses(explode(
"\n",
$columns['vacation_addresses']->binaryToString(
$data['vacation_addresses']
)
));
$ob->setVacationDays((int)$data['vacation_days']);
$ob->setVacationStart((int)$data['vacation_start']);
$ob->setVacationEnd((int)$data['vacation_end']);
$ob->setVacationExcludes(explode(
"\n",
$columns['vacation_excludes']->binaryToString(
$data['vacation_excludes']
)
));
$ob->setVacationIgnorelist((bool)$data['vacation_ignorelists']);
$ob->setVacationReason(Horde_String::convertCharset(
$columns['vacation_reason']->binaryToString(
$data['vacation_reason']
),
$this->_params['charset'],
'UTF-8'
));
$ob->setVacationSubject(Horde_String::convertCharset(
$data['vacation_subject'],
$this->_params['charset'],
'UTF-8'
));
$ob->setSaved(true);
} elseif ($data = @unserialize($GLOBALS['prefs']->getDefault('vacation'))) {
$ob->setVacationAddresses($data['addresses'], false);
$ob->setVacationDays($data['days']);
$ob->setVacationExcludes($data['excludes']);
$ob->setVacationIgnorelist($data['ignorelist']);
$ob->setVacationReason($data['reason']);
$ob->setVacationSubject($data['subject']);
if (isset($data['start'])) {
$ob->setVacationStart($data['start']);
}
if (isset($data['end'])) {
$ob->setVacationEnd($data['end']);
}
}
break;
case self::ACTION_SPAM:
$query = sprintf('SELECT * FROM %s WHERE spam_owner = ?',
$this->_params['table_spam']);
try {
$data = $this->_params['db']->selectOne($query, array(Ingo::getUser()));
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
$ob = new Ingo_Storage_Spam();
if (!empty($data)) {
$ob->setSpamFolder($data['spam_folder']);
$ob->setSpamLevel((int)$data['spam_level']);
$ob->setSaved(true);
} elseif ($data = @unserialize($GLOBALS['prefs']->getDefault('spam'))) {
$ob->setSpamFolder($data['folder']);
$ob->setSpamLevel($data['level']);
}
break;
default:
$ob = false;
}
return $ob;
}
/**
* Stores the specified data in the storage backend.
*
* @access private
*
* @param Ingo_Storage_Rule|Ingo_Storage_Filters $ob The object to store.
*/
protected function _store($ob)
{
switch ($ob->obType()) {
case self::ACTION_BLACKLIST:
case self::ACTION_WHITELIST:
$is_blacklist = (int)($ob->obType() == self::ACTION_BLACKLIST);
if ($is_blacklist) {
$filters = $this->retrieve(self::ACTION_FILTERS);
$id = $filters->findRuleId(self::ACTION_BLACKLIST);
if ($id !== null) {
$rule = $filters->getRule($id);
if (!isset($rule['action-value']) ||
$rule['action-value'] != $ob->getBlacklistFolder()) {
$rule['action-value'] = $ob->getBlacklistFolder();
$filters->updateRule($rule, $id);
}
}
}
$query = sprintf('DELETE FROM %s WHERE list_owner = ? AND list_blacklist = ?',
$this->_params['table_lists']);
$values = array(Ingo::getUser(), $is_blacklist);
try {
$this->_params['db']->delete($query, $values);
} catch (Horde_Db_Exception $e) {
Horde::log($e, 'ERR');
throw new Ingo_Exception($e);
}
$query = sprintf('INSERT INTO %s (list_owner, list_blacklist, list_address) VALUES (?, ?, ?)',
$this->_params['table_lists']);
$addresses = $is_blacklist ? $ob->getBlacklist() : $ob->getWhitelist();
foreach ($addresses as $address) {
try {
$result = $this->_params['db']->insert(
$query,
array(Ingo::getUser(),
$is_blacklist,
$address));
} catch (Horde_Db_Exception $e) {
Horde::log($e, 'ERR');
throw new Ingo_Exception($e);
}
}
$ob->setSaved(true);
break;
case self::ACTION_FORWARD:
$values = array(
new Horde_Db_Value_Text(
implode("\n", $ob->getForwardAddresses())
),
(int)(bool)$ob->getForwardKeep(),
Ingo::getUser());
try {
if ($ob->isSaved()) {
$query = sprintf('UPDATE %s SET forward_addresses = ?, forward_keep = ? WHERE forward_owner = ?', $this->_params['table_forwards']);
$this->_params['db']->update($query, $values);
} else {
$query = sprintf('INSERT INTO %s (forward_addresses, forward_keep, forward_owner) VALUES (?, ?, ?)', $this->_params['table_forwards']);
$this->_params['db']->insert($query, $values);
}
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
$ob->setSaved(true);
break;
case self::ACTION_VACATION:
$values = array(
new Horde_Db_Value_Text(
implode("\n", $ob->getVacationAddresses())
),
Horde_String::convertCharset(
$ob->getVacationSubject(),
'UTF-8',
$this->_params['charset']
),
new Horde_Db_Value_Text(Horde_String::convertCharset(
$ob->getVacationReason(),
'UTF-8',
$this->_params['charset']
)),
(int)$ob->getVacationDays(),
(int)$ob->getVacationStart(),
(int)$ob->getVacationEnd(),
new Horde_Db_Value_Text(
implode("\n", $ob->getVacationExcludes())
),
(int)(bool)$ob->getVacationIgnorelist(),
Ingo::getUser()
);
try {
if ($ob->isSaved()) {
$query = sprintf('UPDATE %s SET vacation_addresses = ?, vacation_subject = ?, vacation_reason = ?, vacation_days = ?, vacation_start = ?, vacation_end = ?, vacation_excludes = ?, vacation_ignorelists = ? WHERE vacation_owner = ?', $this->_params['table_vacations']);
$this->_params['db']->update($query, $values);
} else {
$query = sprintf('INSERT INTO %s (vacation_addresses, vacation_subject, vacation_reason, vacation_days, vacation_start, vacation_end, vacation_excludes, vacation_ignorelists, vacation_owner) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', $this->_params['table_vacations']);
$this->_params['db']->insert($query, $values);
}
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
$ob->setSaved(true);
break;
case self::ACTION_SPAM:
$values = array(
(int)$ob->getSpamLevel(),
$ob->getSpamFolder(),
Ingo::getUser());
try {
if ($ob->isSaved()) {
$query = sprintf('UPDATE %s SET spam_level = ?, spam_folder = ? WHERE spam_owner = ?', $this->_params['table_spam']);
$this->_params['db']->update($query, $values);
} else {
$query = sprintf('INSERT INTO %s (spam_level, spam_folder, spam_owner) VALUES (?, ?, ?)', $this->_params['table_spam']);
$this->_params['db']->insert($query, $values);
}
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
$ob->setSaved(true);
break;
}
}
/**
* Removes the data of the specified user from the storage backend.
*
* @param string $user The user name to delete filters for.
*
* @throws Ingo_Exception
*/
public function removeUserData($user)
{
if (!$GLOBALS['registry']->isAdmin() &&
$user != $GLOBALS['registry']->getAuth()) {
throw new Ingo_Exception(_("Permission Denied"));
}
$queries = array(sprintf('DELETE FROM %s WHERE rule_owner = ?',
$this->_params['table_rules']),
sprintf('DELETE FROM %s WHERE list_owner = ?',
$this->_params['table_lists']),
sprintf('DELETE FROM %s WHERE vacation_owner = ?',
$this->_params['table_vacations']),
sprintf('DELETE FROM %s WHERE forward_owner = ?',
$this->_params['table_forwards']),
sprintf('DELETE FROM %s WHERE spam_owner = ?',
$this->_params['table_spam']));
$values = array($user);
foreach ($queries as $query) {
try {
$this->_params['db']->delete($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Ingo_Exception($e);
}
}
return true;
}
}