From: Michael M Slusarz Date: Thu, 25 Mar 2010 17:55:04 +0000 (-0600) Subject: Preferences UI rewrite. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=6e6599dfe74533b868cb0aaa80eeb6a2d482ce92;p=horde.git Preferences UI rewrite. Goals of the rewrite: 1. Make ALL preference page display across ALL applications handled by a single point: the horde services preference page. This means moving all application specifc preference handling to inside of Horde_Registry_Application functions. NO page, other than horde/services/prefs.php, should be using the Horde Prefs UI functions anymore. 2. Move Horde Prefs UI code out of Prefs package and into the Core package. UI handling is not something that should be handled by a library (will eventually move other things out of Prefs too, including Category Management and Identity code, since this is code that overlays the Prefs driver in a Horde-specific manner) 3. Simplify the prefs UI configuration. Don't require 'shared' or 'locked' entries (default to false) or 'type' entry (default to 'implicit'). Remove some unneeded types (select). Improve documentation. 4. Handle dynamic population of entries and suppression of prefGroups and specific preferences in Application::prefsInit(). This code confuses the prefs.php file. 5. Abstract out some common 'special' preference handlers. For example, identical addressbook selection code is used in several applications (imp, kronolith, whups). Move this code to a prefs UI widgets class so it can be reused. 6. Convert prefs templates to Horde_Template. As always, I know the arguments against HT, but the simple fact is that is still the only time-tested method that we used and it does produce a template file that is easy to edit. Not to mention that the PHP code polluting the old include files made these files absolutely unreadable and/or maintainable. 7. Remove credentials code. It wasn't being used anywhere in the code (I believe it used to be a hack for IMP-related auth in Horde 3.x, but shouldn't be needed anymore due to new authentication code). 8. Other improvements that have escaped my mind since I have been working on this code for several weeks now... Reasons for the rewrite: 1. The old Prefs UI code was ancient and a mess. It was a static file and globals were used all over the place. New UI code is OO-based and allows us to pass the object around, making these like suppression of groups/prefs, hiding buttons, and current state identification much easier and cleaner. 2. There is a need to redo the UI itself, especially for dynamic apps, to allow for a different/better preferences experience. Thus, the UI will eventually be able to be themed based on the current view type (dynamic, standard, mobile/minimal). To do this, all UI needs to be controlled from a single source, rather than disparate scripts. 3. Add ability to mark preferences as 'advanced' so they are not shown by default. This is prefereable to the current method of 'locking' advanced prefs. Admins may very well want users to be able to change a pref, but they don't want that pref shown to basic users. --- diff --git a/agora/config/prefs.php.dist b/agora/config/prefs.php.dist index 82ad0f276..efe4109f6 100644 --- a/agora/config/prefs.php.dist +++ b/agora/config/prefs.php.dist @@ -10,7 +10,7 @@ if ($GLOBALS['conf']['avatar']['allow_avatars']) { 'column' => _("My Information"), 'label' => _("Avatar"), 'desc' => _("Set the avatar image that is shown with your posts."), - 'members' => array('avatar_path', 'avatarselect') + 'members' => array('avatar_path', 'avatar_link') ); } @@ -25,15 +25,20 @@ $prefGroups['display_threads'] = array( 'column' => _("Display Options"), 'label' => _("Threads View"), 'desc' => _("Set your options for the threads view."), - 'members' => array('threads_sortby', 'threads_sortdir', 'threads_hot', 'threads_per_page') + 'members' => array( + 'threads_sortby', 'threads_sortdir', 'threads_hot', + 'threads_per_page' + ) ); $prefGroups['display_thread'] = array( 'column' => _("Display Options"), 'label' => _("Single Thread View"), 'desc' => _("Set your options for the single thread view."), - 'members' => array('thread_sortby', 'thread_sortdir', 'thread_view_bodies', - 'thread_per_page') + 'members' => array( + 'thread_sortby', 'thread_sortdir', 'thread_view_bodies', + 'thread_per_page' + ) ); $prefGroups['display_message'] = array( @@ -47,59 +52,67 @@ $prefGroups['display_comments'] = array( 'column' => _("Display Options"), 'label' => _("Comments view"), 'desc' => _("Set your options for the single thread view."), - 'members' => array('comments_sortby', 'comments_sortdir', 'comments_view_bodies', - 'comments_per_page') + 'members' => array( + 'comments_sortby', 'comments_sortdir', 'comments_view_bodies', + 'comments_per_page' + ) ); /* Avatar */ $_prefs['avatar_path'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'text', 'desc' => _("The location of your avatar image.") ); -if ($GLOBALS['conf']['avatar']['allow_avatars'] && $GLOBALS['conf']['avatar']['enable_image_tests']) { +if ($GLOBALS['conf']['avatar']['allow_avatars'] && + $GLOBALS['conf']['avatar']['enable_image_tests']) { $_prefs['avatar_path']['desc'] .= ' ' . sprintf(_("Avatars must be smaller than %s by %s pixels and less than %sKb in size."), $GLOBALS['conf']['avatar']['max_width'], $GLOBALS['conf']['avatar']['max_height'], $GLOBALS['conf']['avatar']['max_size']); } -$_prefs['avatarselect'] = array('type' => 'special'); +$_prefs['avatar_link'] = array( + 'type' => 'rawhtml', + 'url' => '

' . _("Choose from a gallery of avatars:") . '

' +); /* Forums */ $_prefs['forums_sortby'] = array( 'value' => 'forum_name', - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array('forum_name' => _("Forum"), - 'message_count' => _("Messages"), - 'message_subject' => _("Last Message"), - 'message_author' => _("Posted by"), - 'message_date' => _("Date")), + 'enum' => array( + 'forum_name' => _("Forum"), + 'message_count' => _("Messages"), + 'message_subject' => _("Last Message"), + 'message_author' => _("Posted by"), + 'message_date' => _("Date") + ), 'desc' => _("Default forums view sort:") ); $_prefs['forums_sortdir'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("Ascending"), - 1 => _("Descending")), + 'enum' => array( + 0 => _("Ascending"), + 1 => _("Descending") + ), 'desc' => _("Default sorting direction:") ); $_prefs['forums_per_page'] = array( 'value' => 20, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25), + 'enum' => array( + 5 => 5, + 10 => 10, + 15 => 15, + 20 => 20, + 25 => 25 + ), 'desc' => _("Number of forums to display on each page") ); @@ -107,42 +120,44 @@ $_prefs['forums_per_page'] = array( $_prefs['threads_sortby'] = array( 'value' => 'message_modifystamp', - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array('message_thread' => _("Thread"), - 'message_subject' => _("Subject"), - 'message_author' => _("Posted by"), - 'message_seq' => _("Posts"), - 'message_timestamp' => _("Date"), - 'message_modifystamp' => _("Last post")), + 'enum' => array( + 'message_thread' => _("Thread"), + 'message_subject' => _("Subject"), + 'message_author' => _("Posted by"), + 'message_seq' => _("Posts"), + 'message_timestamp' => _("Date"), + 'message_modifystamp' => _("Last post") + ), 'desc' => _("Default threads view sort:") ); $_prefs['threads_sortdir'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("Ascending"), - 1 => _("Descending")), + 'enum' => array( + 0 => _("Ascending"), + 1 => _("Descending") + ), 'desc' => _("Default sorting direction:") ); $_prefs['threads_hot'] = array( 'value' => 20, - 'locked' => false, - 'shared' => false, 'type' => 'number', 'desc' => _("Number of views in 24hrs to trigger a 'hot-thread':") ); $_prefs['threads_per_page'] = array( 'value' => 10, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25), + 'enum' => array( + 5 => 5, + 10 => 10, + 15 => 15, + 20 => 20, + 25 => 25 + ), 'desc' => _("Number of messages to display on each page") ); @@ -150,78 +165,74 @@ $_prefs['threads_per_page'] = array( $_prefs['thread_sortby'] = array( 'value' => 'message_timestamp', - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array('message_thread' => _("Thread"), - 'message_subject' => _("Subject"), - 'message_author' => _("Posted by"), - 'message_timestamp' => _("Date")), + 'enum' => array( + 'message_thread' => _("Thread"), + 'message_subject' => _("Subject"), + 'message_author' => _("Posted by"), + 'message_timestamp' => _("Date") + ), 'desc' => _("Default thread view sort:") ); $_prefs['thread_sortdir'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("Ascending"), - 1 => _("Descending")), + 'enum' => array( + 0 => _("Ascending"), + 1 => _("Descending") + ), 'desc' => _("Default sorting direction:") ); $_prefs['thread_view_bodies'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("No"), - 1 => _("Yes"), - 2 => _("Yes, and don't thread them")), + 'enum' => array( + 0 => _("No"), + 1 => _("Yes"), + 2 => _("Yes, and don't thread them") + ), 'desc' => _("Display full message bodies in the thread list view?") ); $_prefs['thread_per_page'] = array( 'value' => 10, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25), + 'enum' => array( + 5 => 5, + 10 => 10, + 15 => 15, + 20 => 20, + 25 => 25 + ), 'desc' => _("Number of message to display on each page") ); $_prefs['message_emoticons'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("No graphical emoticons"), - 1 => _("Show graphical emoticons")), + 'enum' => array( + 0 => _("No graphical emoticons"), + 1 => _("Show graphical emoticons") + ), 'desc' => _("Display graphical emoticons?") ); $_prefs['forums_block_display'] = array( - 'value' => 0, - 'type' => 'implicit' + 'value' => 0 ); $_prefs['threads_block_display'] = array( - 'value' => 0, - 'type' => 'implicit' + 'value' => 0 ); $_prefs['moderate_sortby'] = array( - 'value' => 'message_id', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + 'value' => 'message_id' ); $_prefs['moderate_sortdir'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + 'value' => 0 ); @@ -229,40 +240,44 @@ $_prefs['moderate_sortdir'] = array( $_prefs['comments_view_bodies'] = array( 'value' => 2, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(2 => _("Flat"), - 1 => _("Thread")), + 'enum' => array( + 2 => _("Flat"), + 1 => _("Thread") + ), 'desc' => _("Display full message bodies in the comments view?") ); $_prefs['comments_sortby'] = array( 'value' => 'message_timestamp', - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array('message_subject' => _("Subject"), - 'message_author' => _("Posted by"), - 'message_timestamp' => _("Date")), + 'enum' => array( + 'message_subject' => _("Subject"), + 'message_author' => _("Posted by"), + 'message_timestamp' => _("Date") + ), 'desc' => _("Default comments view sort:") ); $_prefs['comments_sortdir'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("Ascending"), - 1 => _("Descending")), + 'enum' => array( + 0 => _("Ascending"), + 1 => _("Descending") + ), 'desc' => _("Default sorting direction:") ); $_prefs['comments_per_page'] = array( 'value' => 20, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(5 => 5, 10 => 10, 15 => 15, 20 => 20, 25 => 25), + 'enum' => array( + 5 => 5, + 10 => 10, + 15 => 15, + 20 => 20, + 25 => 25 + ), 'desc' => _("Number of messages to display on each page") ); diff --git a/agora/lib/Application.php b/agora/lib/Application.php index 92dbf8485..a99324dad 100644 --- a/agora/lib/Application.php +++ b/agora/lib/Application.php @@ -84,6 +84,50 @@ class Agora_Application extends Horde_Registry_Application } /** + * Code to run on init when viewing prefs for this application. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + public function prefsInit($ui) + { + switch ($ui->group) { + case 'display_avatar': + $vfs = Agora::getVFS(); + if (!($vfs instanceof PEAR_Error) && + $GLOBALS['conf']['avatar']['enable_gallery'] && + $vfs->isFolder(Agora::AVATAR_PATH, 'gallery')) { + Horde::addScriptFile('popup.js', 'horde', true); + } else { + $suppress[] = 'avatar_link' + } + break; + } + + /* Hide appropriate prefGroups. */ + if (!$GLOBALS['conf']['avatar']['allow_avatars']) { + $ui->suppressGroups[] = 'display_avatar'; + } + } + + /** + * Generate code used to display a special preference. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return string The HTML code to display on the options page. + */ + public function prefsSpecial($ui, $item) + { + switch ($item) { + case 'avatarselect': + return $this->_accountsManagement($ui); + } + + return ''; + } + + /** * Generate the menu to use on the prefs page. * * @return Horde_Menu A Horde_Menu object. diff --git a/agora/templates/prefs/avatarselect.inc b/agora/templates/prefs/avatarselect.inc deleted file mode 100644 index 22157e061..000000000 --- a/agora/templates/prefs/avatarselect.inc +++ /dev/null @@ -1,10 +0,0 @@ -isFolder(Agora::AVATAR_PATH, 'gallery')): ?> -

- -

- diff --git a/ansel/lib/Application.php b/ansel/lib/Application.php index f63c1502e..5a50395ec 100644 --- a/ansel/lib/Application.php +++ b/ansel/lib/Application.php @@ -97,32 +97,28 @@ class Ansel_Application extends Horde_Registry_Application /** * Special preferences handling on update. * - * @param string $item The preference name. - * @param boolean $updated Set to true if preference was updated. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. * * @return boolean True if preference was updated. */ - public function prefsSpecial($item, $updated) + public function prefsSpecialUpdate($ui, $item) { switch ($item) { case 'default_category_select': - $default_category = Horde_Util::getFormData('default_category_select'); - if (!is_null($default_category)) { - $GLOBALS['prefs']->setValue('default_category', $default_category); + if (isset($ui->vars->default_category_select)) { + $GLOBALS['prefs']->setValue('default_category', $ui->vars->default_category_select); return true; } break; case 'default_gallerystyle_select': - $default_style = Horde_Util::getFormData('default_gallerystyle_select'); - if (!is_null($default_style)) { - $GLOBALS['prefs']->setValue('default_gallerystyle', $default_style); + if (isset($ui->vars->default_gallerystyle_select)) { + $GLOBALS['prefs']->setValue('default_gallerystyle', $ui->vars->default_gallerystyle_select); return true; } break; } - - return $updated; } /** diff --git a/fima/lib/Application.php b/fima/lib/Application.php index fb9628b52..f9985712b 100644 --- a/fima/lib/Application.php +++ b/fima/lib/Application.php @@ -6,38 +6,33 @@ class Fima_Application extends Horde_Regsitry_Application /** * Special preferences handling on update. * - * @param string $item The preference name. - * @param boolean $updated Set to true if preference was updated. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. * * @return boolean True if preference was updated. */ - public function prefsSpecial($item, $updated) + public function prefsSpecialUpdate($ui, $item) { switch ($item) { case 'ledgerselect': - $active_ledger = Horde_Util::getFormData('active_ledger'); - if (!is_null($active_ledger)) { + if (isset($ui->vars->active_ledger)) { $ledgers = Fima::listLedgers(); if (is_array($ledgers) && - array_key_exists($active_ledger, $ledgers)) { - $GLOBALS['prefs']->setValue('active_ledger', $active_ledger); + array_key_exists($ui->vars->active_ledger, $ledgers)) { + $GLOBALS['prefs']->setValue('active_ledger', $ui->vars->active_ledger); return true; } } break; case 'closedperiodselect': - $period = Horde_Util::getFormData('closedperiod'); - if ((int)$period['year'] > 0 && (int)$period['month'] > 0) { - $period = mktime(0, 0, 0, $period['month'] + 1, 0, $period['year']); - } else { - $period = 0; - } + $period = $ui->vars->closedperiod; + $period = ((int)$period['year'] > 0 && (int)$period['month'] > 0) + ? mktime(0, 0, 0, $period['month'] + 1, 0, $period['year']) + : 0; $GLOBALS['prefs']->setValue('closed_period', $period); return true; } - - return $updated; } /** diff --git a/framework/Core/lib/Horde/Core/Prefs/Ui.php b/framework/Core/lib/Horde/Core/Prefs/Ui.php new file mode 100644 index 000000000..82024c03a --- /dev/null +++ b/framework/Core/lib/Horde/Core/Prefs/Ui.php @@ -0,0 +1,711 @@ + + * @author Michael Slusarz + * @category Horde + * @package Core + */ +class Horde_Core_Prefs_Ui +{ + /** + * Preferences groups. + * + * @var array + */ + public $prefGroups = array(); + + /** + * Preferences. + * + * @var array + */ + public $prefs = array(); + + /** + * Data overrides (for 'enum' and 'multienum' types). + * + * @var array + */ + public $override = array(); + + /** + * Suppressed preference entries. + * + * @var array + */ + public $suppress = array(); + + /** + * Suppressed prefGroup entries. + * + * @var array + */ + public $suppressGroups = array(); + + /** + * Current application. + * + * @var string + */ + public $app; + + /** + * Current preferences group. + * + * @var string + */ + public $group; + + /** + * Form variables for this page load. + * + * @var Horde_Variables + */ + public $vars; + + /** + * If set, suppresses display of the buttons. + * + * @var boolean + */ + public $nobuttons = false; + + /** + * Constructor. + * + * @param Horde_Variables $vars Form variables. + */ + public function __construct($vars) + { + $this->app = isset($vars->app) + ? $vars->app + : $this->getDefaultApp(); + $this->group = $vars->group; + $this->vars = $vars; + + /* Load the application's base environment. */ + $GLOBALS['registry']->pushApp($this->app); + + /* Load preferences. */ + $this->_loadPrefs($this->app); + } + + /** + * Hide the menu display for prefs UI pages during this session? + * + * @param boolean $hide If true, hides the menu. + */ + static public function hideMenu($hide) + { + $_SESSION['horde_prefs']['nomenu'] = $hide; + } + + /** + * Determine whether or not a preferences group is editable. + * + * @param string $group The preferences group to check. + * + * @return boolean Whether or not the group is editable. + */ + public function groupIsEditable($group) + { + return (bool)count($this->getChangeablePrefs($group)); + } + + /** + * Returns the list of changeable prefs for a group. + * + * @param string $group The preferences group to check. + * @param boolean $implicit Don't add to list if marked as implict? + * + * @return array The list of changeable prefs. + */ + public function getChangeablePrefs($group, $implicit = false) + { + $prefs = array(); + + foreach ($this->prefGroups[$group]['members'] as $pref) { + if (!$GLOBALS['prefs']->isLocked($pref) && + !in_array($pref, $this->suppress) && + (!$implicit || + (!empty($this->prefs[$pref]['type']) && + ($this->prefs[$pref]['type'] != 'implicit')))) { + $prefs[] = $pref; + } + } + + return $prefs; + } + + /** + * Handle a preferences form submission if there is one, updating + * any preferences which have been changed. + * + * @return boolean Whether preferences have been updated. + */ + public function handleForm() + { + if (!$this->group || !$this->groupIsEditable($this->group)) { + return false; + } + + if (isset($this->vars->prefs_return)) { + $this->group = $this->vars->actionID = ''; + return false; + } + + switch ($this->vars->actionID) { + case 'update_prefs': + return $this->_handleForm($this->getChangeablePrefs($this->group)); + + case 'update_special': + $special = array(); + foreach ($this->getChangeablePrefs($this->group, true) as $pref) { + if ($this->prefs[$pref]['type'] == 'special') { + $special[] = $pref; + } + } + return $this->_handleForm($special); + } + + return false; + } + + /* + * Handle a preferences form submission if there is one, updating + * any preferences which have been changed. + * + * @param array $preflist The list of preferences to process. + * + * @return boolean Whether preferences have been updated. + */ + protected function _handleForm($preflist) + { + global $notification, $prefs, $registry; + + $updated = false; + + /* Run through the action handlers */ + foreach ($preflist as $pref) { + switch ($this->prefs[$pref]['type']) { + case 'alarm': + $methods = Horde_Alarm::notificationMethods(); + $val = (isset($this->vars->$pref) && is_array($this->vars->$pref)) + ? $this->vars->$pref + : array(); + $value = array(); + + foreach ($val as $method) { + $value[$method] = array(); + if (!empty($methods[$method])) { + foreach (array_keys($methods[$method]) as $param) { + $value[$method][$param] = $this->vars->get($pref . '_' . $param, ''); + if (is_array($methods[$method][$param]) && + $methods[$method][$param]['required'] && + ($value[$method][$param] === '')) { + $notification->push(sprintf(_("You must provide a setting for \"%s\"."), $methods[$method][$param]['desc']), 'horde.error'); + break 3; + } + } + } + } + + $updated |= $prefs->setValue($pref, serialize($value)); + break; + + case 'checkbox': + $updated |= $prefs->setValue($pref, intval(isset($this->vars->$pref))); + break; + + case 'enum': + if (isset($this->prefs[$pref]['enum'][$this->vars->$pref])) { + $updated |= $prefs->setValue($pref, $this->vars->$pref); + } else { + $notification->push(_("An illegal value was specified."), 'horde.error'); + } + break; + + case 'multienum': + $set = array(); + + if (is_array($this->vars->$pref)) { + foreach ($this->vars->$pref as $val) { + if (isset($this->prefs[$pref]['enum'][$val])) { + $set[] = $val; + } else { + $notification->push(_("An illegal value was specified."), 'horde.error'); + break 2; + } + } + } + + $updated |= $prefs->setValue($pref, @serialize($set)); + break; + + case 'number': + $num = $this->vars->$pref; + if ((string)(double)$num !== $num) { + $notification->push(_("This value must be a number."), 'horde.error'); + } elseif (empty($num)) { + $notification->push(_("This number must be non-zero."), 'horde.error'); + } else { + $updated |= $prefs->setValue($pref, $num); + } + break; + + case 'password': + case 'text': + case 'textarea': + $updated |= $prefs->setValue($pref, $this->vars->$pref); + break; + + + case 'special': + /* Code for special elements written specifically for each + * application. */ + if ($registry->hasAppMethod($this->app, 'prefsSpecialUpdate')) { + $updated = $updated | (bool)$registry->callAppMethod($this->app, 'prefsSpecialUpdate', array('args' => array($this, $pref))); + } + break; + } + } + + if ($updated) { + if ($registry->hasAppMethod($this->app, 'prefsCallback')) { + $registry->callAppMethod($this->app, 'prefsCallback', array('args' => array($this))); + } + + if ($prefs instanceof Horde_Prefs_Session) { + $notification->push(_("Your options have been updated for the duration of this session."), 'horde.success'); + } else { + $notification->push(_("Your options have been updated."), 'horde.success'); + } + + $this->_loadPrefs($this->app); + } + + return $updated; + } + + /** + * Returns a self URL to the current page. + * + * @param array $options Additional options: + *
+     * 'special' - (boolean) If set, will trigger special action update
+     *             processing when the URL is loaded.
+     * 
+ * + * @return Horde_Url The URL object. + */ + public function selfUrl($options = array()) + { + $url = Horde::getServiceLink('options', $this->app); + if ($this->group) { + $url->add('group', $this->group); + } + if (!empty($options['special'])) { + $url->add('actionID', 'update_special'); + } + return $url; + } + + /** + * Generate the UI for the preferences interface, either for a + * specific group, or the group selection interface. + */ + public function generateUI() + { + global $notification, $prefs, $registry; + + $columns = $pref_list = array(); + + /* Run app-specific init code. */ + if ($registry->hasAppMethod($this->app, 'prefsInit')) { + $registry->callAppMethod($this->app, 'prefsInit', array('args' => array($this))); + } + + $prefgroups = $this->_getPrefGroups(); + + if ($this->group) { + $pref_list = $this->getChangeablePrefs($this->group, true); + } else { + foreach ($prefgroups as $key => $val) { + $columns[$val['column']][$key] = $val; + } + } + + if (empty($columns) && empty($pref_list)) { + $notification->push(_("There are no options available."), 'horde.message'); + $this->nobuttons = true; + } + + $options_link = Horde::getServiceLink('options'); + $h_templates = $registry->get('templates', 'horde'); + + $base = $GLOBALS['injector']->createInstance('Horde_Template'); + $base->setOption('gettext', true); + + /* Need to buffer output - it is possible that 'special' types can + * do things like add javascript to the page output. This should all + * be combined and served in the page HEAD. */ + ob_start(); + + if ($this->group) { + foreach ($pref_list as $pref) { + if ($this->prefs[$pref]['type'] == 'special') { + if ($registry->hasAppMethod($this->app, 'prefsSpecial')) { + echo $registry->callAppMethod($this->app, 'prefsSpecial', array('args' => array($this, $pref))); + } + + continue; + } + + $t = clone $base; + if (isset($this->prefs[$pref]['desc'])) { + $t->set('desc', Horde::label($pref, $this->prefs[$pref]['desc'])); + } + $t->set('helplink', empty($this->prefs[$pref]['help']) ? null : Horde_Help::link(empty($this->prefs[$pref]['shared']) ? $this->app : 'horde', $this->prefs[$pref]['help'])); + $t->set('pref', htmlspecialchars($pref)); + + $type = $this->prefs[$pref]['type']; + switch ($type) { + case 'alarm': + Horde::addScriptFile('alarmprefs.js', 'horde'); + Horde::addInlineScript(array( + 'HordeAlarmPrefs.pref = ' . Horde_Serialize::serialize($pref, Horde_Serialize::JSON) + )); + + $alarm_pref = unserialize($prefs->getValue($pref)); + $selected = array_keys($alarm_pref); + + $param_list = $select_list = array(); + foreach (Horde_Alarm::notificationMethods() as $method => $params) { + $select_list[] = array( + 'l' => $params['__desc'], + 's' => in_array($method, $selected), + 'v' => $method + ); + + if (count($params > 1)) { + $tmp = array( + 'method' => $method, + 'param' => array() + ); + + foreach ($params as $name => $param) { + if (substr($name, 0, 2) == '__') { + continue; + } + + switch ($param['type']) { + case 'text': + $tmp['param'][] = array( + 'label' => Horde::label($pref . '_' . $name, $param['desc']), + 'name' => $pref . '_' . $name, + 'text' => true, + 'value' => empty($alarm_pref[$method][$name]) ? '' : htmlspecialchars($alarm_pref[$method][$name]) + ); + break; + + case 'bool': + $tmp['param'][] = array( + 'bool' => true, + 'checked' => !empty($alarm_pref[$method][$name]), + 'label' => Horde::label($pref . '_' . $name, $param['desc']), + 'name' => $pref . '_' . $name + ); + break; + + case 'sound': + $current_sound = empty($alarm_pref[$method][$name]) + ? '' + : $alarm_pref[$method][$name]; + $sounds = array(); + foreach (Horde_Themes::soundList() as $key => $val) { + $sounds[] = array( + 'c' => ($current_sound == $key), + 'uri' => htmlspecialchars($val->uri), + 'val' => htmlspecialchars($key) + ); + } + + $tmp['param'][] = array( + 'sound' => true, + 'checked' => !$current_sound, + 'name' => $pref . '_' . $name + ); + break; + } + } + + $param_list[] = $tmp; + } + } + $t->set('param_list', $param_list); + $t->set('select_list', $select_list); + break; + + case 'checkbox': + $t->set('checked', $prefs->getValue($pref)); + break; + + case 'enum': + $enum = isset($this->override[$pref]) + ? $this->override[$pref] + : $this->prefs[$pref]['enum']; + $esc = !empty($this->prefs[$pref]['escaped']); + $curval = $prefs->getValue($pref); + + $tmp = array(); + foreach ($enum as $key => $val) { + $tmp[] = array( + 'l' => $esc ? $val : htmlspecialchars($val), + 's' => ($curval == $key), + 'v' => $esc ? $key : htmlspecialchars($key) + ); + } + $t->set('enum', $tmp); + break; + + case 'prefslink': + $url = $this->selfUrl()->add('group', $this->prefs[$pref]['group']); + if (!empty($this->prefs[$pref]['app'])) { + $url->add('app', $this->prefs[$pref]['app']); + } + $this->prefs[$pref]['url'] = $url; + $type = 'link'; + // Fall through to 'link' + + case 'link': + if (isset($this->prefs[$pref]['img'])) { + $t->set('img', Horde::img($this->prefs[$pref]['img'], $this->prefs[$pref]['desc'], array('class' => 'prefsLinkImg'))); + } + $t->set('url', isset($this->prefs[$pref]['url']) ? Horde::applicationUrl($this->prefs[$pref]['url']) : $this->prefs[$pref]['xurl']); + if (isset($this->prefs[$pref]['target'])) { + $t->set('target', htmlspecialchars($this->prefs[$pref]['target'])); + } + break; + + case 'multienum': + $enum = isset($this->override[$pref]) + ? $this->override[$pref] + : $this->prefs[$pref]['enum']; + $esc = !empty($this->prefs[$pref]['escaped']); + if (!$selected = @unserialize($prefs->getValue($pref))) { + $selected = array(); + } + + $tmp = array(); + foreach ($enum as $key => $val) { + $tmp[] = array( + 'l' => $esc ? $val : htmlspecialchars($val), + 's' => in_array($key, $selected), + 'v' => $esc ? $key : htmlspecialchars($key) + ); + } + $t->set('enum', $tmp); + + $t->set('size', min(4, count($enum))); + break; + + case 'number': + $t->set('val', htmlspecialchars(intval($prefs->getValue($pref)))); + break; + + case 'password': + case 'text': + case 'textarea': + $t->set('val', htmlspecialchars($prefs->getValue($pref))); + break; + + case 'rawhtml': + $t->set('html', $this->prefs[$pref]['value']); + break; + } + + echo $t->fetch(HORDE_TEMPLATES . '/prefs/' . $type . '.html'); + } + + $t = clone $base; + $t->set('buttons', !$this->nobuttons); + $t->set('prefgroups', count($prefgroups) > 1); + echo $t->fetch($h_templates . '/prefs/end.html'); + } elseif (!empty($columns)) { + $t = clone $base; + $span = round(100 / count($columns)); + + $cols = array(); + foreach ($columns as $key => $column) { + $tmp = array( + 'groups' => array(), + 'hdr' => htmlspecialchars($key), + 'width' => $span - 1 + ); + + foreach ($column as $group => $gvals) { + if ($this->groupIsEditable($group)) { + $tmp['groups'][] = array( + 'desc' => htmlspecialchars($gvals['desc']), + 'link' => Horde::widget($options_link->copy()->add(array('app' => $this->app, 'group' => $group)), $gvals['label'], '', '', '', $gvals['label']) + ); + } + } + $cols[] = $tmp; + } + $t->set('columns', $cols); + + echo $t->fetch($h_templates . '/prefs/overview.html'); + } + + $content = ob_get_clean(); + + $title = _("User Options"); + + /* Get the menu output before we start to output the page. + * Again, this will catch any javascript inserted into the page. */ + if (empty($_SESSION['horde_prefs']['nomenu'])) { + if ($registry->hasAppMethod($this->app, 'prefsMenu')) { + $menu = $registry->callAppMethod($this->app, 'prefsMenu', array('args' => array($this))); + } + } + + /* Get list of accessible applications. */ + $apps = array(); + foreach ($registry->listApps() as $app) { + // Make sure the app is installed and has a prefs file. + if (file_exists($registry->get('fileroot', $app) . '/config/prefs.php')) { + $apps[$app] = $registry->get('name', $app); + } + } + asort($apps); + + /* Ouptut screen. */ + $GLOBALS['bodyId'] = 'services_prefs'; + require $h_templates . '/common-header.inc'; + + if (empty($_SESSION['horde_prefs']['nomenu'])) { + require $h_templates . '/menu/menu.inc'; + } + + $notification->notify(array('listeners' => 'status')); + + $base_ui = clone $base; + $base_ui->set('action', $options_link); + $base_ui->set('forminput', Horde_Util::formInput()); + + /* Show the current application and a form for switching + * applications. */ + $t = clone $base_ui; + $t->set('horde', !empty($apps['horde'])); + unset($apps['horde'], $apps[$this->app]); + $tmp = array(); + foreach ($apps as $key => $val) { + $tmp[] = array( + 'l' => htmlspecialchars($val), + 'v' => htmlspecialchars($key) + ); + } + $t->set('apps', $tmp); + $t->set('header', htmlspecialchars(($this->app == 'horde') ? _("Global Options") : sprintf(_("Options for %s"), $registry->get('name', $this->app)))); + echo $t->fetch($h_templates . '/prefs/app.html'); + + /* Generate navigation header. */ + if ($this->group) { + $t = clone $base_ui; + $t->set('app', htmlspecialchars($this->app)); + $t->set('group', htmlspecialchars($this->group)); + $t->set('label', htmlspecialchars($this->prefGroups[$this->group]['label'])); + + // Search for previous and next groups. + if (count($prefgroups) > 1) { + $prefgroups = array_keys($prefgroups); + $key = array_search($this->group, $prefgroups); + $previous = isset($prefgroups[$key - 1]) + ? $prefgroups[$key - 1] + : end($prefgroups); + $next = isset($prefgroups[$key + 1]) + ? $prefgroups[$key + 1] + : reset($prefgroups); + $prefs_url = $this->selfUrl(); + + $t->set('prev', $prefs_url->copy()->add('group', $previous)); + $t->set('prevlabel', htmlspecialchars($this->prefGroups[$previous]['label'])); + $t->set('next', $prefs_url->copy()->add('group', $next)); + $t->set('nextlabel', htmlspecialchars($this->prefGroups[$next]['label'])); + } + + echo $t->fetch($h_templates . '/prefs/begin.html'); + } + + echo $content; + + require $h_templates . '/common-footer.inc'; + } + + /** + * Get the default application to show preferences for. Defaults + * to 'horde'. + * + * @return string The default application. + */ + public function getDefaultApp() + { + $applications = $GLOBALS['registry']->listApps(null, true, Horde_Perms::READ); + return isset($applications['horde']) + ? 'horde' + : array_shift($applications); + } + + /** + * Loads preferences configuration into the current object. + * + * @param string $app The application. + */ + protected function _loadPrefs($app, $merge = false) + { + try { + $res = Horde::loadConfiguration('prefs.php', array('prefGroups', '_prefs'), $app); + $this->prefGroups = $res['prefGroups']; + $this->prefs = $res['_prefs']; + } catch (Horde_Exception $e) { + $this->prefGroups = $this->prefs = array(); + } + + /* If there's only one prefGroup, just show it. */ + if (!$this->group && (count($this->prefGroups) == 1)) { + reset($this->prefGroups); + $this->group = key($this->prefGroups); + } + } + + /** + * Get the list of viewable preference groups, filtering out suppressed + * groups and groups with no settable prefs. + * + * @return array The filtered prefGroups array. + */ + protected function _getPrefGroups() + { + $out = array(); + + foreach (array_diff(array_keys($this->prefGroups), $this->suppressGroups) as $val) { + if ($this->groupIsEditable($val)) { + $out[$val] = $this->prefGroups[$val]; + } + } + + return $out; + } + +} diff --git a/framework/Core/lib/Horde/Core/Prefs/Ui/Widgets.php b/framework/Core/lib/Horde/Core/Prefs/Ui/Widgets.php new file mode 100644 index 000000000..b4a43eea6 --- /dev/null +++ b/framework/Core/lib/Horde/Core/Prefs/Ui/Widgets.php @@ -0,0 +1,203 @@ + + * @category Horde + * @package Core + */ +class Horde_Core_Prefs_Ui_Widgets +{ + /* Source selection widget. */ + + /** + * Code to run on init. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + static public function sourceInit($ui) + { + Horde::addScriptFile('sourceselect.js', 'horde'); + } + + /** + * Create code needed for source selection. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param array $data REQUIRED data items: + *
+     * 'mainlabel'
+     * 'selected'
+     * 'selectlabel'
+     * 'unselected'
+     * 'unselectlabel'
+     * 
+ * + * @return string HTML UI code. + */ + static public function source($ui, $data = array()) + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('mainlabel', $data['mainlabel']); + $t->set('selectlabel', $data['selectlabel']); + $t->set('unselectlabel', $data['unselectlabel']); + + $unselected = array(); + foreach ($data['unselected'] as $key => $val) { + $unselected[] = array( + 'l' => $val, + 'v' => $key + ); + } + $t->set('unselected', $unselected); + + $selected = array(); + foreach ($data['selected'] as $key => $val) { + $selected[] = array( + 'l' => $val, + 'v' => $key + ); + } + $t->set('selected', $selected); + + $t->set('addimg', Horde::img(isset($GLOBALS['nls']['rtl'][$GLOBALS['language']]) ? 'lhand.png' : 'rhand.png', _("Add source"))); + $t->set('removeimg', Horde::img(isset($GLOBALS['nls']['rtl'][$GLOBALS['language']]) ? 'rhand.png' : 'lhand.png', _("Remove source"))); + + $t->set('upimg', Horde::img('nav/up.png', _("Move up"))); + $t->set('downimg', Horde::img('nav/down.png', _("Move down"))); + + return $t->fetch(HORDE_TEMPLATES . '/prefs/source.html'); + } + + /* Addressbook selection widget. Extends the source widget to handle + * the special case of addressbook selection. */ + + /** + * Code to run on init for addressbook selection. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + static public function addressbooksInit($ui) + { + self::sourceInit($ui); + Horde::addScriptFile('addressbooksprefs.js', 'horde'); + } + + /** + * Create code needed for addressbook selection. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + static public function addressbooks($ui) + { + global $prefs, $registry; + + $selected = $unselected = array(); + $out = ''; + + if (!$registry->hasMethod('contacts/sources') || + $prefs->isLocked('search_sources')) { + return; + } + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + try { + $readable = $registry->call('contacts/sources'); + } catch (Horde_Exception $e) { + $readable = array(); + } + + try { + $writeable = $registry->call('contacts/sources', array(true)); + } catch (Horde_Exception $e) { + $writeable = array(); + } + + $search = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); + + if (count($readable) == 1) { + // Only one source, no need to display the selection widget + $search['sources'] = array_keys($readable); + } + + foreach ($search['sources'] as $source) { + if (!empty($readable[$source])) { + $selected[$source] = $readable[$source]; + } + } + + foreach (array_diff(array_keys($readable), $search['sources']) as $val) { + $unselected[$val] = $readable[$val]; + } + + if (!empty($selected) || !empty($unselected)) { + $out = Horde_Core_Prefs_Ui_Widgets::source($ui, array( + 'mainlabel' => _("Choose the order of address books to search when expanding addresses."), + 'selected' => $selected, + 'selectlabel' => _("Selected address books:"), + 'unselected' => $unselected, + 'unselectlabel' => _("Available address books:") + )); + + $t->set('selected', count($unselected) > 1); + + $js = array(); + foreach (array_keys($readable) as $source) { + $tmp = array($source); + + try { + foreach ($registry->call('contacts/fields', array($source)) as $field) { + if ($field['search']) { + $tmp[] = array($field['name'], $field['label'], isset($search['fields'][$source]) && in_array($field['name'], $search['fields'][$source])); + } + } + } catch (Horde_Exception $e) {} + + $js[] = $tmp; + } + + Horde::addInlineScript(array( + 'HordeAddressbooksPrefs.fields = ' . Horde_Serialize::serialize($js, Horde_Serialize::JSON, Horde_Nls::getCharset()) + )); + } + + return $out . $t->fetch(HORDE_TEMPLATES . '/prefs/addressbooks.html'); + } + + /** + * Update prefs for addressbook selection. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return boolean True if preferences were updated. + */ + static public function addressbooksUpdate($ui) + { + $updated = false; + + if (isset($ui->vars->sources)) { + $GLOBALS['prefs']->setValue('search_sources', implode("\t", Horde_Serialize::unserialize($ui->vars->sources, Horde_Serialize::JSON))); + $updated = true; + } + + if (isset($ui->vars->search_fields_string)) { + $GLOBALS['prefs']->setValue('search_fields', $ui->vars->search_fields_string); + $updated = true; + } + + return $updated; + } + +} diff --git a/framework/Core/lib/Horde/Core/Prefs/Utils.php b/framework/Core/lib/Horde/Core/Prefs/Utils.php new file mode 100644 index 000000000..cd2603652 --- /dev/null +++ b/framework/Core/lib/Horde/Core/Prefs/Utils.php @@ -0,0 +1,49 @@ + + * @category Horde + * @package Core + */ +class Horde_Core_Prefs_Utils +{ + /** + * Determines parameters needed to do an address search + * + * @return array An array with two keys: 'sources' and 'fields'. + */ + static public function getAddressbookSearchParams() + { + $src = explode("\t", $GLOBALS['prefs']->getValue('search_sources')); + if ((count($src) == 1) && empty($src[0])) { + $src = array(); + } + + $fields = array(); + if (($val = $GLOBALS['prefs']->getValue('search_fields'))) { + $field_arr = explode("\n", $val); + foreach ($field_arr as $field) { + $field = trim($field); + if (!empty($field)) { + $tmp = explode("\t", $field); + if (count($tmp) > 1) { + $source = array_splice($tmp, 0, 1); + $fields[$source[0]] = $tmp; + } + } + } + } + + return array( + 'fields' => $fields, + 'sources' => $src + ); + } + +} diff --git a/framework/Core/lib/Horde/Registry/Application.php b/framework/Core/lib/Horde/Registry/Application.php index b4fc4ce61..f3eff0dfb 100644 --- a/framework/Core/lib/Horde/Registry/Application.php +++ b/framework/Core/lib/Horde/Registry/Application.php @@ -95,4 +95,56 @@ class Horde_Registry_Application { } + // Horde_Core_Prefs_Ui functions. + + /** + * Code to run if the language preference changes. + */ + // public function changeLanguage() {} + + /** + * Code to run on init when viewing prefs for this application. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + // public function prefsInit($ui) {} + + /** + * Called when preferences are changed. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + // public function prefsCallback($ui) {} + + /** + * Generate the menu to use on the prefs page. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return Horde_Menu The Horde_Menu object to display. + */ + // public function prefsMenu($ui) {} + + /** + * Generate code used to display a special preference. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return string The HTML code to display on the options page. + */ + // public function prefsSpecial($ui, $item) {} + + /** + * Special preferences handling on update. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return boolean True if preference was updated. + */ + // public function prefsSpecialUpdate($ui, $item) {} + + // END Horde_Core_Prefs_Ui functions. + } diff --git a/framework/Core/lib/Horde/Script/Files.php b/framework/Core/lib/Horde/Script/Files.php index 965847eaf..276a625c5 100644 --- a/framework/Core/lib/Horde/Script/Files.php +++ b/framework/Core/lib/Horde/Script/Files.php @@ -41,9 +41,8 @@ class Horde_Script_Files */ public function add($file, $app = null, $direct = false, $full = false) { - $res = $this->_add($file, $app, $direct, $full); - - if (($res === false) || (!ob_get_length() && !headers_sent())) { + if (($this->_add($file, $app, $direct, $full) === false) || + !(ob_get_length() && headers_sent())) { return; } diff --git a/framework/Core/package.xml b/framework/Core/package.xml index 4dae572b9..2b5aa1c99 100644 --- a/framework/Core/package.xml +++ b/framework/Core/package.xml @@ -37,7 +37,8 @@ Application Framework. beta LGPL - * Convert from PEAR Log to Horde_Log for logging. + * Import prefs UI handling class from Horde_Prefs. + * Convert from PEAR Log to Horde_Log for logging. * Add Horde_Themes:: class. * Add Horde::nocacheUrl(). * Remove dependency on Horde_DOM package. @@ -93,6 +94,13 @@ Application Framework. + + + + + + + @@ -226,6 +234,9 @@ Application Framework. + + + diff --git a/framework/Prefs/lib/Horde/Prefs.php b/framework/Prefs/lib/Horde/Prefs.php index ea923667d..929576b02 100644 --- a/framework/Prefs/lib/Horde/Prefs.php +++ b/framework/Prefs/lib/Horde/Prefs.php @@ -4,36 +4,14 @@ * various preferences storage mediums. It also includes all of the * functions for retrieving, storing, and checking preference values. * - * TODO: document the format of the $_prefs hash here - * - * $_prefs[*pref name*] = array( - * 'value' => *Default value*, - * 'locked' => *boolean*, - * 'shared' => *boolean*, - * 'type' => 'checkbox' - * 'text' - * 'password' - * 'textarea' - * 'select' - * 'number' - * 'implicit' - * 'special' - * 'link' - There must be a field named either 'url' - * (internal application link) or 'xurl' - * (external application link) if this type is used. - * 'enum' - * 'enum' => TODO, - * 'desc' => _(*Description string*), - * 'help' => *Name of the entry in the XML help file* - * ); - * * Copyright 1999-2010 The Horde Project (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * - * @author Jon Parise - * @package Horde_Prefs + * @author Jon Parise + * @category Horde + * @package Prefs */ class Horde_Prefs { @@ -62,9 +40,9 @@ class Horde_Prefs * itself a hash, so this will ultimately be multi-dimensional. * * [*pref name*] => Array( - * [d] => *default value* - * [m] => *pref mask* - * [v] => *pref value* + * [d] => (string) Default value + * [m] => (integer) Pref mask + * [v] => (string) Current pref value * ) * * @var array @@ -332,6 +310,9 @@ class Horde_Prefs return $result; } + /** + * Shortcut to setValue(). + */ public function __set($name, $value) { return $this->setValue($name, $value); @@ -375,7 +356,7 @@ class Horde_Prefs if (isset($GLOBALS['conf']['prefs']['maxsize']) && (strlen($val) > $GLOBALS['conf']['prefs']['maxsize']) && isset($GLOBALS['notification'])) { - $GLOBALS['notification']->push(sprintf(_("The preference \"%s\" could not be saved because its data exceeded the maximum allowable size"), $pref), 'horde.error'); + $GLOBALS['notification']->push(sprintf(_("The preference \"%s\" could not be saved because its data exceeds the maximum allowable size"), $pref), 'horde.error'); return false; } @@ -425,6 +406,9 @@ class Horde_Prefs return $value; } + /** + * Shortcut to getValue(). + */ public function __get($name) { return $this->getValue($name); @@ -781,56 +765,50 @@ class Horde_Prefs * the default values. */ try { $result = Horde::loadConfiguration('prefs.php', array('_prefs'), $scope); - if (empty($result)) { + if (empty($result) || !isset($result['_prefs'])) { return; } } catch (Horde_Exception $e) { return; } - extract($result); - if (!isset($_prefs)) { - return; - } + foreach ($result['_prefs'] as $name => $pref) { + if (!isset($pref['value'])) { + continue; + } - foreach ($_prefs as $name => $pref) { - if (isset($pref['value']) && - isset($pref['locked']) && - isset($pref['shared']) && - ($pref['type'] != 'link') && - ($pref['type'] != 'special')) { - $name = str_replace('.', '_', $name); + $name = str_replace('.', '_', $name); - $mask = 0; - $mask &= ~self::DIRTY; - $mask |= self::PREFS_DEFAULT; + $mask = 0; + $mask &= ~self::DIRTY; + $mask |= self::PREFS_DEFAULT; - if ($pref['locked']) { - $mask |= self::LOCKED; - } + if (!empty($pref['locked'])) { + $mask |= self::LOCKED; + } - if ($pref['shared'] || ($scope == 'horde')) { - $mask |= self::SHARED; - $pref_scope = 'horde'; - } else { - $pref_scope = $scope; - } + if (empty($pref['shared'])) { + $pref_scope = $scope; + } else { + $mask |= self::SHARED; + $pref_scope = 'horde'; + } - if ($pref['shared'] && isset($this->_scopes[$pref_scope][$name])) { - // This is a shared preference that was already - // retrieved. - $this->_scopes[$pref_scope][$name]['m'] = $mask & ~self::PREFS_DEFAULT; - $this->_scopes[$pref_scope][$name]['d'] = $pref['value']; - } else { - $this->_scopes[$pref_scope][$name] = array('v' => $pref['value'], 'm' => $mask, 'd' => $pref['value']); - } + if (!empty($pref['shared']) && + isset($this->_scopes[$pref_scope][$name])) { + // This is a shared preference that was already retrieved. + $this->_scopes[$pref_scope][$name]['m'] = $mask & ~self::PREFS_DEFAULT; + $this->_scopes[$pref_scope][$name]['d'] = $pref['value']; + } else { + $this->_scopes[$pref_scope][$name] = array( + 'd' => $pref['value'], + 'm' => $mask, + 'v' => $pref['value'] + ); + } - if (!empty($pref['hook'])) { - if (!isset($this->_hooks[$scope])) { - $this->_hooks[$scope] = array(); - } - $this->_hooks[$scope][$name] = $pref_scope; - } + if (!empty($pref['hook'])) { + $this->_hooks[$scope][$name] = $pref_scope; } } } diff --git a/framework/Prefs/lib/Horde/Prefs/CategoryManager.php b/framework/Prefs/lib/Horde/Prefs/CategoryManager.php index f339ec03e..a6a7b6078 100644 --- a/framework/Prefs/lib/Horde/Prefs/CategoryManager.php +++ b/framework/Prefs/lib/Horde/Prefs/CategoryManager.php @@ -10,7 +10,7 @@ * * @author Chuck Hagenbuch * @category Horde - * @package Horde_Prefs + * @package Prefs */ class Horde_Prefs_CategoryManager { diff --git a/framework/Prefs/lib/Horde/Prefs/Credentials.php b/framework/Prefs/lib/Horde/Prefs/Credentials.php deleted file mode 100644 index a2d7fb3f8..000000000 --- a/framework/Prefs/lib/Horde/Prefs/Credentials.php +++ /dev/null @@ -1,160 +0,0 @@ - - * @category Horde - * @package Horde_Prefs - */ -class Horde_Prefs_Credentials -{ - /** - * Singleton instance. - * - * @var Horde_Prefs_Credentials - */ - static protected $_instance = null; - - /** - * Cache for getCredentials(). - * - * @var array - */ - static protected $_credentialsCache = null; - - /** - * The Horde application currently processed. - * - * @see singleton() - * @var string - */ - protected $app; - - /** - * A list of preference field names and their values. - * - * @var array - */ - protected $_credentials = array(); - - /** - * Constructor. - */ - public function __construct() - { - $credentials = @unserialize($GLOBALS['prefs']->getValue('credentials')); - if ($credentials) { - foreach ($credentials as $app => $app_prefs) { - foreach ($app_prefs as $name => $value) { - $this->_credentials['credentials[' . $app . '][' . $name . ']'] = $value; - } - } - } - } - - /** - * Returns a single instance of the Prefs_Credentials class, and sets the - * curently processed application. - * - * @param string $app The current application. - * - * @return Prefs_Credentials A Prefs_Credentials instance. - */ - static public function singleton($app) - { - if (is_null(self::$_instance)) { - self::$_instance = new self(); - } - self::$_instance->app = $app; - - return self::$_instance; - } - - /** - * Returns a list of available credentials collected from all Horde - * applications. - * - * @return array A list of Horde applications and their credentials. - */ - static public function getCredentials() - { - if (!is_null(self::$_credentialsCache)) { - return self::$_credentialsCache; - } - - self::$_credentialsCache = array(); - foreach ($GLOBALS['registry']->listApps() as $app) { - try { - $credentials = $GLOBALS['registry']->callAppMethod($app, 'authCredentials'); - } catch (Horde_Exception $e) { - continue; - } - - if (!count($credentials)) { - continue; - } - - self::$_credentialsCache[$app] = array(); - foreach ($credentials as $name => $credential) { - $pref = 'credentials[' . $app . '][' . $name . ']'; - $credential['shared'] = true; - self::$_credentialsCache[$app][$pref] = $credential; - } - } - - return self::$_credentialsCache; - } - - /** - * Displays the preference interface for setting all available - * credentials. - */ - static public function showUi() - { - $credentials = self::getCredentials(); - $vspace = ''; - foreach ($credentials as $app => $_prefs) { - $prefs = Horde_Prefs_Credentials::singleton($app); - echo $vspace . '

'; - printf(_("%s authentication credentials"), - $GLOBALS['registry']->get('name', $app)); - echo '

'; - foreach (array_keys($_prefs) as $pref) { - $helplink = empty($_prefs[$pref]['help']) - ? null - : Horde_Help::link(!empty($_prefs[$pref]['shared']) ? 'horde' : $GLOBALS['registry']->getApp(), $_prefs[$pref]['help']); - require $GLOBALS['registry']->get('templates') . '/prefs/' . $_prefs[$pref]['type'] . '.inc'; - } - $vspace = '
'; - } - } - - /** - * Returns the value of a credential for the currently processed - * application. - * - * @see Horde_Prefs::getValue() - * - * @param string $pref A credential name. - * - * @return mixed The credential's value, either from the user's - * preferences, or from the default value, or null. - */ - public function getValue($pref) - { - if (isset($this->_credentials[$pref])) { - return $this->_credentials[$pref]; - } - $credentials = $this->getCredentials(); - - return isset($credentials[$this->app][$pref]['value']) - ? $credentials[$this->app][$pref]['value'] - : null; - } - -} diff --git a/framework/Prefs/lib/Horde/Prefs/File.php b/framework/Prefs/lib/Horde/Prefs/File.php index 34b427902..064a8bf31 100644 --- a/framework/Prefs/lib/Horde/Prefs/File.php +++ b/framework/Prefs/lib/Horde/Prefs/File.php @@ -9,7 +9,7 @@ * * @author Thomas Jarosch * @category Horde - * @package Horde_Prefs + * @package Prefs */ class Horde_Prefs_File extends Horde_Prefs { diff --git a/framework/Prefs/lib/Horde/Prefs/Identity.php b/framework/Prefs/lib/Horde/Prefs/Identity.php index 7982105ff..b40795d20 100644 --- a/framework/Prefs/lib/Horde/Prefs/Identity.php +++ b/framework/Prefs/lib/Horde/Prefs/Identity.php @@ -11,8 +11,9 @@ * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * - * @author Jan Schneider - * @package Horde_Prefs + * @author Jan Schneider + * @category Horde + * @package Prefs */ class Horde_Prefs_Identity { diff --git a/framework/Prefs/lib/Horde/Prefs/Imsp.php b/framework/Prefs/lib/Horde/Prefs/Imsp.php index 095e4ab0b..c647f69b2 100644 --- a/framework/Prefs/lib/Horde/Prefs/Imsp.php +++ b/framework/Prefs/lib/Horde/Prefs/Imsp.php @@ -7,8 +7,9 @@ * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * - * @author Michael Rubinsky - * @package Horde_Prefs + * @author Michael Rubinsky + * @category Horde + * @package Prefs */ class Horde_Prefs_Imsp extends Horde_Prefs { diff --git a/framework/Prefs/lib/Horde/Prefs/Kolab.php b/framework/Prefs/lib/Horde/Prefs/Kolab.php index 41796aa8a..0159e6384 100644 --- a/framework/Prefs/lib/Horde/Prefs/Kolab.php +++ b/framework/Prefs/lib/Horde/Prefs/Kolab.php @@ -11,7 +11,7 @@ * * @author Stuart Binge * @category Horde - * @package Horde_Prefs + * @package Prefs */ class Horde_Prefs_Kolab extends Horde_Prefs_Ldap { diff --git a/framework/Prefs/lib/Horde/Prefs/KolabImap.php b/framework/Prefs/lib/Horde/Prefs/KolabImap.php index 063550f1e..63b8343e0 100644 --- a/framework/Prefs/lib/Horde/Prefs/KolabImap.php +++ b/framework/Prefs/lib/Horde/Prefs/KolabImap.php @@ -7,8 +7,9 @@ * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * - * @author Gunnar Wrobel - * @package Horde_Prefs + * @author Gunnar Wrobel + * @category Horde + * @package Prefs */ class Horde_Prefs_KolabImap extends Horde_Prefs { diff --git a/framework/Prefs/lib/Horde/Prefs/Ldap.php b/framework/Prefs/lib/Horde/Prefs/Ldap.php index bf90c97de..d2e1658fc 100644 --- a/framework/Prefs/lib/Horde/Prefs/Ldap.php +++ b/framework/Prefs/lib/Horde/Prefs/Ldap.php @@ -49,7 +49,7 @@ * @author Jon Parise * @author Ben Klang * @category Horde - * @package Horde_Prefs + * @package Prefs */ class Horde_Prefs_Ldap extends Horde_Prefs { diff --git a/framework/Prefs/lib/Horde/Prefs/Session.php b/framework/Prefs/lib/Horde/Prefs/Session.php index 8a3bc22bd..9bc62bef4 100644 --- a/framework/Prefs/lib/Horde/Prefs/Session.php +++ b/framework/Prefs/lib/Horde/Prefs/Session.php @@ -7,8 +7,9 @@ * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. * - * @author Jon Parise - * @package Horde_Prefs + * @author Jon Parise + * @category Horde + * @package Prefs */ class Horde_Prefs_Session extends Horde_Prefs { diff --git a/framework/Prefs/lib/Horde/Prefs/Sql.php b/framework/Prefs/lib/Horde/Prefs/Sql.php index fd3a25014..967a7420e 100644 --- a/framework/Prefs/lib/Horde/Prefs/Sql.php +++ b/framework/Prefs/lib/Horde/Prefs/Sql.php @@ -46,7 +46,7 @@ * * @author Jon Parise * @category Horde - * @package Horde_Prefs + * @package Prefs */ class Horde_Prefs_Sql extends Horde_Prefs { diff --git a/framework/Prefs/lib/Horde/Prefs/Ui.php b/framework/Prefs/lib/Horde/Prefs/Ui.php deleted file mode 100644 index 2531da01f..000000000 --- a/framework/Prefs/lib/Horde/Prefs/Ui.php +++ /dev/null @@ -1,423 +0,0 @@ - - * @category Horde - * @package Horde_Prefs - */ -class Horde_Prefs_Ui -{ - /** - * Cache for groupIsEditable(). - * - * @var array - */ - static protected $_results = array(); - - /** - * Determine whether or not a preferences group is editable. - * - * @param string $group The preferences group to check. - * @param array $prefGroups TODO - * - * @return boolean Whether or not the group is editable. - */ - static public function groupIsEditable($group, $prefGroups) - { - if (!isset(self::$_results[$group])) { - if (!empty($prefGroups[$group]['url'])) { - self::$_results[$group] = true; - } else { - self::$_results[$group] = false; - if (isset($prefGroups[$group]['members'])) { - foreach ($prefGroups[$group]['members'] as $pref) { - if (!$GLOBALS['prefs']->isLocked($pref)) { - self::$_results[$group] = true; - break; - } - } - } - } - } - - return self::$_results[$group]; - } - - /** - * Handle a preferences form submission if there is one, updating - * any preferences which have been changed. - * - * @param string $group The preferences group that was edited. - * @param object $save The object where the changed values are - * saved. Must implement setValue(string, - * string). - * @param string $app The application name. - * @param array $prefGroups TODO - * @param array $_prefs TODO - * - * @return boolean Whether preferences have been updated. - */ - static public function handleForm($group, $save, $app, $prefGroups, $_prefs) - { - global $notification, $prefs, $registry; - - $updated = false; - - /* Run through the action handlers */ - if (self::groupIsEditable($group, $prefGroups)) { - foreach ($prefGroups[$group]['members'] as $pref) { - if (!$prefs->isLocked($pref) || - ($_prefs[$pref]['type'] == 'special')) { - switch ($_prefs[$pref]['type']) { - case 'implicit': - case 'link': - /* These either aren't set or are set in other - * parts of the UI. */ - break; - - case 'password': - case 'select': - case 'text': - case 'textarea': - $updated = $updated | $save->setValue($pref, Horde_Util::getPost($pref)); - break; - - case 'enum': - $val = Horde_Util::getPost($pref); - if (isset($_prefs[$pref]['enum'][$val])) { - $updated = $updated | $save->setValue($pref, $val); - } else { - $notification->push(_("An illegal value was specified."), 'horde.error'); - } - break; - - case 'multienum': - $vals = Horde_Util::getPost($pref); - $set = array(); - if (is_array($vals)) { - foreach ($vals as $val) { - if (isset($_prefs[$pref]['enum'][$val])) { - $set[] = $val; - } else { - $notification->push(_("An illegal value was specified."), 'horde.error'); - break 2; - } - } - } - - $updated = $updated | $save->setValue($pref, @serialize($set)); - break; - - case 'number': - $num = Horde_Util::getPost($pref); - if ((string)(double)$num !== $num) { - $notification->push(_("This value must be a number."), 'horde.error'); - } elseif (empty($num)) { - $notification->push(_("This number must be at least one."), 'horde.error'); - } else { - $updated = $updated | $save->setValue($pref, $num); - } - break; - - case 'checkbox': - $val = Horde_Util::getPost($pref); - $updated = $updated | $save->setValue($pref, isset($val) ? 1 : 0); - break; - - case 'alarm': - $methods = Horde_Alarm::notificationMethods(); - $value = array(); - foreach (Horde_Util::getPost($pref, array()) as $method) { - $value[$method] = array(); - if (!empty($methods[$method])) { - foreach (array_keys($methods[$method]) as $param) { - $value[$method][$param] = Horde_Util::getPost($pref . '_' . $param, ''); - if (is_array($methods[$method][$param]) && - $methods[$method][$param]['required'] && - $value[$method][$param] === '') { - $notification->push(sprintf(_("You must provide a setting for \"%s\"."), $methods[$method][$param]['desc']), 'horde.error'); - $updated = false; - break 3; - } - } - } - } - $updated = $updated | $save->setValue($pref, serialize($value)); - break; - - case 'special': - /* Code for special elements written specifically for - * each application. */ - if ($registry->hasAppMethod($app, 'prefsSpecial')) { - $updated = $updated | $registry->callAppMethod($app, 'prefsSpecial', array('args' => array($pref, $updated))); - } - break; - } - } - } - - if (is_callable(array($save, 'verify'))) { - $result = $save->verify(); - if ($result instanceof PEAR_Error) { - $notification->push($result, 'horde.error'); - $updated = false; - } - } - } - - if ($updated) { - if ($registry->hasAppMethod($app, 'prefsCallback')) { - $registry->callAppMethod($app, 'prefsCallback', array('args' => array($group))); - } - - if ($prefs instanceof Horde_Prefs_Session) { - $notification->push(_("Your options have been updated for the duration of this session."), 'horde.success'); - } else { - $notification->push(_("Your options have been updated."), 'horde.success'); - } - } - - return $updated; - } - - /** - * Generate the UI for the preferences interface, either for a - * specific group, or the group selection interface. - * - * @param string $app The application name. - * @param array $prefGroups TODO - * @param array $_prefs TODO - * @param string $group The group to generate the UI for. - * @param boolean $chunk Whether to only return the body part. - */ - static public function generateUI($app, $prefGroups, $_prefs, - $group = null, $chunk = false) - { - global $browser, $conf, $notification, $prefs, $registry; - - /* Check if any options are actually available. */ - if (is_null($prefGroups)) { - $notification->push(_("There are no options available."), 'horde.message'); - } - - /* Assign variables to hold select lists. */ - if (!$prefs->isLocked('language')) { - $GLOBALS['language_options'] = Horde_Nls::$config['languages']; - array_unshift($GLOBALS['language_options'], _("Default")); - } - - $columns = array(); - $in_group = (!empty($group) && self::groupIsEditable($group, $prefGroups) && !empty($prefGroups[$group]['members'])); - - /* We need to do this check up here because it is possible that - * we will generate a notification object, which is handled by - * generateHeader. */ - if (!$in_group && is_array($prefGroups)) { - foreach ($prefGroups as $key => $val) { - if (self::groupIsEditable($key, $prefGroups)) { - $col = $val['column']; - unset($val['column']); - $columns[$col][$key] = $val; - } - } - if (!count($columns)) { - $notification->push(_("There are no options available."), 'horde.message'); - } - } - - self::generateHeader($app, $prefGroups, $group, $chunk); - - if ($in_group) { - foreach ($prefGroups[$group]['members'] as $pref) { - if (!$prefs->isLocked($pref)) { - /* Get the help link. */ - $helplink = empty($_prefs[$pref]['help']) - ? null - : Horde_Help::link(!empty($_prefs[$pref]['shared']) ? 'horde' : $registry->getApp(), $_prefs[$pref]['help']); - - switch ($_prefs[$pref]['type']) { - case 'implicit': - break; - - case 'special': - if (!$registry->hasAppMethod($app, 'prefsSpecialGenerate') || - $registry->callAppMethod($app, 'prefsSpecialGenerate', array('args' => array($pref)))) { - require $registry->get('templates', empty($_prefs[$pref]['shared']) ? $registry->getApp() : 'horde') . '/prefs/' . $pref . '.inc'; - } - break; - - default: - require $registry->get('templates', 'horde') . '/prefs/' . $_prefs[$pref]['type'] . '.inc'; - break; - } - } - } - require $registry->get('templates', 'horde') . '/prefs/end.inc'; - } elseif (count($columns)) { - $span = round(100 / count($columns)); - require $registry->get('templates', 'horde') . '/prefs/overview.inc'; - } - } - - /** - * Generates the the full header of a preference screen including - * menu and navigation bars. - * - * @param string $app The application name. - * @param array $prefGroups TODO - * @param string $group The group to generate the header for. - * @param boolean $chunk Whether to only return the body part. - */ - static public function generateHeader($app, $prefGroups = null, - $group = null, $chunk = false) - { - global $notification, $prefs, $registry; - - $title = _("User Options"); - if ($group == 'identities' && !$prefs->isLocked('default_identity')) { - Horde::addInlineScript(array('IdentitySelect.newChoice()'), 'dom'); - } - $GLOBALS['bodyId'] = 'services_prefs'; - if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-header.inc'; - - if (empty($_SESSION['horde_prefs']['nomenu'])) { - if ($registry->hasAppMethod($app, 'prefsMenu')) { - $menu = $registry->callAppMethod($app, 'prefsMenu'); - } - require $registry->get('templates', 'horde') . '/menu/menu.inc'; - } - - $notification->notify(array('listeners' => 'status')); - } - - /* Get list of accessible applications. */ - $apps = array(); - foreach ($registry->applications as $application => $params) { - // Make sure the app is installed and has a prefs file. - if (!file_exists($registry->get('fileroot', $application) . '/config/prefs.php')) { - continue; - } - - if ($params['status'] == 'heading' || - $params['status'] == 'block') { - continue; - } - - /* Check if the current user has permisson to see this - * application, and if the application is active. - * Administrators always see all applications. */ - if ((Horde_Auth::isAdmin() && $params['status'] != 'inactive') || - ($registry->hasPermission($application) && - ($params['status'] == 'active' || $params['status'] == 'notoolbar'))) { - $apps[$application] = _($params['name']); - } - } - asort($apps); - - /* Show the current application and a form for switching - * applications. */ - require $registry->get('templates', 'horde') . '/prefs/app.inc'; - - if (is_null($prefGroups)) { - extract(Horde::loadConfiguration('prefs.php', array('prefGroups'), $app)); - } - - /* If there's only one prefGroup, just show it. */ - if (empty($group) && count($prefGroups) == 1) { - $group = array_keys($prefGroups); - $group = array_pop($group); - } - - if (!empty($group) && self::groupIsEditable($group, $prefGroups)) { - require $registry->get('templates', 'horde') . '/prefs/begin.inc'; - } - } - - /** - * Generate the content of the title bar navigation cell (previous | next - * option group). - * - * @param string $group Current option group. - */ - static public function generateNavigationCell($app, $group) - { - // Search for previous and next groups. - $first = $last = $next = $previous = null; - $finish = $found = false; - - extract(Horde::loadConfiguration('prefs.php', array('prefGroups'), $app)); - - foreach ($prefGroups as $pgroup => $gval) { - if (self::groupIsEditable($pgroup, $prefGroups)) { - if (!$first) { - $first = $pgroup; - } - if (!$found) { - if ($pgroup == $group) { - $previous = $last; - $found = true; - } - } elseif (!$finish) { - $finish = true; - $next = $pgroup; - } - $last = $pgroup; - } - } - - if (!$previous) { - $previous = $last; - } - - if (!$next) { - $next = $first; - } - - /* Don't loop if there's only one group. */ - if ($next == $previous) { - return; - } - - echo '
  • ' . - Horde::link(Horde_Util::addParameter(Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/prefs.php'), array('app' => $app, 'group' => $previous), _("Previous options"))) . - '<< ' . $prefGroups[$previous]['label'] . - ' | ' . - Horde::link(Horde_Util::addParameter(Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/prefs.php'), array('app' => $app, 'group' => $next), _("Next options"))) . - $prefGroups[$next]['label'] . ' >>' . - '
'; - } - - /** - * Get the default application to show preferences for. Defaults - * to 'horde'. - */ - static public function getDefaultApp() - { - $applications = $GLOBALS['registry']->listApps(null, true, Horde_Perms::READ); - return isset($applications['horde']) - ? 'horde' - : array_shift($applications); - } - -} diff --git a/framework/Prefs/package.xml b/framework/Prefs/package.xml index e6665cbed..c9485e7fc 100644 --- a/framework/Prefs/package.xml +++ b/framework/Prefs/package.xml @@ -24,7 +24,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> beta LGPL - * Initial Horde 4 package. + * Moved UI code to Horde_Core::. + * Initial Horde 4 package. @@ -32,7 +33,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - @@ -41,7 +41,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - @@ -85,7 +84,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - @@ -94,7 +92,6 @@ http://pear.php.net/dtd/package-2.0.xsd"> - @@ -111,8 +108,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> alpha LGPL - * Add 'nomenu' option to hide menu generation in Prefs_UI::. - * Data in postgres must be stored in a BYTEA field, not a TEXT field (Bug #8130). + * Data in postgres must be stored in a BYTEA field, not a TEXT field (Bug #8130). * Converted to package.xml 2.0 for pear.horde.org * Added files-based preferences backend (thomas.jarosch@intra2net.com, Request #6653) diff --git a/gollem/lib/Application.php b/gollem/lib/Application.php index f9d03d1c0..b58f0b34b 100644 --- a/gollem/lib/Application.php +++ b/gollem/lib/Application.php @@ -98,24 +98,21 @@ class Gollem_Application extends Horde_Registry_Application /** * Special preferences handling on update. * - * @param string $item The preference name. - * @param boolean $updated Set to true if preference was updated. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. * * @return boolean True if preference was updated. */ - public function prefsSpecial($item, $updated) + public function prefsSpecialUpdate($ui, $item) { switch ($item) { case 'columnselect': - $columns = Horde_Util::getFormData('columns'); - if (!empty($columns)) { - $GLOBALS['prefs']->setValue('columns', $columns); + if (isset($ui->vars->columns)) { + $GLOBALS['prefs']->setValue('columns', $ui->vars->columns); return true; } break; } - - return $updated; } /** diff --git a/horde/config/hooks.php.dist b/horde/config/hooks.php.dist index 952feab1e..ac3f0d2c7 100644 --- a/horde/config/hooks.php.dist +++ b/horde/config/hooks.php.dist @@ -30,7 +30,9 @@ * * Setting value * ------------- - * If 'hook' => true in a preference attribute, a hook named + * If + * 'hook' => true + * exists for a preference (config/prefs.php), a hook named * prefs_hook_ will be run on login. It receives the username as * the only parameter and the return value from the function will be used as * the preference value. @@ -188,7 +190,7 @@ class Horde_Hooks // // Example preferences change hook. // function prefs_change_hook_theme() // { -// $GLOBALS['notification']->push('You changed your theme to ' . $GLOBALS['prefs']->getValue('theme') . '!'); +// $GLOBALS['notification']->push('You changed your theme to ' . $GLOBALS['prefs']->getValue('theme') . '.'); // } diff --git a/horde/config/prefs.php.dist b/horde/config/prefs.php.dist index a1ce5d4ba..ace84085d 100644 --- a/horde/config/prefs.php.dist +++ b/horde/config/prefs.php.dist @@ -6,211 +6,231 @@ * user logs out and logs in again. * * If you change these preferences in a production system, you will - * need to delete any horde_prefs in your preferences database. - * - * prefGroups array - * ---------------- - * $prefGroups are for display purposes when you press the options button. - * The options choice will appear when you set your preferences driver - * in the horde/config/conf.php file. - * - * $prefGroups array definition: - * column: What column head this group will go under - * label: Label for the group of settings - * desc: Description that will show under label - * members: List of preferences supported by this group - * - * _prefs array - * ------------ - * The $_prefs array's are listed in the same order as listed in the - * members element of $prefGroups. - * - * value: This entry will hold the default preference value depending on the - * preference type: - * checkbox: 0 or false for unchecked, 1 or true for checked - * enum: Preselected item from associated enumeration - * implicit: See Preference type - * link: Not used - * number: Number value - * password: Should be '' - * select: Preselected item from associated selection list - * special: Not used - * text: Text value - * textarea: Text value, lines separated with "\n" - * - * locked: Allow preference to be changed from UI - * true: Do not show this preference in the UI. - * This has no effect on 'link' type preferences. - * false: Show this preference in the UI and allow changing. - * - * shared: Share with other horde apps - * true: Share this pref with other Horde apps - * false: Keep this pref local to the current app - * - * type: Preference type - * checkbox: Provides a checkbox. - * enum: Provides a selection list in the UI, list is - * specified in the associated 'enum' setting. - * implicit: Provides storage for 'special' types. - * link: Provides a link to another data entry form. - * number: Provides a 3-character textbox to enter a natural - * number; syntaxcheck is performed after data entry. - * password: Provides a textbox for password entry. - * select: Provides a selection list in the UI that is built in - * lib/Application.php - * special: Provides an UI widget. - * text: Provides a single-line textbox. - * textarea: Provides a multi-line textbox. - * - * enum: Static list of elements for 'type' => 'enum'. - * - * escaped: For an enum or a select, are the keys and values already - * html-escaped? Defaults to false if not present. - * - * hook: Call a hook function for the value of this preference - * true: Will call the function prefs_hook_ - * to fill in the value of this preference. - * See hooks.php for more details. - * false: Normal behaviour - no hook is called. + * need to delete these preference entries in your backend; entries in the + * backend have priority over the default entry. + * + * $prefGroups + * =========== + * $prefGroups defines the options page in which a preference value will + * appear in. + * + * Format: + * ------- + * column - (string) Which column head this group will go under. + * desc - (string) Description shown under label. + * label - (string) Label for the group of settings. + * members - (array) List of displayable preferences contained in this group. + * + * $_prefs + * ======= + * $_prefs defines the preferences used within an application. Each + * preference is contained within a separate array entry, with the key being + * the name of the preference. + * + * The following are OPTIONAL values for each entry: + * + * locked - (boolean) Allow preference to be changed from the options screen? + * VALUES: + * true: Do not show this preference in the UI and don't allow + * changing by any mechanism. + * false: Show this preference in the UI and allow changing. + * DEFAULT: false + * + * shared - (boolean) Share with other Horde apps? + * VALUES: + * true: Share this pref with other Horde apps. + * false: Keep this pref local to the current app. + * DEFAULT: false + * + * help - (string) The help file identifier for this preference. + * VALUES: + * If present, a help icon will be displayed next to the preference. + * Clicking on this icon will open the entry in the help viewer in + * a popup window. + * DEFAULT: No help icon is displayed + * + * The UI display for a preference is controlled by the 'type' key. This key + * controls how the preference is displayed on the options screen. If this + * key is not present, the preference is treated as type 'implict'. The + * following is the list of types, with a description of further keys used + * for each type. + * + * 'alarm' + * ------- + * TODO + * + * 'checkbox' + * ---------- + * Provides a checkbox (yes/no) entry. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'value' - (integer) 0 (or false) for unchecked, 1 (or true) for checked. + * DEFAULT: 0 + * + * 'enum' + * ------ + * Provides an enumeration (a/k/a selection) list in the UI. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'escaped' - (boolean) If true, values in 'enum' are already escaped. + * DEFAULT: false + * 'enum' - (array) The enumeration list. Keys will be used as the + * prefernce value; values are the text that will be displayed in + * the selection list. + * 'value' - (mixed) The value of the preference. Will be used to + * auto-select the entry in the selection list. + * + * 'implicit' + * ---------- + * Preference used in an application but never directly shown to the viewer + * via the preferences screen. + * + * ADDITIONAL KEYS: + * 'value' - (mixed) The value of the preference. Will be used to + * auto-select the entry in the selection list. + * + * 'link' + * ------ + * Provides a clickable link. + * + * This pref is a UI placeholder only and will not be stored in the preference + * backend. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The link text. + * 'img' - (string) An image file to display before the link. + * DEFAULT: no image displayed + * 'url' - (string) The URL to link to (unescaped). Only specify one of + * 'url' or 'xurl'. + * 'xurl' - (string) The URL to link to (escaped). Only specify one of 'url' + * or 'xurl'. + * + * 'multienum' + * ----------- + * Provides an enumeration list in the UI that allows for multiple entries + * to be selected. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'escaped' - (boolean) If true, values in 'enum' are already escaped. + * DEFAULT: false + * 'enum' - (array) The enumeration list. Keys will be used as the + * prefernce value; values are the text that will be displayed in + * the selection list. + * 'value' - (string) A serialized value containing the key(s) selected. All + * keys will be auto-selected in the selection area. + * + * 'number' + * -------- + * Provides a small textbox to enter a natural number. Values entered for this + * preference are automatically converted to a number value. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'value' - (number) The preference value. + * + * 'password' + * ---------- + * Provides a textbox for password entry (input characters will not be + * displayed to the screen). + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'value' - (string) The preference value. + * + * 'prefslink' + * ----------- + * Create a link to another preferences page. + * + * This pref is a UI placeholder only and will not be stored in the preference + * backend. + * + * ADDITIONAL KEYS: + * 'app' - (string) The application to link to. + * DEFAULT: current application. + * 'desc' - (string) The link text. + * 'group' - (string) The preferences group to link to. + * 'img' - (string) An image file to display before the link. + * DEFAULT: no image displayed + * + * 'rawhtml' + * --------- + * Outputs the raw HTML string to the page. + * + * This pref is a UI placeholder only and will not be stored in the preference + * backend. + * + * ADDITIONAL KEYS: + * 'value' - (string) The raw (already escaped) HTML to output to the page. + * + * 'special' + * --------- + * Used as placeholder to indicate that the application will provide both the + * UI display code and the subsequent preferences storage. + * + * This pref is a UI placeholder only and will not be stored in the preference + * backend. + * + * 'text' + * ------ + * Provides a single-line textbox. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'value' - (string) The preference value. + * + * 'textarea' + * ---------- + * Provides a multi-line textbox. + * + * ADDITIONAL KEYS: + * 'desc' - (string) The description text to use on the options page. + * 'value' - (string) The preference value. Lines should be separated + * with the "\n" character. * * $Id$ */ +// *** Personal Information preferences *** + $prefGroups['identities'] = array( 'column' => _("Your Information"), 'label' => _("Personal Information"), 'desc' => _("Change the name and address that people see when they read and reply to your emails."), - 'members' => array('default_identity', 'identityselect', 'deleteidentity', - 'id', 'fullname', 'from_addr') -); - -$prefGroups['authentication'] = array( - 'column' => _("Your Information"), - 'label' => _("Authentication Credentials"), - 'desc' => _("Set authentication credentials like user names and passwords for external servers."), - 'members' => array('credentialsui'), -); - -try { - $auth = Horde_Auth::singleton($GLOBALS['conf']['auth']['driver']); - if ($auth->hasCapability('update')) { - $prefGroups['forgotpass'] = array( - 'column' => _("Your Information"), - 'label' => _("Account Password"), - 'desc' => _("Set options to allow you to reset your password if you ever forget it."), - 'members' => array('security_question', 'security_answer', 'alternate_email') - ); - } -} catch (Horde_Exception $e) {} - -$prefGroups['language'] = array( - 'column' => _("Your Information"), - 'label' => _("Locale and Time"), - 'desc' => _("Set your preferred language, timezone and date options."), - 'members' => array('language', 'timezone', 'twentyFour', 'date_format', 'first_week_day') -); - -$prefGroups['categories'] = array( - 'column' => _("Your Information"), - 'label' => _("Categories and Labels"), - 'desc' => _("Manage the list of categories you have to label items with, and colors associated with those categories."), - 'members' => array('categorymanagement') -); - -$prefGroups['display'] = array( - 'column' => _("Other Information"), - 'label' => _("Display Options"), - 'desc' => _("Set your startup application, color scheme, page refreshing, and other display options."), - 'members' => array('initial_application', 'show_last_login', 'theme', - 'summary_refresh_time', 'show_sidebar', 'sidebar_width', - 'moz_sidebar', 'menu_view', 'menu_refresh_time', - 'widget_accesskey') -); - -$prefGroups['remote'] = array( - 'column' => _("Other Information"), - 'label' => _("Remote Servers"), - 'desc' => _("Set up remote servers that you want to access from your portal."), - 'url' => 'services/portal/rpcsum.php' -); - -if (!empty($GLOBALS['conf']['facebook']['key']) && !empty($GLOBALS['conf']['facebook']['secret'])) { - $prefGroups['facebook'] = array( - 'column' => _("Other Information"), - 'label' => _("Facebook Integration"), - 'desc' => _("Set up integration with your Facebook account."), - 'url' => 'services/facebook.php' - ); -} - -if (!empty($GLOBALS['conf']['twitter']['key']) && !empty($GLOBALS['conf']['twitter']['secret'])) { - $prefGroups['twitter'] = array( - 'column' => _("Other Information"), - 'label' => _("Twitter Integration"), - 'desc' => _("Set up integration with your Twitter account."), - 'url' => 'services/twitter.php' - ); -} - - -// For alternate IMSP authentication. -if (!empty($GLOBALS['conf']['imsp']['enabled'])) { - $prefGroups['imspauth'] = array( - 'column' => _("Other Information"), - 'label' => _("Alternate IMSP Login"), - 'desc' => _("Use if name/password is different for IMSP server."), - 'members' => array('imsp_auth_user', 'imsp_auth_pass') - ); -} - -$prefGroups['syncml'] = array( - 'column' => _("Other Information"), - 'label' => _("SyncML"), - 'desc' => _("Configuration for syncing with PDAs, Smartphones and Outlook."), - 'url' => 'services/portal/syncml.php', - 'members' => array() + 'members' => array( + 'default_identity', 'identityselect', 'id', 'fullname', 'from_addr' + ) ); -// Personal Information preferences - // default identity // Set locked to true if you don't want the users to have multiple identities. $_prefs['default_identity'] = array( 'value' => 0, - 'locked' => false, 'shared' => true, 'type' => 'enum', - 'enum' => (isset($GLOBALS['identity']) && is_object($GLOBALS['identity'])) ? $GLOBALS['identity']->getAll('id') : array(), - 'desc' => _("Your default identity:"), + 'desc' => _("Your default identity:") ); -// identities array -// Don't change anything here. +// identities data $_prefs['identities'] = array( + // value = serialize(array()) 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit', + 'shared' => true ); // identify email confirmation $_prefs['confirm_email'] = array( + // value = serialize(array()) 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit', + 'shared' => true ); // identity selection widget $_prefs['identityselect'] = array( - 'shared' => true, - 'type' => 'special', -); - -// delete button -$_prefs['deleteidentity'] = array( 'type' => 'special', - 'shared' => true, + 'shared' => true ); // identity name @@ -218,7 +238,6 @@ $_prefs['deleteidentity'] = array( // horde/config/hooks.php. $_prefs['id'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'text', 'desc' => _("Identity's name:") @@ -229,7 +248,6 @@ $_prefs['id'] = array( // horde/config/hooks.php. $_prefs['fullname'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'text', 'desc' => _("Your full name:") @@ -240,32 +258,27 @@ $_prefs['fullname'] = array( // horde/config/hooks.php. $_prefs['from_addr'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'text', 'desc' => _("Your From: address:") ); -// Authentication Options -// credentials -$_prefs['credentials'] = array( - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit' -); -// credentials interface -$_prefs['credentialsui'] = array( - 'shared' => true, - 'type' => 'special', +// *** Authentication Preferences *** + +$prefGroups['forgotpass'] = array( + 'column' => _("Your Information"), + 'label' => _("Account Password"), + 'desc' => _("Set options to allow you to reset your password if you ever forget it."), + 'members' => array( + 'security_question', 'security_answer', 'alternate_email' + ) ); // user security question $_prefs['security_question'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'text', 'desc' => _("Enter a security question which you will be asked if you need to reset your password, e.g. 'what is the name of your pet?':") @@ -274,7 +287,6 @@ $_prefs['security_question'] = array( // user security answer $_prefs['security_answer'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'text', 'desc' => _("Insert the required answer to the security question:") @@ -283,35 +295,46 @@ $_prefs['security_answer'] = array( // user alternate email $_prefs['alternate_email'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'text', 'desc' => _("Insert an email address to which you can receive the new password:") ); + + +// *** Locale/Time Preferences *** + +$prefGroups['language'] = array( + 'column' => _("Your Information"), + 'label' => _("Locale and Time"), + 'desc' => _("Set your preferred language, timezone and date options."), + 'members' => array( + 'language', 'timezone', 'twentyFour', 'date_format', 'first_week_day' + ) +); + // user language +// Language list is dynamically built when prefs screen is displayed $_prefs['language'] = array( 'value' => '', - 'locked' => false, 'shared' => true, - 'type' => 'select', + 'type' => 'enum', 'escaped' => true, 'desc' => _("Select your preferred language:") ); // user time zone +// Timezone list is dynamically built when prefs screen is displayed $_prefs['timezone'] = array( 'value' => '', - 'locked' => false, 'shared' => true, - 'type' => 'select', + 'type' => 'enum', 'desc' => _("Your current time zone:") ); // time format $_prefs['twentyFour'] = array( 'value' => false, - 'locked' => false, 'shared' => true, 'type' => 'checkbox', 'desc' => _("Display 24-hour times?") @@ -320,7 +343,6 @@ $_prefs['twentyFour'] = array( // date format $_prefs['date_format'] = array( 'value' => '%x', - 'locked' => false, 'shared' => true, 'type' => 'enum', 'enum' => array( @@ -353,61 +375,109 @@ $_prefs['date_format'] = array( // what day should be displayed as the first day of the week? $_prefs['first_week_day'] = array( 'value' => '0', - 'locked' => false, 'shared' => true, 'type' => 'enum', 'desc' => _("Which day would you like to be displayed as the first day of the week?"), - 'enum' => array('0' => _("Sunday"), - '1' => _("Monday")) + 'enum' => array( + '0' => _("Sunday"), + '1' => _("Monday") + ) ); -// UI theme -$_prefs['theme'] = array( - 'value' => 'silver', - 'locked' => false, - 'shared' => true, - 'type' => 'select', - 'desc' => _("Select your color scheme.") + + +// *** Categories/Labels Preferences *** + +$prefGroups['categories'] = array( + 'column' => _("Your Information"), + 'label' => _("Categories and Labels"), + 'desc' => _("Manage the list of categories you have to label items with, and colors associated with those categories."), + 'members' => array('categorymanagement') +); + +// UI for category management. +$_prefs['categorymanagement'] = array( + 'type' => 'special' ); // categories $_prefs['categories'] = array( 'value' => '', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit' + 'shared' => true ); // category colors $_prefs['category_colors'] = array( 'value' => '', - 'locked' => false, + 'shared' => true +); + + + +// *** Display Options Preferences *** + +$prefGroups['display'] = array( + 'column' => _("Other Information"), + 'label' => _("Display Options"), + 'desc' => _("Set your startup application, color scheme, page refreshing, and other display options."), + 'members' => array( + 'initial_application', 'show_last_login', 'theme', + 'summary_refresh_time', 'show_sidebar', 'sidebar_width', + 'moz_sidebar', 'menu_view', 'menu_refresh_time', 'widget_accesskey' + ) +); + +// what application should we go to after login? +// Application list is dynamically built when prefs screen is displayed +$_prefs['initial_application'] = array( + 'value' => 'horde', 'shared' => true, - 'type' => 'implicit' + 'type' => 'enum', + 'desc' => sprintf(_("What application should %s display after login?"), $GLOBALS['registry']->get('name')) ); -// UI for category management. -$_prefs['categorymanagement'] = array( - 'type' => 'special' +// show the last login time of user +$_prefs['show_last_login'] = array( + 'value' => true, + 'shared' => true, + 'type' => 'checkbox', + 'desc' => _("Show last login time when logging in?") +); + +// last login time of user +// value is a serialized array of the UNIX timestamp of the last +// login, and the host that the last login was from. +$_prefs['last_login'] = array( + // value = serialize(array()) + 'value' => 'a:0:{}', + 'shared' => true +); + +// UI theme +// Theme list is dynamically built when prefs screen is displayed +$_prefs['theme'] = array( + 'value' => 'silver', + 'shared' => true, + 'type' => 'enum', + 'desc' => _("Select your color scheme.") ); $_prefs['summary_refresh_time'] = array( 'value' => 300, - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array(0 => _("Never"), - 30 => _("Every 30 seconds"), - 60 => _("Every minute"), - 300 => _("Every 5 minutes"), - 900 => _("Every 15 minutes"), - 1800 => _("Every half hour")), + 'enum' => array( + 0 => _("Never"), + 30 => _("Every 30 seconds"), + 60 => _("Every minute"), + 300 => _("Every 5 minutes"), + 900 => _("Every 15 minutes"), + 1800 => _("Every half hour") + ), 'desc' => _("Refresh Portal View:") ); $_prefs['show_sidebar'] = array( 'value' => true, - 'locked' => false, 'shared' => true, 'type' => 'checkbox', 'desc' => sprintf(_("Show the %s Menu on the left?"), $GLOBALS['registry']->get('name', 'horde')) @@ -415,8 +485,6 @@ $_prefs['show_sidebar'] = array( $_prefs['sidebar_width'] = array( 'value' => 150, - 'locked' => false, - 'shared' => false, 'type' => 'number', 'desc' => sprintf(_("Width of the %s menu on the left:"), $GLOBALS['registry']->get('name', 'horde')) ); @@ -433,42 +501,33 @@ $_prefs['moz_sidebar'] = array( $_prefs['menu_view'] = array( 'value' => 'both', - 'locked' => false, 'shared' => true, 'type' => 'enum', - 'enum' => array('text' => _("Text Only"), - 'icon' => _("Icons Only"), - 'both' => _("Icons with text")), + 'enum' => array( + 'text' => _("Text Only"), + 'icon' => _("Icons Only"), + 'both' => _("Icons with text") + ), 'desc' => _("Menu mode:") ); $_prefs['menu_refresh_time'] = array( 'value' => 300, - 'locked' => false, 'shared' => true, 'type' => 'enum', - 'enum' => array(0 => _("Never"), - 30 => _("Every 30 seconds"), - 60 => _("Every minute"), - 120 => _("Every 2 minutes"), - 300 => _("Every 5 minutes")), + 'enum' => array( + 0 => _("Never"), + 30 => _("Every 30 seconds"), + 60 => _("Every minute"), + 120 => _("Every 2 minutes"), + 300 => _("Every 5 minutes") + ), 'desc' => _("Refresh Dynamic Menu Elements:") ); - -// what application should we go to after login? -$_prefs['initial_application'] = array( - 'value' => 'horde', - 'locked' => false, - 'shared' => true, - 'type' => 'select', - 'desc' => sprintf(_("What application should %s display after login?"), $GLOBALS['registry']->get('name')) -); - // should we create access keys? $_prefs['widget_accesskey'] = array( 'value' => true, - 'locked' => false, 'shared' => true, 'type' => 'checkbox', 'desc' => _("Should access keys be defined for most links?") @@ -476,75 +535,114 @@ $_prefs['widget_accesskey'] = array( // the layout of the portal page. $_prefs['portal_layout'] = array( - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + // value = serialize(array()) + 'value' => 'a:0:{}' +); + +// *** Remote Servers Preferences *** + +$prefGroups['remote'] = array( + 'column' => _("Other Information"), + 'label' => _("Remote Servers"), + 'desc' => _("Set up remote servers that you want to access from your portal."), + 'members' => array('remotemanagement') +); + +$_prefs['remotemanagement'] = array( + 'type' => 'special' ); // the remote servers. $_prefs['remote_summaries'] = array( - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + // value = serialize(array()) + 'value' => 'a:0:{}' +); + + + +// *** Facebook Integration Preferences *** + +$prefGroups['facebook'] = array( + 'column' => _("Other Information"), + 'label' => _("Facebook Integration"), + 'desc' => _("Set up integration with your Facebook account."), + 'members' => array('facebookmanagement') +); + +$_prefs['facebookmanagement'] = array( + 'type' => 'special' ); $_prefs['facebook'] = array( + // value = serialize(array()) 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit' + 'shared' => true +); + + + +// *** Twitter Intergration Preferences *** + +$prefGroups['twitter'] = array( + 'column' => _("Other Information"), + 'label' => _("Twitter Integration"), + 'desc' => _("Set up integration with your Twitter account."), + 'members' => array('twittermanagement') +); + +$_prefs['twittermanagement'] = array( + 'type' => 'special' ); $_prefs['twitter'] = array( - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + // value = serialize(array()) + 'value' => 'a:0:{}' ); -// last login time of user -// value is a serialized array of the UNIX timestamp of the last -// login, and the host that the last login was from. -$_prefs['last_login'] = array( - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit' + + +// *** IMSP Intergration Preferences *** + +$prefGroups['imspauth'] = array( + 'column' => _("Other Information"), + 'label' => _("Alternate IMSP Login"), + 'desc' => _("Use if name/password is different for IMSP server."), + 'members' => array('imsp_auth_user', 'imsp_auth_pass') ); -// show the last login time of user -$_prefs['show_last_login'] = array( - 'value' => true, - 'locked' => false, - 'shared' => true, - 'type' => 'checkbox', - 'desc' => _("Show last login time when logging in?") +$_prefs['imsp_auth_user'] = array( + 'value' => '', + 'type' => 'text', + 'desc' => _("Alternate IMSP Username") +); + +$_prefs['imsp_auth_pass'] = array( + 'value' => '', + 'type' => 'password', + 'desc' => _("Alternate IMSP Password") ); -if (!empty($GLOBALS['conf']['imsp']['enabled'])) { - $_prefs['imsp_auth_user'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'text', - 'desc' => _("Alternate IMSP Username") - ); - - $_prefs['imsp_auth_pass'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'password', - 'desc' => _("Alternate IMSP Password") - ); -} + + +// *** SyncML Preferences *** +$prefGroups['syncml'] = array( + 'column' => _("Other Information"), + 'label' => _("SyncML"), + 'desc' => _("Configuration for syncing with PDAs, Smartphones and Outlook."), + 'members' => array('syncmlmanagement') +); + +$_prefs['syncmlmanagement'] = array( + 'type' => 'special' +); + + + +// *** Internal Preferences *** // last time login tasks were run. $_prefs['last_logintasks'] = array( + // value = serialize(array()) 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit' + 'shared' => true ); diff --git a/horde/js/addressbooksprefs.js b/horde/js/addressbooksprefs.js new file mode 100644 index 000000000..675032a59 --- /dev/null +++ b/horde/js/addressbooksprefs.js @@ -0,0 +1,88 @@ +/** + * Provides the javascript for managing addressbooks. + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +var HordeAddressbooksPrefs = { + + // Variables set by other code: fields + + updateSearchFields: function() + { + var sv = this._getSelectedValue(false), + sf = $('search_fields'); + + sf.update(''); + this.fields.each(function(f) { + if (f[0] == sv) { + f.slice(1).each(function(o) { + var tmp = new Option(o[1], o[0]); + if (o[2]) { + tmp.selected = true; + } + sf.insert(tmp); + }); + } + }); + + this.changeSearchFields(); + }, + + _getSelectedValue: function(index) + { + var ss = $('selected_sources'); + if (ss) { + if (index) { + return ss.selectedIndex; + } + if (ss.selectedIndex >= 0) { + return ss.options[ss.selectedIndex].value; + } + return ''; + } else { + return index ? 0 : this.fields[0][0]; + } + }, + + changeSearchFields: function() + { + var data = [], + i = 0, + sf = $('search_fields'), + sv = this._getSelectedValue(true); + + $A(sf.options).each(function(o) { + this.fields[sv][i][2] = o.selected; + ++i; + }.bind(this)); + + this.fields.each(function(f) { + var tmp = [ f[0] ]; + f.slice(1).each(function(o) { + if (o[2]) { + tmp.push(o[0]); + } + }); + data.push(tmp.join("\t")); + }); + $('search_fields_string').setValue(data.join("\n")); + }, + + onDomLoad: function() + { + this.updateSearchFields(); + + if ($('search_fields')) { + $('search_fields').observe('change', this.changeSearchFields.bind(this)); + } + + if ($('selected_sources')) { + $('selected_sources').observe('change', this.updateSearchFields.bind(this)); + } + } + +}; + +document.observe('dom:loaded', HordeAddressbooksPrefs.onDomLoad.bind(HordeAddressbooksPrefs)); diff --git a/horde/js/alarmprefs.js b/horde/js/alarmprefs.js new file mode 100644 index 000000000..c226b90fd --- /dev/null +++ b/horde/js/alarmprefs.js @@ -0,0 +1,34 @@ +/** + * Provides the javascript for managing alarms. + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +var HordeAlarmPrefs = { + + // Variables defaulting to null: pref + + updateParams: function() + { + [ 'notify', 'mail', 'sms' ].each(function(method) { + var p = $(method + 'Params'); + if (p) { + if ($(this.pref).getValue().include(method)) { + p.show(); + } else { + p.hide(); + } + } + }, this); + }, + + onDomLoad: function() + { + $(this.pref).observe('change', this.updateParams.bind(this)); + this.updateParams(); + } + +}; + +document.observe('dom:load', HordeAlarmPrefs.onDomLoad.bind(HordeAlarmPrefs)); diff --git a/horde/js/categoryprefs.js b/horde/js/categoryprefs.js new file mode 100644 index 000000000..2390b89e4 --- /dev/null +++ b/horde/js/categoryprefs.js @@ -0,0 +1,67 @@ +/** + * Provides the javascript for managing categories. + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +var HordeCategoryPrefs = { + + // Variables defaulting to null: category_text + + removeCategory: function(e) + { + var p = $('prefs'); + $(p.cAction).setValue('remove'); + $(p.category).setValue(e.element().readAttribute('category')); + p.submit(); + }, + + addCategory: function() + { + var category = window.prompt(this.category_text, ''), p; + if (!category.empty()) { + p = $('prefs'); + $(p.cAction).setValue('add'); + $(p.category).setValue(category); + p.submit(); + } + }, + + resetBackgrounds: function() + { + $('prefs').getInputs('text').each(function(i) { + if (i.readAttribute('id').startsWith('color_')) { + i.setStyle({ backgroundColor: $F(i) }); + } + }); + }, + + colorPicker: function(e) + { + var elt = e.element(), + input = e.element().previous(); + + new ColorPicker({ + color: $F(input), + offsetParent: elt, + update: [ [ input, 'value' ], [ input, 'background' ] ] + }); + + e.stop(); + }, + + onDomLoad: function() + { + $('prefs').observe('reset', function() { + this.resetBackgrounds.defer() + }.bind(this)); + $('add_category').observe('click', this.addCategory.bind(this)); + + $$('.categoryColorPicker').invoke('observe', 'click', this.colorPicker.bindAsEventListener(this)); + $$('.categoryDelete').invoke('observe', 'click', this.removeCategory.bindAsEventListener(this)); + } + +}; + +document.observe('dom:loaded', HordeCategoryPrefs.onDomLoad.bind(HordeCategoryPrefs)); diff --git a/horde/js/rpcprefs.js b/horde/js/rpcprefs.js new file mode 100644 index 000000000..fcf1d8f73 --- /dev/null +++ b/horde/js/rpcprefs.js @@ -0,0 +1,50 @@ +/** + * Provides the javascript for managing remote servers. + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + */ + +var HordeRpcPrefs = { + + // Variables defaulting to null: servers + + serverChoice: function(idx) + { + switch (idx) { + case '-1': + $('rpc_create').show(); + $('rpc_change', 'rpc_delete').invoke('hide'); + $('url', 'user', 'passwd').invoke('setValue', ''); + break; + + default: + $('rpc_create').hide(); + $('rpc_change', 'rpc_delete').invoke('show'); + $('url').setValue(this.servers[idx][0]); + $('user').setValue(this.servers[idx][1]); + $('passwd').setValue(''); + break; + } + }, + + onDomLoad: function() + { + $('server').observe('change', function() { + this.serverChoice($('server').selectedIndex); + }.bind(this)); + $('rpc_reset').observe('click', function(e) { + this.serverChoice('-1'); + e.stop(); + }.bindAsEventListener(this)); + + if (!this.servers.size()) { + $('server').up().hide(); + } + + this.serverChoice('-1'); + } + +}; + +document.observe('dom:loaded', HordeRpcPrefs.onDomLoad.bind(HordeRpcPrefs)); diff --git a/horde/js/sourceselect.js b/horde/js/sourceselect.js new file mode 100644 index 000000000..0af423f53 --- /dev/null +++ b/horde/js/sourceselect.js @@ -0,0 +1,80 @@ +/** + * Provides the javascript for managing the source selection widget. + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + */ + +var HordeSourceSelectPrefs = { + + resetHidden: function() + { + $('sources').setValue($F('selected_sources').toJSON()); + }, + + moveAction: function(from, to) + { + $(from).childElements().each(function(c) { + if (c.selected) { + c.remove(); + $(to).insert(c); + } + }); + + this.resetHidden(); + }, + + moveSource: function(e, mode) + { + var sa = $('selected_sources'), sel, tmp; + + if (sa.selectedIndex < 1 || sa.length < 3) { + return; + } + + // Deselect everything but the first selected item + sa.childElements().each(function(s) { + if (sel) { + s.selected = false; + } else if (s.selected) { + sel = s; + } + }); + + switch (mode) { + case 'down': + tmp = sel.next(); + if (tmp) { + sel.remove(); + tmp.insert({ after: sel }); + } + break; + + case 'up': + tmp = sel.previous(); + if (tmp && tmp.value) { + sel.remove(); + tmp.insert({ before: sel }); + } + break; + } + + this.resetHidden(); + e.stop(); + }, + + onDomLoad: function() + { + this.resetHidden(); + + if ($('unselected_sources')) { + $('addsource').observe('click', this.moveAction.bind(this, 'unselected_sources', 'selected_sources')); + $('removesource').observe('click', this.moveAction.bind(this, 'selected_sources', 'unselected_sources')); + $('moveup').observe('click', this.moveSource.bindAsEventListener(this, 'up')); + $('movedown').observe('click', this.moveSource.bindAsEventListener(this, 'down')); + } + } + +}; + +document.observe('dom:loaded', HordeSourceSelectPrefs.onDomLoad.bind(HordeSourceSelectPrefs)); diff --git a/horde/lib/Application.php b/horde/lib/Application.php index 9e113f530..d482d168a 100644 --- a/horde/lib/Application.php +++ b/horde/lib/Application.php @@ -43,191 +43,49 @@ class Horde_Application extends Horde_Registry_Application } /** - * Code to run when viewing prefs for this application. + * Code to run on init when viewing prefs for this application. * - * @param string $group The prefGroup name. + * @param Horde_Core_Prefs_Ui $ui The UI object. */ - public function prefsInit($group) + public function prefsInit($ui) { - $out = array(); - - /* Assign variables for select lists. */ - if (!$GLOBALS['prefs']->isLocked('timezone')) { - $out['timezone_options'] = Horde_Nls::getTimezones(); - array_unshift($out['timezone_options'], _("Default")); - } - - if (!$GLOBALS['prefs']->isLocked('initial_application')) { - $out['initial_application_options'] = array(); - $apps = $GLOBALS['registry']->listApps(array('active')); - foreach ($apps as $a) { - $perms = $GLOBALS['injector']->getInstance('Horde_Perms'); - if (file_exists($GLOBALS['registry']->get('fileroot', $a)) && - (($perms->exists($a) && ($perms->hasPermission($a, Horde_Auth::getAuth(), Horde_Perms::READ) || Horde_Auth::isAdmin())) || - !$perms->exists($a))) { - $out['initial_application_options'][$a] = $GLOBALS['registry']->get('name', $a); - } - } - asort($out['initial_application_options']); - } - - if (!$GLOBALS['prefs']->isLocked('theme')) { - $out['theme_options'] = array(); - $theme_base = $GLOBALS['registry']->get('themesfs', 'horde'); - $dh = @opendir($theme_base); - if (!$dh) { - $GLOBALS['notification']->push("Theme directory can't be opened", 'horde.error'); - } else { - while (($dir = readdir($dh)) !== false) { - if ($dir == '.' || $dir == '..') { - continue; - } - - $theme_name = null; - @include $theme_base . '/' . $dir . '/info.php'; - if (!empty($theme_name)) { - $out['theme_options'][$dir] = $theme_name; - } - } - } - - asort($out['theme_options']); - } + $GLOBALS['injector']->getInstance('Horde_Prefs_Ui')->prefsInit($ui); + } - return $out; + /** + * Generate code used to display a special preference. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return string The HTML code to display on the options page. + */ + public function prefsSpecial($ui, $item) + { + return $GLOBALS['injector']->getInstance('Horde_Prefs_Ui')->prefsSpecial($ui, $item); } /** * Special preferences handling on update. * - * @param string $item The preference name. - * @param boolean $updated Set to true if preference was updated. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. * * @return boolean True if preference was updated. */ - public function prefsHandle($item, $updated) + public function prefsSpecialUpdate($ui, $item) { - switch ($item) { - case 'showsummaryselect': - $show_summaries = Horde_Util::getFormData('show_summaries'); - if (!is_null($show_summaries)) { - $GLOBALS['prefs']->setValue('show_summaries', $show_summaries); - return true; - } - break; - - case 'themeselect': - $theme = Horde_Util::getFormData('theme'); - if (!is_null($theme)) { - $GLOBALS['prefs']->setValue('theme', $theme); - return true; - } - break; - - case 'categorymanagement': - $cManager = new Horde_Prefs_CategoryManager(); - - /* Always save colors of all categories. */ - $colors = array(); - $categories = $cManager->get(); - foreach ($categories as $category) { - if ($color = Horde_Util::getFormData('color_' . md5($category))) { - $colors[$category] = $color; - } - } - if ($color = Horde_Util::getFormData('color_' . md5('_default_'))) { - $colors['_default_'] = $color; - } - if ($color = Horde_Util::getFormData('color_' . md5('_unfiled_'))) { - $colors['_unfiled_'] = $color; - } - $cManager->setColors($colors); - - $action = Horde_Util::getFormData('cAction'); - $category = Horde_Util::getFormData('category'); - - switch ($action) { - case 'add': - $cManager->add($category); - break; - - case 'remove': - $cManager->remove($category); - break; - - default: - /* Save button. */ - $updated = true; - Horde::addInlineScript( - 'if (window.opener && window.name) window.close();', 'javascript' - ); - } - break; - - case 'credentialsui': - $credentials = Horde_Util::getFormData('credentials'); - if (!is_null($credentials)) { - $GLOBALS['prefs']->setValue('credentials', serialize($credentials)); - return true; - } - break; - } - - return $updated; + return $GLOBALS['injector']->getInstance('Horde_Prefs_Ui')->prefsSpecialUpdate($ui, $item); } /** - * Do anything that we need to do as a result of certain preferences - * changing. + * Called when preferences are changed. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. */ - public function prefsCallback() + public function prefsCallback($ui) { - $need_reload = false; - $old_sidebar = $GLOBALS['prefs']->getValue('show_sidebar'); - - if ($GLOBALS['prefs']->isDirty('language')) { - if ($GLOBALS['prefs']->isDirty('language')) { - Horde_Nls::setLanguageEnvironment($GLOBALS['prefs']->getValue('language')); - foreach ($GLOBALS['registry']->listAPIs() as $api) { - if ($GLOBALS['registry']->hasMethod($api . '/changeLanguage')) { - $GLOBALS['registry']->call($api . '/changeLanguage'); - } - } - } - - $need_reload = true; - } else { - /* Do reload on change of any of these variables. */ - $need_reload = ( - $GLOBALS['prefs']->isDirty('sidebar_width') || - $GLOBALS['prefs']->isDirty('theme') || - $GLOBALS['prefs']->isDirty('menu_view') || - $GLOBALS['prefs']->isDirty('menu_refresh_time')); - } - - if ($GLOBALS['prefs']->isDirty('show_sidebar')) { - $need_reload = true; - $old_sidebar = !$old_sidebar; - } - - if ($need_reload) { - $url = $GLOBALS['registry']->get('webroot', 'horde'); - if (substr($url, -1) != '/') { - $url .= '/'; - } - - $url = str_replace('&', '&', Horde::url(Horde_Util::addParameter($url . 'index.php', array('force_sidebar' => true, 'url' => Horde::selfUrl(true, false, true)), null, false))); - - /* If the old view was with sidebar, need to reload the entire - * frame. */ - if ($old_sidebar) { - Horde::addInlineScript( - 'window.parent.frames.location = ' . Horde_Serialize::serialize($url, Horde_Serialize::JSON, Horde_Nls::getCharset()) . ';' - ); - } else { - Horde::redirect($url); - } - } + $GLOBALS['injector']->getInstance('Horde_Prefs_Ui')->prefsCallback($ui); } } diff --git a/horde/lib/Prefs/Ui.php b/horde/lib/Prefs/Ui.php new file mode 100644 index 000000000..082c9c2de --- /dev/null +++ b/horde/lib/Prefs/Ui.php @@ -0,0 +1,665 @@ + + * @package Horde + */ +class Horde_Prefs_Ui +{ + /** + * Code to run on init when viewing prefs for this application. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + public function prefsInit($ui) + { + global $conf, $prefs, $registry; + + switch ($ui->group) { + case 'display': + if (!$prefs->isLocked('initial_application')) { + $out = array(); + $apps = $registry->listApps(array('active')); + foreach ($apps as $a) { + $perms = $GLOBALS['injector']->getInstance('Horde_Perms'); + if (file_exists($registry->get('fileroot', $a)) && + (($perms->exists($a) && ($perms->hasPermission($a, Horde_Auth::getAuth(), Horde_Perms::READ) || Horde_Auth::isAdmin())) || + !$perms->exists($a))) { + $out[$a] = $registry->get('name', $a); + } + } + asort($out); + $ui->override['initial_application'] = $out; + } + + if (!$prefs->isLocked('theme')) { + $out = array(); + $theme_base = $registry->get('themesfs', 'horde'); + $dh = @opendir($theme_base); + if (!$dh) { + $GLOBALS['notification']->push(_("Theme directory can't be opened"), 'horde.error'); + } else { + while (($dir = readdir($dh)) !== false) { + if ($dir == '.' || $dir == '..') { + continue; + } + + $theme_name = null; + @include $theme_base . '/' . $dir . '/info.php'; + if (!empty($theme_name)) { + $out[$dir] = $theme_name; + } + } + } + + asort($out); + $ui->override['theme'] = $out; + } + break; + + case 'language': + if (!$prefs->isLocked('language')) { + $ui->override['language'] = Horde_Nls::$config['languages']; + array_unshift($ui->override['language'], _("Default")); + } + + if (!$prefs->isLocked('timezone')) { + $ui->override['timezone'] = Horde_Nls::getTimezones(); + array_unshift($ui->override['timezone'], _("Default")); + } + break; + + case 'remote': + Horde::addScriptFile('rpcprefs.js', 'horde'); + $ui->nobuttons = true; + break; + } + + /* Hide appropriate prefGroups. */ + try { + Horde_Auth::singleton($conf['auth']['driver'])->hasCapability('update'); + } catch (Horde_Exception $e) { + $ui->suppressGroups[] = 'forgotpass'; + } + + if (empty($conf['facebook']['enabled']) || + empty($conf['facebook']['key']) || + empty($conf['facebook']['secret'])) { + $ui->suppressGroups[] = 'facebook'; + } + + if (empty($conf['twitter']['enabled']) || + empty($conf['twitter']['key']) || + empty($conf['twitter']['secret'])) { + $ui->suppressGroups[] = 'twitter'; + } + + if (empty($conf['imsp']['enabled'])) { + $ui->suppressGroups[] = 'imspauth'; + } + } + + /** + * Generate code used to display a special preference. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return string The HTML code to display on the options page. + */ + public function prefsSpecial($ui, $item) + { + switch ($item) { + case 'categorymanagement': + return $this->_categoryManagement($ui); + + case 'identityselect': + return $this->_identitySelect($ui); + + case 'remotemanagement': + return $this->_remoteManagement($ui); + + case 'syncmlmanagement': + return $this->_syncmlManagement($ui); + } + + return ''; + } + + /** + * Special preferences handling on update. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return boolean True if preference was updated. + */ + public function prefsSpecialUpdate($ui, $item) + { + switch ($item) { + case 'categorymanagement': + return $this->_updateCategoryManagement($ui); + + case 'identityselect': + return false; + + case 'remotemanagement': + $this->_updateRemoteManagement($ui); + break; + + case 'syncmlmanagement': + $this->_updateSyncmlManagement($ui); + break; + } + + return false; + } + + /** + * Called when preferences are changed. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + public function prefsCallback($ui) + { + global $prefs, $registry; + + $need_reload = false; + $old_sidebar = $prefs->getValue('show_sidebar'); + + if ($prefs->isDirty('language')) { + if ($prefs->isDirty('language')) { + Horde_Nls::setLanguageEnvironment($prefs->getValue('language')); + foreach ($registry->listAPIs() as $api) { + if ($registry->hasMethod($api . '/changeLanguage')) { + $registry->call($api . '/changeLanguage'); + } + } + } + + $need_reload = true; + } else { + /* Do reload on change of any of these variables. */ + $need_reload = ( + $prefs->isDirty('sidebar_width') || + $prefs->isDirty('theme') || + $prefs->isDirty('menu_view') || + $prefs->isDirty('menu_refresh_time') + ); + } + + if ($prefs->isDirty('show_sidebar')) { + $need_reload = true; + $old_sidebar = !$old_sidebar; + } + + if ($need_reload) { + $url = Horde::applicationUrl('index.php')->setRaw(true)->add(array( + 'force_sidebar' => true, + 'url' => strval(Horde::selfUrl(true, false, true)) + )); + + /* If the old view was with sidebar, need to reload the entire + * frame. */ + if ($old_sidebar) { + Horde::addInlineScript( + 'window.parent.frames.location = ' . Horde_Serialize::serialize($url, Horde_Serialize::JSON, Horde_Nls::getCharset()) . ';' + ); + } else { + Horde::redirect($url); + } + } + } + + /** + * Create code for category management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _categoryManagement($ui) + { + Horde::addScriptFile('categoryprefs.js', 'horde'); + Horde::addScriptFile('colorpicker.js', 'horde'); + Horde::addInlineScript(array( + 'HordeAlarmPrefs.category_text = ' . Horde_Serialize::serialize(_("Enter a name for the new category:"), Horde_Serialize::JSON) + )); + + $cManager = new Horde_Prefs_CategoryManager(); + $categories = $cManager->get(); + $colors = $cManager->colors(); + $fgcolors = $cManager->fgColors(); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + if (!$GLOBALS['prefs']->isLocked('category_colors')) { + $t->set('picker_img', Horde::img('colorpicker.png', _("Color Picker"))); + } + $t->set('delete_img', Horde::img('delete.png')); + + // Default Color + $color = isset($colors['_default_']) + ? htmlspecialchars($colors['_default_']) + : '#FFFFFF'; + $fgcolor = isset($fgcolors['_default_']) + ? htmlspecialchars($fgcolors['_default_']) + : '#000000'; + $color_b = 'color_' . hash('md5', '_default_'); + + $t->set('default_color', $color); + $t->set('default_fgcolor', $fgcolor); + $t->set('default_label', Horde::label($color_b, _("Default Color"))); + $t->set('default_id', $color_b); + + // Unfiled Color + $color = isset($colors['_unfiled_']) + ? htmlspecialchars($colors['_unfiled_']) + : '#FFFFFF'; + $fgcolor = isset($fgcolors['_unfiled_']) + ? htmlspecialchars($fgcolors['_unfiled_']) + : '#000000'; + $color_b = 'color_' . hash('md5', '_unfiled_'); + + $t->set('unfiled_color', $color); + $t->set('unfiled_fgcolor', $fgcolor); + $t->set('unfiled_label', Horde::label($color_b, _("Unfiled"))); + $t->set('unfiled_id', $color_b); + + $entries = array(); + foreach ($categories as $name) { + $color = isset($colors[$name]) + ? htmlspecialchars($colors[$name]) + : '#FFFFFF'; + $fgcolor = isset($fgcolors[$name]) + ? htmlspecialchars($fgcolors[$name]) + : '#000000'; + $color_b = 'color_' . hash('md5', $name); + + $entries[] = array( + 'color' => $color, + 'fgcolor' => $fgcolor, + 'label' => Horde::label($color_b, ($name == '_default_' ? _("Default Color") : htmlspecialchars($name))), + 'id' => $color_b, + 'name' => htmlspecialchars($name) + ); + } + $t->set('categories', $entries); + + return $t->fetch(HORDE_TEMPLATES . '/prefs/category.html'); + } + + /** + * Create code for identity selection. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _identitySelect($ui) + { + $identity = Horde_Prefs_Identity::singleton($ui->app == 'horde' ? null : array($ui->app, $ui->app)); + $default_identity = $identity->getDefault(); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + if ($GLOBALS['prefs']->isLocked('default_identity')) { + $t->set('locked', true); + $t->set('default_identity', intval($default_identity)); + } else { + $t->set('label', Horde::label('identity', _("Select the identity you want to change:"))); + + $identities = $identity->getAll('id'); + $members = $this->getChangeablePrefs('identities'); + + $entry = $js = array(); + + for ($i = 0, $icnt = count($identities); $i < $icnt; ++$i) { + $entry[] = array( + 'i' => $i, + 'label' => htmlspecialchars($identities[$i]), + 'sel' => ($i == $default_identity) + ); + + $tmp = array(); + foreach ($members as $member) { + if (($member == 'default_identity') || + !empty($this->prefs[$member]['locked']) || + empty($this->prefs[$member]['type']) || + in_array($this->prefs[$member]['type'], array('link', 'special'))) { + continue; + } + + $val = $identity->getValue($member, $i); + switch ($this->prefs[$member]['type']) { + case 'checkbox': + $val2 = $val ? 'true' : 'false'; + break; + + case 'number': + $val2 = intval($val); + break; + + case 'textarea': + if (is_array($val)) { + $val = implode("\n", $val); + } + // Fall-through + + default: + $val2 = Horde_String::convertCharset($val, Horde_Nls::getCharset(), 'UTF-8'); + } + + $tmp[] = array( + $member, + $this->prefs[$member]['type'], + $val2 + ); + } + + $js[] = $tmp; + } + + $t->set('entry', $entry); + + Horde::addScriptFile('identityselect.js', 'horde'); + Horde::addInlineScript(array( + 'IdentitySelect.newChoice()' + ), 'dom'); + Horde::addInlineScript(array( + 'IdentitySelect.identities = ' . Horde_Serialize::serialize($js, Horde_Serialize::JSON), + 'IdentitySelect.deleteurl = ' . Horde_Serialize::serialize(strval(Horde::selfUrl(true)->setRaw(true)->add('actionID', 'delete_identity')), Horde_Serialize::JSON) + )); + } + + return $t->fetch(HORDE_TEMPLATES . '/prefs/identityselect.html'); + } + + /** + * Create code for remote server management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _remoteManagement($ui) + { + $rpc_servers = @unserialize($GLOBALS['prefs']->getValue('remote_summaries')); + if (!is_array($rpc_servers)) { + $rpc_servers = array(); + } + + $js = $serverlist = array(); + foreach ($rpc_servers as $key => $val) { + $js[] = array($val['url'], $val['user']); + $serverlist[] = array( + 'i' => $key, + 'l' => htmlspecialchars($val['url']) + ); + } + + Horde::addInlineScript(array( + 'HordeRpcPrefs.servers = ' . Horde_Serialize::serialize($js, Horde_Serialize::JSON) + + )); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('serverlabel', Horde::label('server', _("Your remote servers:"))); + $t->set('serverlist', $serverlist); + $t->set('urllabel', Horde::label('url', _("Remote URL (http://www.example.com/horde):"))); + $t->set('userlabel', Horde::label('user', _("Username:"))); + $t->set('passwdlabel', Horde::label('passwd', _("Password:"))); + + return $t->fetch(HORDE_TEMPLATES . '/prefs/rpc.html'); + } + + /** + * Create code for SyncML management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _syncmlManagement($ui) + { + $devices = SyncML_Backend::factory('Horde')->getUserAnchors(Horde_Auth::getAuth()); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $devices = array(); + $selfurl = $ui->selfUrl()->add('deleteanchor', 1); + + foreach ($devices as $device => $anchors) { + foreach ($anchors as $anchor) { + $devices[] = array( + 'anchor' => htmlspecialchars($anchor['syncml_clientanchor']), + 'db' => htmlspecialchars($anchor['syncml_db']), + 'delete' => $selfurl->copy()->add(array( + 'db' => $anchor['syncml_db'], + 'deviceid' => $device + )), + 'device' => htmlspecialchars($device), + 'time' => strftime($GLOBALS['prefs']->getValue('date_format') . ' %H:%M', $anchor['syncml_serveranchor']) + ); + } + } + $t->set('devices', $devices); + + return $t->fetch(HORDE_TEMPLATES . '/prefs/syncml.html'); + } + + /** + * Update category related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return boolean True if preferences were updated. + */ + protected function _updateCategoryManagement($ui) + { + $cManager = new Horde_Prefs_CategoryManager(); + + /* Always save colors of all categories. */ + $colors = array(); + $categories = $cManager->get(); + foreach ($categories as $category) { + if ($color = $ui->vars->get('color_' . hash('md5', $category))) { + $colors[$category] = $color; + } + } + if ($color = $ui->vars->get('color_' . hash('md5', '_default_'))) { + $colors['_default_'] = $color; + } + if ($color = $ui->vars->get('color_' . hash('md5', '_unfiled_'))) { + $colors['_unfiled_'] = $color; + } + $cManager->setColors($colors); + + switch ($ui->vars->cAction) { + case 'add': + $cManager->add($ui->vars->category); + break; + + case 'remove': + $cManager->remove($ui->vars->category); + break; + + default: + /* Save button. */ + Horde::addInlineScript(array( + 'if (window.opener && window.name) window.close();' + )); + return true; + } + + return false; + } + + /** + * Update remote servers related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateRemoteManagement($ui) + { + global $notification, $prefs; + + $rpc_servers = @unserialize($prefs->getValue('remote_summaries')); + if (!is_array($rpc_servers)) { + $rpc_servers = array(); + } + + if ($ui->vars->rpc_change || $ui->vars->rpc_create) { + $tmp = array( + 'passwd' => $ui->vars->passwd, + 'url' => $ui->vars->url, + 'user' => $ui->vars->user + ); + + if ($ui->vars->rpc_change) { + $rpc_servers[$ui->vars->server] = $tmp; + } else { + $rpc_servers[] = $tmp; + } + + $prefs->setValue('remote_summaries', serialize($rpc_servers)); + $notification->push(sprintf(_("The server \"%s\" has been saved."), $ui->vars->url), 'horde.success'); + } elseif ($ui->vars->rpc_delete) { + if ($ui->vars->server == -1) { + $notification->push(_("You must select an server to be deleted."), 'horde.warning'); + } else { + $notification->push(sprintf(_("The server \"%s\" has been deleted."), $rpc_servers[$ui->vars->server]['url']), 'horde.success'); + + $deleted_server = $rpc_servers[$ui->vars->server]['url']; + unset($rpc_servers[$ui->vars->server]); + $prefs->setValue('remote_summaries', serialize(array_values($rpc_servers))); + + $chosenColumns = explode(';', $prefs->getValue('show_summaries')); + if ($chosenColumns != array('')) { + $newColumns = array(); + foreach ($chosenColumns as $chosenColumn) { + $chosenColumn = explode(',', $chosenColumn); + $remote = explode('|', $chosenColumn[0]); + if (count($remote) != 3 || $remote[2] == $deleted_server) { + $newColumns[] = implode(',', $chosenColumn); + } + } + $prefs->setValue('show_summaries', implode(';', $newColumns)); + } + } + } + } + + /** + * Update SyncML related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateSyncmlManagement($ui) + { + $backend = SyncML_Backend::factory('Horde'); + + if ($ui->vars->deleteanchor) { + $res = $backend->removeAnchor(Horde_Auth::getAuth(), $ui->vars->deviceid, $ui->vars->db); + if ($res instanceof PEAR_Error) { + $GLOBALS['notification']->push(_("Error deleting synchronization session:") . ' ' . $res->getMessage(), 'horde.error'); + } else { + $GLOBALS['notification']->push(sprintf(_("Deleted synchronization session for device \"%s\" and database \"%s\"."), $ui->vars->deviceid, $ui->vars->db), 'horde.success'); + } + } elseif ($ui->vars->deleteall) { + $res = $backend->removeAnchor(Horde_Auth::getAuth()); + if ($res instanceof PEAR_Error) { + $GLOBALS['notification']->push(_("Error deleting synchronization sessions:") . ' ' . $res->getMessage(), 'horde.error'); + } else { + $GLOBALS['notification']->push(_("All synchronization sessions deleted."), 'horde.success'); + } + } + } + +/* + try { + $this->prefGroups['identities']['members'] = array_keys(array_flip(array_merge( + $res['prefGroups']['identities']['members'], + $this->prefGroups['identities']['members'] + ))); + $this->prefs = Horde_Array::array_merge_recursive_overwrite($res['_prefs'], $this->prefs); + } catch (Horde_Exception $e) {} + case 'update_prefs': + $from_addresses = $identity->getAll('from_addr'); + $current_from = $identity->getValue('from_addr'); + if ($prefs->isLocked('default_identity')) { + $default = $identity->getDefault(); + } else { + $default = $this->vars->default_identity; + $id = $this->vars->identity; + if ($id == -1) { + $id = $identity->add(); + } elseif ($id == -2) { + $this->prefGroups['identities']['members'] = array('default_identity'); + } + $identity->setDefault($id); + } + + $this->_save = $identity; + + if (!$this->_handleForm($this->getChangeablePrefs($this->group))) { + return; + } + + $new_from = $identity->getValue('from_addr'); + if (!empty($conf['user']['verify_from_addr']) && + $current_from != $new_from && + !in_array($new_from, $from_addresses)) { + try { + $result = $identity->verifyIdentity($id, empty($current_from) ? $new_from : $current_from); + if ($result instanceof Notification_Event) { + $notification->push($result, 'horde.message'); + } + } catch (Horde_Exception $e) { + $notification->push(_("The new from address can't be verified, try again later: ") . $e->getMessage(), 'horde.error'); + Horde::logMessage($e, 'ERR'); + } + break; + } + + $identity->setDefault($default); + $identity->save(); + break; + case 'delete_identity': + $id = intval($this->vars->id); + $deleted_identity = $identity->delete($id); + unset($this->prefs['default_identity']['enum'][$id]); + $notification->push(sprintf(_("The identity \"%s\" has been deleted."), $deleted_identity[0]['id']), 'horde.success'); + break; + + case 'change_default_identity': + $default_identity = $identity->setDefault(intval($this->vars->id)); + $identity->save(); + $notification->push(_("Your default identity has been changed."), 'horde.success'); + break; + } + break; + + if (is_callable(array($this->_save, 'verify'))) { + try { + $this->_save->verify(); + } catch (Exception $e) { + $notification->push($e, 'horde.error'); + } + } + + // $ui->override['default_identity'] = $identity->getAll('id'); + // +*/ +} diff --git a/horde/services/facebook.php b/horde/services/facebook.php index 544f963f0..475c3e7b1 100644 --- a/horde/services/facebook.php +++ b/horde/services/facebook.php @@ -13,9 +13,9 @@ require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('horde'); -if (empty($GLOBALS['conf']['facebook']['enabled']) || - empty($GLOBALS['conf']['facebook']['key']) || - empty($GLOBALS['conf']['facebook']['secret'])) { +if (empty($conf['facebook']['enabled']) || + empty($conf['facebook']['key']) || + empty($conf['facebook']['secret'])) { $horde_url = Horde::url($registry->get('webroot', 'horde') . '/index.php'); header('Location: ' . $horde_url); @@ -23,8 +23,8 @@ if (empty($GLOBALS['conf']['facebook']['enabled']) || } // Facebook key and secret -$apikey = $GLOBALS['conf']['facebook']['key']; -$secret = $GLOBALS['conf']['facebook']['secret']; +$apikey = $conf['facebook']['key']; +$secret = $conf['facebook']['secret']; // Create required objects $context = array('http_client' => new Horde_Http_Client(), @@ -40,14 +40,14 @@ if ($token = Horde_Util::getFormData('auth_token')) { try { $haveSession = $facebook->auth->validateSession(true, true); } catch (Horde_Service_Facebook_Exception $e) { - $GLOBALS['notify']->push(_("Temporarily unable to connect with Facebook, Please try again."), 'horde.alert'); + $notification->push(_("Temporarily unable to connect with Facebook, Please try again."), 'horde.alert'); } if ($haveSession) { // Remember in user prefs $sid = $facebook->auth->getSessionKey(); $uid = $facebook->auth->getUser(); $prefs->setValue('facebook', serialize(array('uid' => $uid, 'sid' => $sid))); - $GLOBALS['notification']->push(_("Succesfully connected your Facebook account."), 'horde.success'); + $notification->push(_("Succesfully connected your Facebook account."), 'horde.success'); } } else { // Require the rest of the actions to be POST only since following them @@ -196,10 +196,9 @@ if (!empty($haveSession)) { } // Start rendering the prefs page -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('horde', null, 'facebook', $chunk); -$csslink = $GLOBALS['registry']->get('themesuri', 'horde') . '/facebook.css'; -echo ''; +// TODO: This won't work - prefs handling must be moved to the new +// preferences framework. +//$csslink = $registry->get('themesuri', 'horde') . '/facebook.css'; if (!empty($haveSession)) { // If we are here, we have a valid session. Facebook strongly suggests to @@ -212,7 +211,7 @@ if (!empty($haveSession)) { try { $user_info = $facebook->fql->run($fql); } catch (Horde_Service_Facebook_Exception $e) { - $GLOBALS['notify']->push(_("Temporarily unable to connect with Facebook, Please try again."), 'horde.alert'); + $notify->push(_("Temporarily unable to connect with Facebook, Please try again."), 'horde.alert'); } // url to revoke authorization $url = Horde_Util::addParameter(Horde::selfUrl(true), array('action' => 'revokeApplication')); @@ -287,6 +286,3 @@ if (!empty($haveSession)) { echo sprintf(_("Login to Facebook and authorize the %s application:"), $registry->get('name')) . 'Facebook'; } -// Need to close the prefs form (opened by the Horde_Prefs_Ui) -echo ''; -require HORDE_TEMPLATES . '/common-footer.inc'; diff --git a/horde/services/portal/rpcsum.php b/horde/services/portal/rpcsum.php deleted file mode 100644 index dedd79dd9..000000000 --- a/horde/services/portal/rpcsum.php +++ /dev/null @@ -1,87 +0,0 @@ - - */ - -require_once dirname(__FILE__) . '/../../lib/Application.php'; -Horde_Registry::appInit('horde'); - -$rpc_servers = @unserialize($prefs->getValue('remote_summaries')); -if (!is_array($rpc_servers)) { - $rpc_servers = array(); -} - -$actionID = Horde_Util::getFormData('actionID'); - -// Handle clients without javascript. -if (is_null($actionID)) { - if (Horde_Util::getPost('edit')) { - $actionID = 'edit'; - } elseif (Horde_Util::getPost('save')) { - $actionID = 'save'; - } elseif (Horde_Util::getPost('delete')) { - $actionID = 'delete'; - } -} - -/* Run through the action handlers */ -switch ($actionID) { -case 'save': - if (($to_edit = Horde_Util::getFormData('edit_server')) == null) { - $to_edit = count($rpc_servers); - $rpc_servers[] = array(); - } - $rpc_servers[$to_edit]['url'] = Horde_Util::getFormData('url'); - $rpc_servers[$to_edit]['user'] = Horde_Util::getFormData('user'); - $rpc_servers[$to_edit]['passwd'] = Horde_Util::getFormData('passwd'); - $prefs->setValue('remote_summaries', serialize($rpc_servers)); - $prefs->store(); - $notification->push(sprintf(_("The server \"%s\" has been saved."), $rpc_servers[$to_edit]['url']), 'horde.success'); - break; - -case 'delete': - $to_delete = Horde_Util::getFormData('server'); - if ($to_delete != -1) { - $deleted_server = $rpc_servers[$to_delete]['url']; - $server_list = array(); - for ($i = 0; $i < count($rpc_servers); $i++) { - if ($i == $to_delete) { - continue; - } - $server_list[] = $rpc_servers[$i]; - } - $prefs->setValue('remote_summaries', serialize($server_list)); - $chosenColumns = explode(';', $prefs->getValue('show_summaries')); - if ($chosenColumns != array('')) { - $newColumns = array(); - foreach ($chosenColumns as $chosenColumn) { - $chosenColumn = explode(',', $chosenColumn); - $remote = explode('|', $chosenColumn[0]); - if (count($remote) != 3 || $remote[2] == $deleted_server) { - $newColumns[] = implode(',', $chosenColumn); - } - } - $prefs->setValue('show_summaries', implode(';', $newColumns)); - } - $prefs->store(); - $rpc_servers = $server_list; - $notification->push(sprintf(_("The server \"%s\" has been deleted."), $deleted_server), 'horde.success'); - } else { - $notification->push(_("You must select an server to be deleted."), 'horde.warning'); - } - break; -} - -/* Show the header. */ -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('horde', null, 'remote', $chunk); - -require HORDE_TEMPLATES . '/rpcsum/rpcsum.inc'; -if (!$chunk) { - require HORDE_TEMPLATES . '/common-footer.inc'; -} diff --git a/horde/services/portal/syncml.php b/horde/services/portal/syncml.php deleted file mode 100644 index cb79aeed0..000000000 --- a/horde/services/portal/syncml.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ - -require_once dirname(__FILE__) . '/../../lib/Application.php'; -Horde_Registry::appInit('horde'); - -$backend = SyncML_Backend::factory('Horde'); - -$actionID = Horde_Util::getFormData('actionID'); -switch ($actionID) { -case 'deleteanchor': - $deviceid = Horde_Util::getFormData('deviceid'); - $db = Horde_Util::getFormData('db'); - $result = $backend->removeAnchor(Horde_Auth::getAuth(), $deviceid, $db); - if (is_a($result, 'PEAR_Error')) { - $notification->push(_("Error deleting synchronization session:") - . ' ' . $result->getMessage(), - 'horde.error'); - } else { - $notification->push(sprintf(_("Deleted synchronization session for device \"%s\" and database \"%s\"."), - $deviceid, $db), - 'horde.success'); - } - break; - -case 'deleteall': - $result = $backend->removeAnchor(Horde_Auth::getAuth()); - if (is_a($result, 'PEAR_Error')) { - $notification->push(_("Error deleting synchronization sessions:") - . ' ' . $result->getMessage(), - 'horde.error'); - } else { - $notification->push(_("All synchronization sessions deleted."), - 'horde.success'); - } - break; -} - -$devices = $backend->getUserAnchors(Horde_Auth::getAuth()); - -/* Show the header. */ -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_UI::generateHeader('horde', null, 'syncml', $chunk); - -require HORDE_TEMPLATES . '/syncml/syncml.inc'; -if (!$chunk) { - require HORDE_TEMPLATES . '/common-footer.inc'; -} diff --git a/horde/services/prefs.php b/horde/services/prefs.php index 5556d63aa..967e6af7c 100644 --- a/horde/services/prefs.php +++ b/horde/services/prefs.php @@ -1,6 +1,12 @@ array(), '_prefs' => array()); - } - - if ($merge) { - try { - $GLOBALS['prefGroups']['identities']['members'] = array_keys(array_flip(array_merge( - $res['prefGroups']['identities']['members'], - $GLOBALS['prefGroups']['identities']['members']))); - $GLOBALS['_prefs'] = Horde_Array::array_merge_recursive_overwrite($res['_prefs'], $GLOBALS['_prefs']); - } catch (Horde_Exception $e) {} - } else { - $GLOBALS['prefGroups'] = $res['prefGroups']; - $GLOBALS['_prefs'] = $res['_prefs']; - } -} - require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('horde'); -/* Figure out which application we're setting preferences for. */ -$app = Horde_Util::getFormData('app', Horde_Prefs_Ui::getDefaultApp()); -$appbase = realpath($registry->get('fileroot', $app)); - -/* See if we have a preferences group set. */ -$group = Horde_Util::getFormData('group'); - -/* See if only a page body was requested. */ -$chunk = Horde_Util::nonInputVar('chunk'); - -/* Load $app's base environment. */ -$registry->pushApp($app); - -/* Set title. */ -$title = sprintf(_("Options for %s"), $registry->get('name')); - -/* Load identity here - Identity object may be needed in app's prefs.php. */ -if ($group == 'identities') { - $identity = Horde_Prefs_Identity::singleton($app == 'horde' ? null : array($app, $app)); -} - -/* Get ActionID. */ -$actionID = Horde_Util::getFormData('actionID'); - -/* Run prefs_ui init code, if available. */ -if ($registry->hasAppMethod($app, 'prefsInit')) { - $result = $registry->callAppMethod($app, 'prefsInit', array('args' => array($group))); - if (!empty($result)) { - extract($result); - } -} - -/* Load $app's preferences, if any. */ -$prefGroups = array(); -_loadPrefsConfig($app); - -/* See if this group has a custom URL. */ -if ($group && !empty($prefGroups[$group]['url'])) { - $pref_url = $prefGroups[$group]['url']; - $filename = $appbase . '/' . $pref_url; - if (file_exists($filename)) { - require $filename; - return; - } - throw new Horde_Exception('Incorrect url value (' . $pref_url . ') for preferences group ' . $group . ' for app ' . $app); -} - -/* If there's only one prefGroup, just show it. */ -if (empty($group) && count($prefGroups) == 1) { - $group = array_keys($prefGroups); - $group = array_pop($group); -} - -if ($group == 'identities') { - if ($app != 'horde') { - _loadPrefsConfig('horde', true); - } - - switch ($actionID) { - case 'update_prefs': - $from_addresses = $identity->getAll('from_addr'); - $current_from = $identity->getValue('from_addr'); - if ($prefs->isLocked('default_identity')) { - $default = $identity->getDefault(); - } else { - $default = Horde_Util::getPost('default_identity'); - $id = Horde_Util::getPost('identity'); - if ($id == -1) { - $id = $identity->add(); - } elseif ($id == -2) { - $prefGroups['identities']['members'] = array('default_identity'); - } - $identity->setDefault($id); - } - - if (!Horde_Prefs_Ui::handleForm($group, $identity, $app, $prefGroups, $_prefs)) { - break; - } - - $new_from = $identity->getValue('from_addr'); - if (!empty($conf['user']['verify_from_addr']) && - $current_from != $new_from && - !in_array($new_from, $from_addresses)) { - try { - $result = $identity->verifyIdentity($id, empty($current_from) ? $new_from : $current_from); - if ($result instanceof Notification_Event) { - $notification->push($result, 'horde.message'); - } - } catch (Horde_Exception $e) { - $notification->push(_("The new from address can't be verified, try again later: ") . $e->getMessage(), 'horde.error'); - Horde::logMessage($e, 'ERR'); - } - break; - } - - $identity->setDefault($default); - $identity->save(); - unset($prefGroups); - - _loadPrefsConfig($app); - if ($app != 'horde') { - _loadPrefsConfig('horde', true); - } - break; - - case 'delete_identity': - $id = (int)Horde_Util::getFormData('id'); - $deleted_identity = $identity->delete($id); - unset($_prefs['default_identity']['enum'][$id]); - $notification->push(sprintf(_("The identity \"%s\" has been deleted."), $deleted_identity[0]['id']), 'horde.success'); - break; - - case 'change_default_identity': - $default_identity = $identity->setDefault(Horde_Util::getFormData('id')); - $identity->save(); - $notification->push(_("Your default identity has been changed."), - 'horde.success'); - break; - } -} elseif ($group && - ($actionID == 'update_prefs') && - Horde_Prefs_Ui::handleForm($group, $prefs, $app, $prefGroups, $_prefs)) { - _loadPrefsConfig($app); - - if (count($prefGroups) == 1 && empty($group)) { - $group = array_keys($prefGroups); - $group = array_pop($group); - } -} +$prefs_ui = new Horde_Core_Prefs_Ui(Horde_Variables::getDefaultVariables()); -/* Show the UI. */ -Horde_Prefs_Ui::generateUI($app, $prefGroups, $_prefs, $group, $chunk); +/* Handle form submission. */ +$prefs_ui->handleForm(); -if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-footer.inc'; -} +/* Generate the UI. */ +$prefs_ui->generateUI(); diff --git a/horde/services/twitter.php b/horde/services/twitter.php index 805149dbe..f505353a3 100644 --- a/horde/services/twitter.php +++ b/horde/services/twitter.php @@ -12,34 +12,36 @@ require_once dirname(__FILE__) . '/../lib/Application.php'; Horde_Registry::appInit('horde'); -if (empty($GLOBALS['conf']['twitter']['enabled'])) { +if (empty($conf['twitter']['enabled'])) { $horde_url = Horde::url($registry->get('webroot', 'horde') . '/index.php'); header('Location: ' . $horde_url); exit; } -/* Create a cache object for the twitter client */ -$cache = $injector->getInstance('Horde_Cache'); - /* Using OAuth or Http Basic? */ -if (!empty($GLOBALS['conf']['twitter']['key']) && !empty($GLOBALS['conf']['twitter']['secret'])) { +if (!empty($conf['twitter']['key']) && !empty($conf['twitter']['secret'])) { /* Keys - these are obtained when registering for the service */ - $consumer_key = $GLOBALS['conf']['twitter']['key']; - $consumer_secret = $GLOBALS['conf']['twitter']['secret']; + $consumer_key = $conf['twitter']['key']; + $consumer_secret = $conf['twitter']['secret']; /* Parameters required for the Horde_Oauth_Consumer */ - $params = array('key' => $consumer_key, - 'secret' => $consumer_secret, - 'requestTokenUrl' => Horde_Service_Twitter::REQUEST_TOKEN_URL, - 'authorizeTokenUrl' => Horde_Service_Twitter::USER_AUTHORIZE_URL, - 'accessTokenUrl' => Horde_Service_Twitter::ACCESS_TOKEN_URL, - 'signatureMethod' => new Horde_Oauth_SignatureMethod_HmacSha1()); + $params = array( + 'key' => $consumer_key, + 'secret' => $consumer_secret, + 'requestTokenUrl' => Horde_Service_Twitter::REQUEST_TOKEN_URL, + 'authorizeTokenUrl' => Horde_Service_Twitter::USER_AUTHORIZE_URL, + 'accessTokenUrl' => Horde_Service_Twitter::ACCESS_TOKEN_URL, + 'signatureMethod' => new Horde_Oauth_SignatureMethod_HmacSha1() + ); /* Create the Consumer */ $oauth = new Horde_Oauth_Consumer($params); /* Create the Twitter client */ - $twitter = new Horde_Service_Twitter(array('oauth' => $oauth, 'cache' => $cache)); + $twitter = new Horde_Service_Twitter(array( + 'cache' => $injector->getInstance('Horde_Cache'), + 'oauth' => $oauth + )); /* See if we have an existing token for the current user */ $token = unserialize($prefs->getValue('twitter')); @@ -49,10 +51,13 @@ if (!empty($GLOBALS['conf']['twitter']['key']) && !empty($GLOBALS['conf']['twitt $auth_token = new Horde_Oauth_Token($token['key'], $token['secret']); $twitter->auth->setToken($auth_token); } -} elseif (!empty($_SESSION['horde']['twitterblock']['username']) && !empty($_SESSION['horde']['twitterblock']['password'])) { - $twitter = new Horde_Service_Twitter(array('username' => $_SESSION['horde']['twitterblock']['username'], - 'password' => $_SESSION['horde']['twitterblock']['password'], - 'cache' => $cache)); +} elseif (!empty($_SESSION['horde']['twitterblock']['username']) && + !empty($_SESSION['horde']['twitterblock']['password'])) { + $twitter = new Horde_Service_Twitter(array( + 'cache' => $injector->getInstance('Horde_Cache'), + 'password' => $_SESSION['horde']['twitterblock']['password'], + 'username' => $_SESSION['horde']['twitterblock']['username'] + )); } /* See if we are here for any actions */ @@ -63,6 +68,7 @@ case 'revokeInfinite': $prefs->setValue('twitter', 'a:0:{}'); echo ''; exit; + case 'updateStatus': $result = $twitter->statuses->update(Horde_Util::getPost('statusText'), Horde_Util::getPost('inReplyTo', '')); header('Content-Type: application/json'); @@ -76,8 +82,7 @@ if (!empty($auth_token)) { } elseif (!empty($_SESSION['twitter_request_secret'])) { /* No existing auth token, maybe we are in the process of getting it? */ try { - $auth_token = $twitter->auth->getAccessToken(new Horde_Controller_Request_Http(), - $_SESSION['twitter_request_secret']); + $auth_token = $twitter->auth->getAccessToken(new Horde_Controller_Request_Http(), $_SESSION['twitter_request_secret']); } catch (Horde_Service_Twitter_Exception $e) { echo '
' . sprintf(_("Error connecting to Twitter: %s Details have been logged for the administrator."), $e->getMessage()) . '
'; echo ''; @@ -118,10 +123,7 @@ if (!empty($auth_token)) { } // Start rendering the prefs page -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('horde', null, 'twitter', $chunk); -$csslink = $GLOBALS['registry']->get('themesuri', 'horde') . '/facebook.css'; -echo ''; +//$csslink = $registry->get('themesuri', 'horde') . '/facebook.css'; /* Could not find a valid auth token, and we are not in the process of getting one */ if (empty($profile)) { @@ -147,6 +149,3 @@ if (empty($profile)) { echo '
' . sprintf(_("%s can interact with your Twitter account."), $registry->get('name')); echo '
'; } - -echo ''; -require HORDE_TEMPLATES . '/common-footer.inc'; diff --git a/horde/templates/menu/menu.inc b/horde/templates/menu/menu.inc index 10699f550..e3642354e 100644 --- a/horde/templates/menu/menu.inc +++ b/horde/templates/menu/menu.inc @@ -1,15 +1,12 @@ - - -

- " /> - - ';" value="" /> - " /> -

- - diff --git a/horde/templates/syncml/syncml.inc b/horde/templates/syncml/syncml.inc deleted file mode 100644 index 33822b3b0..000000000 --- a/horde/templates/syncml/syncml.inc +++ /dev/null @@ -1,43 +0,0 @@ -
- -
- - - - - - - - - - - - $anchors) { - foreach ($anchors as $anchor) { -?> - - - - - - - - -
getValue('date_format') . ' %H:%M', $anchor['syncml_serveranchor']) ?> -
- - - - " /> -
-
- -

- - " /> - " /> -

- - - diff --git a/horde/themes/screen.css b/horde/themes/screen.css index b18bd2e17..3b7ac819b 100644 --- a/horde/themes/screen.css +++ b/horde/themes/screen.css @@ -524,6 +524,9 @@ div.nicetitle { list-style: none; display: inline; } +#services_prefs #app { + font-weight: bold; +} .prefsOverview div { float: left; } @@ -558,6 +561,9 @@ div.prefsContainer { div.prefsContainer p { padding-top: 1em; } +img.prefsLinkImg { + padding-right: 1px; +} /* Block styles. */ .currentBlock { diff --git a/imp/acl.php b/imp/acl.php deleted file mode 100644 index 5588927d4..000000000 --- a/imp/acl.php +++ /dev/null @@ -1,192 +0,0 @@ - - * @author Eric Garrido - * @package IMP - */ - -require_once dirname(__FILE__) . '/lib/Application.php'; -Horde_Registry::appInit('imp'); - -/* Redirect back to the options screen if ACL is not enabled. */ -$prefs_url = Horde::getServiceLink('options', 'imp'); -if ($prefs->isLocked('acl') || empty($_SESSION['imp']['imap']['acl'])) { - $notification->push('Folder sharing is not enabled.', 'horde.error'); - header('Location: ' . $prefs_url); - exit; -} - -try { - $ACL = $injector->getInstance('IMP_Imap_Acl'); -} catch (Horde_Exception $e) { - $notification->push(_("This server does not support sharing folders."), 'horde.error'); - header('Location: ' . $prefs_url); - exit; -} - -$vars = Horde_Variables::getDefaultVariables(); - -/* Check to see if $vars->new_user already has an acl on the folder. */ -if ($vars->new_user && isset($vars->acl[$vars->new_user])) { - $vars->acl[$vars->new_user] = $vars->new_acl; - $vars->new_user = ''; -} - -$protected = $ACL->getProtected(); - -/* Run through the action handlers. */ -switch ($vars->actionID) { -case 'imp_acl_set': - if (!$vars->folder) { - $notification->push(_("No folder selected."), 'horde.error'); - break; - } - - if ($vars->new_user) { - try { - $ACL->editACL($vars->folder, $vars->new_user, $vars->new_acl); - if (count($vars->new_acl)) { - $notification->push(sprintf(_("User \"%s\" successfully given the specified rights for the folder \"%s\"."), $vars->new_user, $vars->folder), 'horde.success'); - } else { - $notification->push(sprintf(_("All rights on folder \"%s\" successfully removed for user \"%s\"."), $vars->folder, $vars->new_user), 'horde.success'); - } - } catch (Horde_Exception $e) { - $notification->push($e); - } - } - - $curr_acl = $ACL->getACL($vars->folder); - foreach ($vars->acl as $user => $acl) { - if ($acl) { - $acl = array_flip($acl); - /* We had to have an empty value submitted to make sure all - users with acls were sent back, so we can remove those - without checkmarks. */ - unset($acl['']); - } else { - $acl = array(); - } - - if (!$user) { - $notification->push(_("No user specified."), 'horde.error'); - continue; - } - - if (in_array($user, $protected)) { - if ($acl) { - $notification->push(sprintf(_("Rights for user \"%s\" cannot be modified."), $user), 'horde.error'); - } - continue; - } - - /* Check to see if ACL didn't change */ - if ((isset($curr_acl[$user])) && - (array_keys($curr_acl[$user]) == array_keys($acl))) { - continue; - } - - try { - unset($curr_acl); - $ACL->editACL($vars->folder, $user, $acl); - if (!count($acl)) { - $notification->push(sprintf(_("All rights on folder \"%s\" successfully removed for user \"%s\"."), $vars->folder, $user), 'horde.success'); - } else { - $notification->push(sprintf(_("User \"%s\" successfully given the specified rights for the folder \"%s\"."), $user, $vars->folder), 'horde.success'); - } - } catch (Horde_Exception $e) { - $notification->push($e); - } - } - break; -} - -$imp_folder = $injector->getInstance('IMP_Folder'); -$rights = $ACL->getRights(); - -if (empty($vars->folder)) { - $vars->folder = 'INBOX'; -} - -if (!isset($curr_acl)) { - $curr_acl = $ACL->getACL($vars->folder); -} -$canEdit = $ACL->canEdit($vars->folder, Horde_Auth::getAuth()); - -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('imp', null, null, $chunk); - -/* Set up template. */ -$t = $injector->createInstance('Horde_Template'); -$t->setOption('gettext', true); -$t->set('aclurl', Horde::applicationUrl('acl.php')); -$t->set('forminput', Horde_Util::formInput()); -$t->set('aclnavcell', Horde_Util::bufferOutput(array('Horde_Prefs_Ui', 'generateNavigationCell'), 'imp', 'acl')); -$t->set('changefolder', Horde::link('#', _("Change Folder"), 'smallheader', '', '', '', '', array('id' => 'changefolder'))); -$t->set('options', IMP::flistSelect(array('selected' => $vars->folder))); -$t->set('current', sprintf(_("Current access to %s"), IMP::displayFolder($vars->folder))); -$t->set('folder', $vars->folder); -$t->set('noacl', !count($curr_acl)); -$t->set('maxrule', 1); -if (!$t->get('noacl')) { - $i = 0; - $cval = array(); - foreach ($curr_acl as $index => $rule) { - $entry = array( - 'i' => ++$i, - 'num_val' => ($i - 1), - 'disabled' => in_array($index, $protected) || !$canEdit, - 'index' => $index - ); - /* Create table of each ACL option for each user granted permissions, - * enabled indicates the right has been given to the user */ - foreach (array_keys($rights) as $val) { - $entry['rule'][] = array('val' => $val, 'enabled' => in_array($val, $rule)); - } - $cval[] = $entry; - } - $t->set('curr_acl', $cval); - $t->set('maxval', count($curr_acl)); - /* number of individual ACL options, for table rendering */ - $t->set('maxrule', count($rights)); -} -$t->set('canedit', $canEdit); -if (empty($_SESSION['imp']['admin'])) { - $new_user_field = ''; -} else { - $current_users = array_keys($curr_acl); - $new_user_field = '"; -} -$t->set('new_user', $new_user_field); - -$rightsTitlesval = array(); -foreach ($rights as $right => $val) { - $rightsval[] = array( - 'right' => $right, - 'desc' => $val['desc'], - 'title' => $val['title'] - ); -} - -$t->set('rights', $rightsval); -$t->set('width', round(100 / (count($rightsval) + 1)) . '%'); -$t->set('prefsurl', $prefs_url); - -Horde::addScriptFile('acl.js', 'imp'); -echo $t->fetch(IMP_TEMPLATES . '/imp/acl/acl.html'); -if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-footer.inc'; -} diff --git a/imp/config/prefs.php.dist b/imp/config/prefs.php.dist index 5da230de6..6291b41e2 100644 --- a/imp/config/prefs.php.dist +++ b/imp/config/prefs.php.dist @@ -5,289 +5,74 @@ * $Id$ */ -// Make sure that constants are defined. -$is_pop3 = isset($_SESSION['imp']['protocol']) && ($_SESSION['imp']['protocol'] == 'pop'); +// *** Personal Information Preferences *** $prefGroups['identities'] = array( 'column' => _("General Options"), 'label' => _("Personal Information"), 'desc' => _("Change the name, address, and signature that people see when they read and reply to your email."), - 'members' => array('replyto_addr', 'alias_addr', 'tieto_addr', 'bcc_addr', - 'signature', 'sig_dashes', 'sig_first', - 'save_sent_mail', 'sent_mail_folder', 'sentmailselect') -); - -if (!$is_pop3) { - $prefGroups['server'] = array( - 'column' => _("General Options"), - 'label' => _("Server and Folder Information"), - 'desc' => _("Change mail server and folder settings."), - 'members' => array('use_vinbox', 'subscribe', 'draftsselect', - 'trashselect', 'spamselect') - ); -} - -if (!empty($_SESSION['imp']['imap']['acl'])) { - $prefGroups['acl'] = array( - 'column' => _("General Options"), - 'label' => _("Share Folders"), - 'desc' => _("Share your mail folders with other users."), - 'url' => 'acl.php' - ); -} - -$prefGroups['logintasks'] = array( - 'column' => _("General Options"), - 'label' => _("Login Tasks"), - 'desc' => sprintf(_("Configure tasks to run upon logon to %s."), $GLOBALS['registry']->get('name')), - 'members' => array('delete_attachments_monthly', - 'delete_attachments_monthly_keep') -); -if (!$is_pop3) { - $prefGroups['logintasks']['members'] = array_merge( - $prefGroups['logintasks']['members'], - array('initialpageselect', 'rename_sentmail_monthly', - 'delete_sentmail_monthly', 'delete_sentmail_monthly_keep', - 'purge_sentmail', 'purge_sentmail_interval', - 'purge_sentmail_keep', 'purge_trash', 'purge_trash_interval', - 'purge_trash_keep', 'purge_spam', 'purge_spam_interval', - 'purge_spam_keep')); -} - -if (!empty($GLOBALS['conf']['user']['allow_accounts'])) { - $prefGroups['accounts'] = array( - 'column' => _("General Options"), - 'label' => _("Additional Accounts"), - 'desc' => _("Configure additional mail accounts to display."), - 'members' => array('accountsmanagement') - ); -} - -$prefGroups['compose'] = array( - 'column' => _("Message Options"), - 'label' => _("Message Composition"), - 'desc' => _("Configure how you send mail."), - 'members' => array('stationery_link', 'mailto_handler', 'compose_cc', - 'compose_bcc', 'compose_spellcheck', 'compose_confirm', - 'set_priority', 'compose_popup', 'compose_html', - 'ckeditor_buttons', 'mail_domain', - 'compose_cursor', 'sending_charset', 'encryptselect', - 'save_attachments') -); - -if (!empty($GLOBALS['conf']['compose']['allow_receipts'])) { - $prefGroups['compose']['members'] = array_merge($prefGroups['compose']['members'], array('disposition_request_read')); -} - -$prefGroups['reply'] = array( - 'column' => _("Message Options"), - 'label' => _("Message Replies"), - 'desc' => _("Configure how you reply to mail."), - 'members' => array('reply_quote', 'reply_format', 'reply_headers', - 'attrib_text') -); - -$prefGroups['forward'] = array( - 'column' => _("Message Options"), - 'label' => _("Message Forwards"), - 'desc' => _("Configure how you forward mail."), - 'members' => array('forward_default', 'forward_format') + 'members' => array( + 'replyto_addr', 'alias_addr', 'tieto_addr', 'bcc_addr', 'signature', + 'sig_dashes', 'sig_first', 'save_sent_mail', 'sent_mail_folder', + 'sentmailselect' + ) ); -$prefGroups['drafts'] = array( - 'column' => _("Message Options"), - 'label' => _("Message Drafts"), - 'desc' => _("Configure how to deal with message drafts."), - 'members' => array('draftsselect', 'close_draft', 'unseen_drafts', - 'auto_save_drafts', 'auto_delete_drafts') -); - -$prefGroups['viewing'] = array( - 'column' => _("Message Options"), - 'label' => _("Message Viewing"), - 'desc' => _("Configure how messages are displayed."), - 'members' => array('filtering', 'strip_attachments', - 'html_image_replacement', 'html_image_addrbook', - 'highlight_text', 'highlight_simple_markup', - 'show_quoteblocks', 'dim_signature', 'emoticons', - 'parts_display', 'mail_hdr', 'default_msg_charset') -); -if (!empty($GLOBALS['conf']['maillog']['use_maillog'])) { - $prefGroups['viewing']['members'] = array_merge($prefGroups['viewing']['members'], array('disposition_send_mdn')); -} - -$prefGroups['delmove'] = array( - 'column' => _("Message Options"), - 'label' => _("Deleting and Moving Messages"), - 'desc' => _("Set preferences for what happens when you move and delete messages."), - 'members' => array('mailbox_return', 'delete_spam_after_report', - 'move_ham_after_report', 'empty_spam_menu') -); -if (!$is_pop3) { - $prefGroups['delmove']['members'] = array_merge( - $prefGroups['delmove']['members'], - array('use_trash', 'trashselect', 'use_vtrash', 'empty_trash_menu')); -} - -$prefGroups['newmail'] = array( - 'column' => _("Message Options"), - 'label' => _("New Mail"), - 'desc' => _("Control when new mail will be checked for, and whether or not to notify you when it arrives."), - 'members' => array('refresh_time', 'nav_poll_all', 'nav_popup', 'soundselect') -); - -if (!$is_pop3) { - $prefGroups['flags'] = array( - 'column' => _("Message Options"), - 'label' => _("Message Flags"), - 'desc' => _("Configure flag highlighting."), - 'members' => array('flagmanagement') - ); -} - -$prefGroups['display'] = array( - 'column' => _("Other Options"), - 'label' => _("Mailbox and Folder Display Options"), - 'desc' => _("Change display options such as how many messages you see on each page and how messages are sorted."), - 'members' => array('mailbox_start', 'sortby', 'sortdir', 'max_msgs', - 'from_link', 'time_format', 'atc_flag') -); -if (!$is_pop3) { - $prefGroups['display']['members'] = array_merge( - $prefGroups['display']['members'], - array('nav_expanded', 'tree_view', 'nav_expanded_sidebar')); -} - -$prefGroups['filters'] = array( - 'column' => _("Other Options"), - 'label' => _("Filters"), - 'desc' => _("Create filtering rules to organize your incoming mail, sort it into folders, and delete spam."), - 'url' => 'filterprefs.php' -); - -$contacts_app = $GLOBALS['registry']->hasInterface('contacts'); -if ($contacts_app && $GLOBALS['registry']->hasPermission($contacts_app)) { - $prefGroups['addressbooks'] = array( - 'column' => _("Other Options"), - 'label' => _("Address Books"), - 'desc' => _("Select address book sources for adding and searching for addresses."), - 'members' => array('save_recipients', 'display_contact', 'sourceselect') - ); -} - -$prefGroups['events'] = array( - 'column' => _("Other Options"), - 'label' => _("Event Requests"), - 'desc' => _("Configure how event or meeting requests should be handled."), - 'members' => array('conflict_interval') -); - -if (isset($GLOBALS['conf']['gnupg']['path'])) { - $prefGroups['pgp'] = array( - 'column' => _("Other Options"), - 'label' => _("PGP Options"), - 'desc' => sprintf(_("Control PGP support for %s."), $GLOBALS['registry']->get('name')), - 'url' => 'pgp.php' - ); -} - -if (Horde_Util::extensionExists('openssl') && isset($GLOBALS['conf']['openssl']['path'])) { - $prefGroups['smime'] = array( - 'column' => _("Other Options"), - 'label' => _("S/MIME Options"), - 'desc' => sprintf(_("Control S/MIME support for %s."), $GLOBALS['registry']->get('name')), - 'url' => 'smime.php' - ); -} - -$prefGroups['mimp'] = array( - 'column' => _("Other Options"), - 'label' => _("Mobile View Options"), - 'desc' => _("Configure options for the mobile view."), - 'members' => array('mimp_preview_msg', 'mimp_download_confirm', - 'mimp_inline_all') -); - -$prefGroups['standard'] = array( - 'column' => _("Other Options"), - 'label' => _("Standard View Options"), - 'desc' => _("Configure options for the standard view."), - 'members' => array('preview_enabled', 'preview_maxlen', 'preview_strip_nl', 'preview_show_unread', 'preview_show_tooltip') -); - -$prefGroups['dimp'] = array( - 'column' => _("Other Options"), - 'label' => _("Dynamic View Options"), - 'desc' => _("Configure options for the dynamic view."), - 'members' => array('dimp_login_view') -); - - -// Personal Information preferences - // user preferred email address for Reply-To:, if different from From: $_prefs['replyto_addr'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'text', - 'desc' => _("Your Reply-to: address: (optional)")); + 'desc' => _("Your Reply-to: address: (optional)") +); // user preferred alias addresses $_prefs['alias_addr'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'textarea', - 'desc' => _("Your alias addresses: (optional, enter each address on a new line)")); + 'desc' => _("Your alias addresses: (optional, enter each address on a new line)") +); // user preferred 'tie to' addresses $_prefs['tieto_addr'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'textarea', - 'desc' => _("Addresses to explicitly tie to this identity: (optional, enter each address on a new line)")); + 'desc' => _("Addresses to explicitly tie to this identity: (optional, enter each address on a new line)") +); // Automatically Bcc addresses when composing $_prefs['bcc_addr'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'textarea', - 'desc' => _("Addresses to BCC all messages: (optional, enter each address on a new line)")); + 'desc' => _("Addresses to BCC all messages: (optional, enter each address on a new line)") +); // user signature $_prefs['signature'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'textarea', - 'desc' => _("Your signature:")); + 'desc' => _("Your signature:") +); // precede the signature with dashes ('-- ')? $_prefs['sig_dashes'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Precede your signature with dashes ('-- ')?")); + 'desc' => _("Precede your signature with dashes ('-- ')?") +); // signature before replies and forwards? $_prefs['sig_first'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Place your signature before replies and forwards?")); + 'desc' => _("Place your signature before replies and forwards?") +); // save a copy of sent messages? $_prefs['save_sent_mail'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Save sent mail?")); + 'desc' => _("Save sent mail?") +); // sent mail folder $_prefs['sent_mail_folder'] = array( @@ -300,39 +85,50 @@ $_prefs['sent_mail_folder'] = array( // necessary conversion. // 'value' => Horde_String::convertCharset('Sent', null, 'UTF7-IMAP'), // Exchange servers use this default value instead. - // 'value' => 'Sent Items', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + // 'value' => 'Sent Items' +); -// sent mail folder selection widget. includes some javascript, so it's -// specific to IMP. -$_prefs['sentmailselect'] = array('type' => 'special'); +// sent mail folder selection widget. +$_prefs['sentmailselect'] = array( + 'type' => 'special' +); -// End Personal Information preferences -// Server and Folder Information preferences +// *** Server and Folder Preferences *** + +$prefGroups['server'] = array( + 'column' => _("General Options"), + 'label' => _("Server and Folder Information"), + 'desc' => _("Change mail server and folder settings."), + 'members' => array( + 'use_vinbox', 'subscribe', 'draftsselect', 'trashselect', 'spamselect' + ) +); // display Virtual INBOX? $_prefs['use_vinbox'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Display Virtual Inbox?")); + 'desc' => _("Display Virtual Inbox?") +); + +// virtual inbox identifier +$_prefs['vinbox_id'] = array( + 'value' => '' +); // use IMAP subscribe? $_prefs['subscribe'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Use IMAP folder subscriptions?")); + 'desc' => _("Use IMAP folder subscriptions?") +); -// drafts folder selection widget. includes some javascript, so it's specific -// to IMP. -$_prefs['draftsselect'] = array('type' => 'special'); +// drafts folder selection widget. +$_prefs['draftsselect'] = array( + 'type' => 'special' +); // drafts folder $_prefs['drafts_folder'] = array( @@ -343,14 +139,13 @@ $_prefs['drafts_folder'] = array( // If the mailbox value contains non-ASCII characters, it must be encoded // in the UTF7-IMAP charset (RFC 3501 [5.1.3]). This entry will do the // necessary conversion. - // 'value' => Horde_String::convertCharset('Drafts', null, 'UTF7-IMAP'), - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + // 'value' => Horde_String::convertCharset('Drafts', null, 'UTF7-IMAP') +); -// trash folder selection widget. includes some javascript, so it's -// specific to IMP. -$_prefs['trashselect'] = array('type' => 'special'); +// trash folder selection widget. +$_prefs['trashselect'] = array( + 'type' => 'special' +); // trash folder $_prefs['trash_folder'] = array( @@ -363,242 +158,258 @@ $_prefs['trash_folder'] = array( // necessary conversion. // 'value' => Horde_String::convertCharset('Trash', null, 'UTF7-IMAP'), // Exchange servers use this default value instead. - // 'value' => 'Deleted Items', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + // 'value' => 'Deleted Items' +); -// spam folder selection widget. includes some javascript, so it's -// specific to IMP. -$_prefs['spamselect'] = array('type' => 'special'); +// spam folder selection widget. +$_prefs['spamselect'] = array( + 'type' => 'special' +); // spam folder $_prefs['spam_folder'] = array( // NOTE: Localization of this name for display purposes is done // automatically. This entry only needs to be changed if the mailbox name // on the IMAP server is different than this value. - 'value' => 'Spam', + 'value' => 'Spam' // If the mailbox value contains non-ASCII characters, it must be encoded // in the UTF7-IMAP charset (RFC 3501 [5.1.3]). This entry will do the // necessary conversion. - // 'value' => Horde_String::convertCharset('Spam', null, 'UTF7-IMAP'), - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + // 'value' => Horde_String::convertCharset('Spam', null, 'UTF7-IMAP') +); $_prefs['vfolder'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); + + -// End Server and Folder Information preferences +// *** ACL Preferences *** +$prefGroups['acl'] = array( + 'column' => _("General Options"), + 'label' => _("Share Folders"), + 'desc' => _("Share your mail folders with other users."), + 'members' => array('aclmanagement') +); -// Folder sharing preferences +// ACL preference management screen +$_prefs['aclmanagement'] = array( + 'type' => 'special' +); // folder sharing options $_prefs['acl'] = array( - 'value' => '', // set 'locked' => true to disable folder sharing - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); + -// End folder sharing preferences +// *** Login Tasks Preferences *** + +$prefGroups['logintasks'] = array( + 'column' => _("General Options"), + 'label' => _("Login Tasks"), + 'desc' => sprintf(_("Configure tasks to run upon logon to %s."), $GLOBALS['registry']->get('name')), + 'members' => array( + 'delete_attachments_monthly', 'delete_attachments_monthly_keep', + 'initialpageselect', 'rename_sentmail_monthly', + 'delete_sentmail_monthly', 'delete_sentmail_monthly_keep', + 'purge_sentmail', 'purge_sentmail_interval', 'purge_sentmail_keep', + 'purge_trash', 'purge_trash_interval', 'purge_trash_keep', + 'purge_spam', 'purge_spam_interval', 'purge_spam_keep' + ) +); -// Login Tasks preferences +// purge old attachments every month? +$_prefs['delete_attachments_monthly'] = array( + 'value' => 1, + 'type' => 'checkbox', + 'desc' => _("Delete old linked attachments at beginning of month?"), + 'help' => 'prefs-delete_attachments_monthly' +); + +// how many old months of attachments to keep? +$_prefs['delete_attachments_monthly_keep'] = array( + 'value' => 6, + 'type' => 'number', + 'desc' => _("Number of months to keep old linked attachments if deleting monthly."), + 'help' => 'prefs-delete_attachments_monthly_keep' +); // select widget for the initial_page preference -$_prefs['initialpageselect'] = array('type' => 'special'); +$_prefs['initialpageselect'] = array( + 'type' => 'special' +); // the page to display. Either a filename like 'folders.php' // or a mailbox name. $_prefs['initial_page'] = array( - 'value' => 'INBOX', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 'INBOX' +); // rename sent-mail folder every month? $_prefs['rename_sentmail_monthly'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Rename sent-mail folder at beginning of month?"), - 'help' => 'prefs-rename_sentmail_monthly'); + 'help' => 'prefs-rename_sentmail_monthly' +); // delete sent-mail folders every month? $_prefs['delete_sentmail_monthly'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Delete old sent-mail folders at beginning of month?"), - 'help' => 'prefs-delete_sentmail_monthly'); + 'help' => 'prefs-delete_sentmail_monthly' +); // how many old sent-mail folders to keep every month? $_prefs['delete_sentmail_monthly_keep'] = array( 'value' => 12, - 'locked' => false, - 'shared' => false, 'type' => 'number', 'desc' => _("Number of old sent-mail folders to keep if deleting monthly."), - 'help' => 'prefs-delete_sentmail_monthly_keep'); + 'help' => 'prefs-delete_sentmail_monthly_keep' +); // purge sent-mail folder? $_prefs['purge_sentmail'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Purge old messages in the sent-mail folder(s)?"), - 'help' => 'prefs-purge_sentmail'); + 'help' => 'prefs-purge_sentmail' +); // how often to purge the Sent-Mail folder? $_prefs['purge_sentmail_interval'] = array( 'value' => Horde_LoginTasks::MONTHLY, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => Horde_LoginTasks::getLabels(), 'desc' => _("Purge sent-mail how often:"), - 'help' => 'prefs-purge_sentmail_interval'); + 'help' => 'prefs-purge_sentmail_interval' +); // when purging sent-mail folder, purge messages older than how many days? $_prefs['purge_sentmail_keep'] = array( 'value' => 30, - 'locked' => false, - 'shared' => false, 'type' => 'number', 'desc' => _("Purge messages in sent-mail folder(s) older than this amount of days."), - 'help' => 'prefs-purge_sentmail_keep'); + 'help' => 'prefs-purge_sentmail_keep' +); -// purge old attachments every month? -$_prefs['delete_attachments_monthly'] = array( - 'value' => 1, - 'locked' => false, - 'shared' => false, +// purge Trash folder? +$_prefs['purge_trash'] = array( + 'value' => 0, 'type' => 'checkbox', - 'desc' => _("Delete old linked attachments at beginning of month?"), - 'help' => 'prefs-delete_attachments_monthly'); + 'desc' => _("Purge old messages in the Trash folder?"), + 'help' => 'prefs-purge_trash' +); -// how many old months of attachments to keep? -$_prefs['delete_attachments_monthly_keep'] = array( - 'value' => 6, - 'locked' => false, - 'shared' => false, +// how often to purge the Trash folder? +$_prefs['purge_trash_interval'] = array( + 'value' => Horde_LoginTasks::MONTHLY, + 'type' => 'enum', + 'enum' => Horde_LoginTasks::getLabels(), + 'desc' => _("Purge Trash how often:"), + 'help' => 'prefs-purge_trash_interval' +); + +// when purging Trash folder, purge messages older than how many days? +$_prefs['purge_trash_keep'] = array( + 'value' => 30, 'type' => 'number', - 'desc' => _("Number of months to keep old linked attachments if deleting monthly."), - 'help' => 'prefs-delete_attachments_monthly_keep'); + 'desc' => _("Purge messages in Trash folder older than this amount of days."), + 'help' => 'prefs-purge_trash_keep' +); // purge Spam folder? $_prefs['purge_spam'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Purge old messages in the Spam folder?"), - 'help' => 'prefs-purge_spam'); + 'help' => 'prefs-purge_spam' +); // how often to purge the Spam folder? $_prefs['purge_spam_interval'] = array( 'value' => Horde_LoginTasks::MONTHLY, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => Horde_LoginTasks::getLabels(), 'desc' => _("Purge Spam how often:"), - 'help' => 'prefs-purge_spam_interval'); + 'help' => 'prefs-purge_spam_interval' +); // when purging Spam folder, purge messages older than how many days? $_prefs['purge_spam_keep'] = array( 'value' => 30, - 'locked' => false, - 'shared' => false, 'type' => 'number', 'desc' => _("Purge messages in Spam folder older than this amount of days."), - 'help' => 'prefs-purge_spam_keep'); + 'help' => 'prefs-purge_spam_keep' +); -// purge Trash folder? -$_prefs['purge_trash'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'checkbox', - 'desc' => _("Purge old messages in the Trash folder?"), - 'help' => 'prefs-purge_trash'); -// how often to purge the Trash folder? -$_prefs['purge_trash_interval'] = array( - 'value' => Horde_LoginTasks::MONTHLY, - 'locked' => false, - 'shared' => false, - 'type' => 'enum', - 'enum' => Horde_LoginTasks::getLabels(), - 'desc' => _("Purge Trash how often:"), - 'help' => 'prefs-purge_trash_interval'); - -// when purging Trash folder, purge messages older than how many days? -$_prefs['purge_trash_keep'] = array( - 'value' => 30, - 'locked' => false, - 'shared' => false, - 'type' => 'number', - 'desc' => _("Purge messages in Trash folder older than this amount of days."), - 'help' => 'prefs-purge_trash_keep'); - -// End Login Tasks preferences +// *** Additional Accounts Preferences *** -// Accounts preferences +$prefGroups['accounts'] = array( + 'column' => _("General Options"), + 'label' => _("Additional Accounts"), + 'desc' => _("Configure additional mail accounts to display."), + 'members' => array('accountsmanagement') +); // UI for flag management. $_prefs['accountsmanagement'] = array( 'type' => 'special' ); +// Internal accounts storage value $_prefs['accounts'] = array( - 'value' => json_encode(array()), - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + // 'value' = json_encode(array()) + 'value' => '[]' +); -// End Accounts preferences -// Message Composition preferences +// *** Compose Preferences *** + +$prefGroups['compose'] = array( + 'column' => _("Message Options"), + 'label' => _("Message Composition"), + 'desc' => _("Configure how you send mail."), + 'members' => array( + 'stationery_link', 'mailto_handler', 'compose_cc', 'compose_bcc', + 'compose_spellcheck', 'compose_confirm', 'set_priority', + 'compose_popup', 'compose_html', 'mail_domain', 'compose_cursor', + 'sending_charset', 'encryptselect', 'save_attachments', + 'disposition_request_read' + ) +); // Link to the stationery preferences. $_prefs['stationery_link'] = array( - 'type' => 'link', - 'url' => 'stationery.php', - 'desc' => _("To the stationery and form responses.")); - -$_prefs['stationery'] = array( - // value = serialize(array()) - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'prefslink', + 'group' => 'stationery', + 'img' => 'compose.png', + 'desc' => _("Edit stationery and form responses.") +); // Link to add a Firefox 3 mailto: handler $_prefs['mailto_handler'] = array( 'type' => 'link', + 'img' => 'compose.png', 'xurl' => 'javascript:if(typeof navigator.registerProtocolHandler==\'undefined\')alert(\'' . addslashes(_("Your browser does not support this feature.")) . '\');else navigator.registerProtocolHandler(\'mailto\',\'' . Horde::applicationUrl('compose.php', true)->setRaw(true)->add(array('actionID' => 'mailto_link', 'to' => '')) . '%s\',\'' . $GLOBALS['registry']->get('name') . '\');', - 'desc' => sprintf(_("Click here to open all mailto: links in %s."), $GLOBALS['registry']->get('name'))); + 'desc' => sprintf(_("Click here to open all mailto: links in %s."), $GLOBALS['registry']->get('name')) +); // Show Cc: field? $_prefs['compose_cc'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Show the Cc: header field when composing mail?") ); @@ -606,8 +417,6 @@ $_prefs['compose_cc'] = array( // Show Bcc: field? $_prefs['compose_bcc'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Show the Bcc: header field when composing mail?") ); @@ -615,33 +424,29 @@ $_prefs['compose_bcc'] = array( // Check spelling before sending the message? $_prefs['compose_spellcheck'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Check spelling before sending a message?")); + 'desc' => _("Check spelling before sending a message?") +); // confirm successful sending of messages? $_prefs['compose_confirm'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Display confirmation after sending a message?")); + 'desc' => _("Display confirmation after sending a message?") +); // allow the user to add a priority header when composing messages? $_prefs['set_priority'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Set a priority header when composing messages?")); + 'desc' => _("Set a priority header when composing messages?") +); // compose in a separate window? $_prefs['compose_popup'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Compose messages in a separate window?") ); @@ -650,70 +455,51 @@ $_prefs['compose_popup'] = array( // default? $_prefs['compose_html'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Compose messages with an HTML editor by default?") ); -// The list of buttons to show in CKeditor -// See http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Toolbar for -// details on configuration -$_prefs['ckeditor_buttons'] = array( - 'value' => "[['Source','Maximize','-','Templates'],['Cut','Copy','Paste','PasteText','PasteFromWord'],['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],'/',['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],['Link','Unlink'],['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar'],'/',['Styles','Format','Font','FontSize'],['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],['TextColor','BGColor']]", - // Use the following line for a very basic set of buttons: - // 'value' => "['Bold','Italic','-','NumberedList','BulletedList','-','Link','Unlink']", - // Locked by default - 'locked' => true, - 'shared' => false, - 'type' => 'textarea', - 'desc' => _("The buttons to show when using the HTML editor.") -); - // default outgoing mail domain and address completion $_prefs['mail_domain'] = array( 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'text', - 'desc' => _("When sending mail or expanding addresses, what domain should we append to unqualified addresses (email addresses without \"@\")?")); + 'desc' => _("When sending mail or expanding addresses, what domain should we append to unqualified addresses (email addresses without \"@\")?") +); // Where should the cursor be located in the compose text area by default? $_prefs['compose_cursor'] = array( 'value' => 'top', - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array('top' => _("Top"), - 'bottom' => _("Bottom"), - 'sig' => _("Before Signature")), + 'enum' => array( + 'top' => _("Top"), + 'bottom' => _("Bottom"), + 'sig' => _("Before Signature") + ), 'desc' => _("Where should the cursor be located in the compose text area by default?") ); // Select widget for the possible charsets $_prefs['sending_charset'] = array( 'value' => '', - 'locked' => false, 'shared' => true, 'type' => 'enum', 'enum' => array_merge(array('' => _("Default")), Horde_Nls::$config['encodings']), - 'desc' => _("Your default charset for sending messages:")); + 'desc' => _("Your default charset for sending messages:") +); // Select widget for the 'default_encrypt' preference -$_prefs['encryptselect'] = array('type' => 'special'); +$_prefs['encryptselect'] = array( + 'type' => 'special' +); // The default encryption method to use when sending messages $_prefs['default_encrypt'] = array( - 'value' => IMP::ENCRYPT_NONE, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => IMP::ENCRYPT_NONE +); // Save attachments when saving in sent-mail folder? $_prefs['save_attachments'] = array( 'value' => 'prompt_no', - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 'always' => _("Always save attachments"), @@ -722,66 +508,109 @@ $_prefs['save_attachments'] = array( 'never' => _("Never save attachments") ), 'desc' => _("When saving sent-mail, should we save attachment data?"), - 'help' => 'prefs-save_attachments'); + 'help' => 'prefs-save_attachments' +); // Disposition Notification Preferences $_prefs['disposition_request_read'] = array( 'value' => 'ask', - 'locked' => false, - 'shared' => false, 'type' => 'enum', - 'enum' => array('never' => _("Never"), - 'ask' => _("Ask"), - 'always' => _("Always")), + 'enum' => array( + 'never' => _("Never"), + 'ask' => _("Ask"), + 'always' => _("Always") + ), 'desc' => _("Request read receipts?"), 'help' => 'prefs-disposition_request_read' ); -// End Message Composition preferences +// The list of buttons to show in CKeditor +// See http://docs.cksource.com/CKEditor_3.x/Developers_Guide/Toolbar for +// details on configuration +$_prefs['ckeditor_buttons'] = array( + 'value' => "[['Source','Maximize','-','Templates'],['Cut','Copy','Paste','PasteText','PasteFromWord'],['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],'/',['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],['Link','Unlink'],['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar'],'/',['Styles','Format','Font','FontSize'],['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],['TextColor','BGColor']]", + // Use the following line for a very basic set of buttons: + // 'value' => "['Bold','Italic','-','NumberedList','BulletedList','-','Link','Unlink']", +); + + + +// *** Stationery Preferences *** + +$prefGroups['stationery'] = array( + 'column' => _("Message Options"), + 'label' => _("Stationery"), + 'desc' => _("Edit stationery and form responses."), + 'members' => array('stationerymanagement') +); + +// Stationery configuration widget +$_prefs['stationerymanagement'] = array( + 'type' => 'special' +); + +// Internal stationery storage value +$_prefs['stationery'] = array( + // value = serialize(array()) + 'value' => 'a:0:{}' +); -// Message Replies preferences + +// *** Compose Reply Preferences *** + +$prefGroups['reply'] = array( + 'column' => _("Message Options"), + 'label' => _("Message Replies"), + 'desc' => _("Configure how you reply to mail."), + 'members' => array( + 'reply_quote', 'reply_format', 'reply_headers', 'attrib_text' + ) +); // Should the original message be included? $_prefs['reply_quote'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Include original message in a reply?")); + 'desc' => _("Include original message in a reply?") +); // When replying to a message, should we use the same format as the // original message? $_prefs['reply_format'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("When replying to a message, should we use the same format as the original message?")); + 'desc' => _("When replying to a message, should we use the same format as the original message?") +); // Reply to header summary - leave a brief summary of the header inside // the message. $_prefs['reply_headers'] = array( 'desc' => _("Include a brief summary of the header in a reply?"), 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'checkbox'); + 'type' => 'checkbox' +); // How should we attribute quoted lines in a reply $_prefs['attrib_text'] = array( 'value' => _("Quoting %f:"), - 'locked' => false, - 'shared' => false, 'type' => 'text', 'desc' => _("How to attribute quoted lines in a reply"), - 'help' => 'prefs-attrib_text'); + 'help' => 'prefs-attrib_text' +); -// End Message Replies preferences -// Message Forwards preferences +// *** Compose Forward Preferences *** + +$prefGroups['forward'] = array( + 'column' => _("Message Options"), + 'label' => _("Message Forwards"), + 'desc' => _("Configure how you forward mail."), + 'members' => array('forward_default', 'forward_format') +); // Should the body text of the original message be included? // If this preference is locked, the user will not be able to select the @@ -790,14 +619,14 @@ $_prefs['forward_default'] = array( 'value' => 'attach', // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'enum', 'enum' => array( 'attach' => _("As attachment"), 'body' => _("In the body text"), 'both' => _("As both body text and an attachment") ), - 'desc' => _("How should messages be forwarded by default?")); + 'desc' => _("How should messages be forwarded by default?") +); // When forwarding a message, should we use the same format as the // original message (for the body text)? @@ -805,37 +634,43 @@ $_prefs['forward_format'] = array( 'value' => 0, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("When forwarding a message in the body text, should we use the same format as the original message?")); + 'desc' => _("When forwarding a message in the body text, should we use the same format as the original message?") +); -// End Message Forwards preferences -// Message Drafts preferences +// *** Message Drafts Preferences *** + +$prefGroups['drafts'] = array( + 'column' => _("Message Options"), + 'label' => _("Message Drafts"), + 'desc' => _("Configure how to deal with message drafts."), + 'members' => array( + 'draftsselect', 'close_draft', 'unseen_drafts', 'auto_save_drafts', + 'auto_delete_drafts' + ) +); // closing window after saving a draft? $_prefs['close_draft'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Should the compose window be closed after saving a draft?")); + 'desc' => _("Should the compose window be closed after saving a draft?") +); // save drafts as seen or unseen $_prefs['unseen_drafts'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Save drafts as unseen?")); + 'desc' => _("Save drafts as unseen?") +); // auto-save drafts? value is in minutes, 0 == don't save. $_prefs['auto_save_drafts'] = array( 'value' => 5, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("No"), @@ -848,73 +683,68 @@ $_prefs['auto_save_drafts'] = array( // delete draft after resume & send? $_prefs['auto_delete_drafts'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Automatically delete draft after successfully resuming and sending message?") ); -// End Message Drafts preferences -// Message Viewing preferences +// *** Message Viewing Preferences *** + +$prefGroups['viewing'] = array( + 'column' => _("Message Options"), + 'label' => _("Message Viewing"), + 'desc' => _("Configure how messages are displayed."), + 'members' => array( + 'filtering', 'strip_attachments', 'html_image_replacement', + 'html_image_addrbook', 'highlight_text', 'highlight_simple_markup', + 'show_quoteblocks', 'dim_signature', 'emoticons', 'parts_display', + 'mail_hdr', 'default_msg_charset', 'disposition_send_mdn' + ) +); // filter message content? $_prefs['filtering'] = array( 'value' => 0, 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Filter message content for profanity?")); + 'desc' => _("Filter message content for unwanted text (e.g. profanity)?") +); // Should we display an icon to strip attachments? $_prefs['strip_attachments'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Show an icon to allow stripping of attachments from messages?")); // What should we do with spam messages after reporting them? $_prefs['delete_spam_after_report'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("Nothing"), - 1 => _("Delete message") + 1 => _("Delete message"), + 2 => _("Move to spam folder") ), 'desc' => _("What should we do with spam messages after they have been reported as spam?"), 'help' => 'prefs-delete_spam_after_report' ); -if (!$is_pop3) { - $_prefs['delete_spam_after_report']['enum'][2] = - _("Move to spam folder"); -} // What should we do with spam messages after reporting them as innocent? $_prefs['move_ham_after_report'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( - 0 => _("Nothing") + 0 => _("Nothing"), + 1 => _("Move to Inbox") ), 'desc' => _("What should we do with spam messages after they have been reported as innocent?"), 'help' => 'prefs-move_ham_after_report' ); -if (!$is_pop3) { - $_prefs['move_ham_after_report']['enum'][1] = - _("Move to Inbox"); -} // Replace image tags in inline viewed HTML messages with blank images? $_prefs['html_image_replacement'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Block images in inline viewed HTML messages unless they are specifically requested?"), 'help' => 'prefs-html_image_replacement' @@ -924,8 +754,6 @@ $_prefs['html_image_replacement'] = array( // sender is in the user's addressbook? $_prefs['html_image_addrbook'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Automatically show images in inline viewed HTML messages when the sender is in my address book?"), 'help' => 'prefs-html_image_addrbook' @@ -936,24 +764,22 @@ $_prefs['highlight_text'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Mark different levels of quoting with different colors?")); + 'desc' => _("Mark different levels of quoting with different colors?") +); // should we try to mark simple markup with html tags? $_prefs['highlight_simple_markup'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Mark simple markup?")); + 'desc' => _("Mark simple markup?") +); // should we show large blocks of quoted text or hide them? $_prefs['show_quoteblocks'] = array( 'value' => 'thread', - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 'shown' => _("Shown"), @@ -962,37 +788,36 @@ $_prefs['show_quoteblocks'] = array( 'listthread' => _("Hidden in Thread View and List Messages"), 'hidden' => _("Hidden") ), - 'desc' => _("Should large blocks of quoted text be shown or hidden by default? It can be toggled easily whichever you choose.")); + 'desc' => _("Should large blocks of quoted text be shown or hidden by default? It can be toggled easily whichever you choose.") +); // should we dim signatures? $_prefs['dim_signature'] = array( 'value' => 0, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Dim signatures?")); + 'desc' => _("Dim signatures?") +); // Convert textual emoticons into graphical ones? $_prefs['emoticons'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Convert textual emoticons into graphical ones?")); + 'desc' => _("Convert textual emoticons into graphical ones?") +); // how do we display message parts in the summary? $_prefs['parts_display'] = array( 'value' => 'atc', - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 'all' => _("Show all parts"), 'atc' => _("Show all attachments"), 'none' => _("Do not show parts") ), - 'desc' => _("Which message parts do you want to display in the summary?")); + 'desc' => _("Which message parts do you want to display in the summary?") +); // Display custom headers (configured via the identity screen) when viewing // messages? @@ -1000,10 +825,9 @@ $_prefs['mail_hdr'] = array( // Value is a list of headers to display, separated by "\n" // e.g.: "Message-ID\nX-Spam-Level" 'value' => '', - 'locked' => false, - 'shared' => false, 'type' => 'textarea', - 'desc' => _("Additional headers to display when viewing: (enter each header on a new line)")); + 'desc' => _("Additional headers to display when viewing: (enter each header on a new line)") +); // default message character set $_prefs['default_msg_charset'] = array( @@ -1012,20 +836,19 @@ $_prefs['default_msg_charset'] = array( : (isset($GLOBALS['nls']['charsets'][$GLOBALS['language']]) ? $GLOBALS['nls']['charsets'][$GLOBALS['language']] : ''), - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array_merge( array('' => _("Default (US-ASCII)")), Horde_Nls::$config['encodings'] ), 'desc' => _("The default charset for messages with no charset information:"), - 'help' => 'prefs-default_msg_charset'); + 'help' => 'prefs-default_msg_charset' +); +// Send read receipts? $_prefs['disposition_send_mdn'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("Never send read receipt"), @@ -1036,75 +859,81 @@ $_prefs['disposition_send_mdn'] = array( 'help' => 'prefs-disposition_send_mdn' ); -// End Message Viewing preferences -// Deleting and Moving Messages preferences +// *** Delete/Move Messages Preferences *** + +$prefGroups['delmove'] = array( + 'column' => _("Message Options"), + 'label' => _("Deleting and Moving Messages"), + 'desc' => _("Set preferences for what happens when you move and delete messages."), + 'members' => array( + 'mailbox_return', 'delete_spam_after_report', 'move_ham_after_report', + 'empty_spam_menu', 'use_trash', 'trashselect', 'use_vtrash', + 'empty_trash_menu' + ) +); // should we return to the mailbox listing after deleting a message? $_prefs['mailbox_return'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Return to the mailbox listing after deleting, moving, or copying a message?")); + 'desc' => _("Return to the mailbox listing after deleting, moving, or copying a message?") +); // should we move messages to a trash folder instead of just marking // them as deleted? $_prefs['use_trash'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("When deleting messages, move them to your Trash folder instead of marking them as deleted?")); + 'desc' => _("When deleting messages, move them to your Trash folder instead of marking them as deleted?") +); // use Virtual Trash folder $_prefs['use_vtrash'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 0 +); // virtual trash folder identifier $_prefs['vtrash_id'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); // display the 'Empty Trash' link in the menubar? $_prefs['empty_trash_menu'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Display the \"Empty Trash\" link in the menubar?")); + 'desc' => _("Display the \"Empty Trash\" link in the menubar?") +); // display the 'Empty Spam' link in the menubar? $_prefs['empty_spam_menu'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Display the \"Empty Spam\" link in the menubar?")); + 'desc' => _("Display the \"Empty Spam\" link in the menubar?") +); // hide deleted $_prefs['delhide'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 0 +); + -// End Deleting and Moving Messages preferences +// *** New Mail Notification Preferences *** -// New Mail preferences +$prefGroups['newmail'] = array( + 'column' => _("Message Options"), + 'label' => _("New Mail"), + 'desc' => _("Control when new mail will be checked for, and whether or not to notify you when it arrives."), + 'members' => array( + 'refresh_time', 'nav_poll_all', 'nav_popup', 'soundselect' + ) +); // time before reloading the navigator or mailbox page $_prefs['refresh_time'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("Never"), @@ -1120,27 +949,30 @@ $_prefs['refresh_time'] = array( // javascript popup if there's new mail? $_prefs['nav_popup'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Display pop-up notification of new mail?"), ); // play a sound on new mail? if so, which one? $_prefs['nav_audio'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit', + 'value' => '' ); // sound selection widget -$_prefs['soundselect'] = array('type' => 'special'); +$_prefs['soundselect'] = array( + 'type' => 'special' +); + -// End New Mail preferences +// *** IMAP Flag Preferences *** -// IMAP Flag preferences +$prefGroups['flags'] = array( + 'column' => _("Message Options"), + 'label' => _("Message Flags"), + 'desc' => _("Configure flag highlighting."), + 'members' => array('flagmanagement') +); // UI for flag management. $_prefs['flagmanagement'] = array( @@ -1271,28 +1103,31 @@ $_prefs['msgflags'] = array( // Pursuant to RFC, this flag SHOULD NOT be changed by the user 't' => 'imap' ), - )), - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + )) ); // The default color to use for flags that don't require row highlighting. $_prefs['msgflags_color'] = array( - 'value' => '#ffffff', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '#ffffff' +); + -// End IMAP Flag preferences -// Display Options preferences +// *** Mailbox Display Preferences *** + +$prefGroups['mboxdisplay'] = array( + 'column' => _("Other Options"), + 'label' => _("Mailbox Display Options"), + 'desc' => _("Change display options such as how many messages you see on each page and how messages are sorted."), + 'members' => array( + 'mailbox_start', 'sortby', 'sortdir', 'max_msgs', 'from_link', + 'time_format', 'atc_flag' + ) +); // Where to start when opening mailbox? $_prefs['mailbox_start'] = array( 'value' => IMP::MAILBOX_START_FIRSTUNSEEN, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( IMP::MAILBOX_START_FIRSTUNSEEN => _("First (oldest) Unseen Message"), @@ -1301,7 +1136,8 @@ $_prefs['mailbox_start'] = array( IMP::MAILBOX_START_LASTPAGE => _("Last Page") ), 'desc' => _("When opening a mailbox for the first time, where do you want to start?"), - 'help' => 'prefs-mailbox_start'); + 'help' => 'prefs-mailbox_start' +); // default sorting column $_prefs['sortby'] = array( @@ -1309,8 +1145,6 @@ $_prefs['sortby'] = array( // sort that can be done without parsing message headers. It sorts // messages by the order they arrived within the mailbox. 'value' => Horde_Imap_Client::SORT_SEQUENCE, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( Horde_Imap_Client::SORT_SEQUENCE => _("NONE"), @@ -1321,27 +1155,25 @@ $_prefs['sortby'] = array( Horde_Imap_Client::SORT_SIZE => _("Message Size"), Horde_Imap_Client::SORT_THREAD => _("Thread") ), - 'desc' => _("Default sorting criteria:")); + 'desc' => _("Default sorting criteria:") +); // default sorting direction $_prefs['sortdir'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("Ascending"), 1 => _("Descending") ), - 'desc' => _("Default sorting direction:")); + 'desc' => _("Default sorting direction:") +); // sort prefs for individual folders $_prefs['sortpref'] = array( // value = serialize(array()) - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 'a:0:{}' +); // default sorting criteria for the date column $_prefs['sortdate'] = array( @@ -1351,7 +1183,6 @@ $_prefs['sortdate'] = array( 'value' => Horde_Imap_Client::SORT_ARRIVAL, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'enum', 'enum' => array( Horde_Imap_Client::SORT_ARRIVAL => _("Arrival time on server"), @@ -1363,41 +1194,25 @@ $_prefs['sortdate'] = array( // mailbox constraints $_prefs['max_msgs'] = array( 'value' => 30, - 'locked' => false, - 'shared' => false, 'type' => 'number', - 'desc' => _("Messages per page in the mailbox view.")); + 'desc' => _("Messages per page in the mailbox view.") +); // How the from field should be displayed on the mailbox screen $_prefs['from_link'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("Clicking on the address will compose a new message to the sender"), 1 => _("Clicking on the address will open the message to be read"), 2 => _("Do not generate a link in the From: column") ), - 'desc' => _("The From: column of the message should be linked:")); - -// Display attachment information in mailbox list. -// Disabled by default, and not shown to user, because this display requires -// substantial overhead to parse the message structures of all message in -// the mailbox list at view time. -$_prefs['atc_flag'] = array( - 'value' => 0, - // Locked by default - 'locked' => true, - 'shared' => false, - 'type' => 'checkbox', - 'desc' => _("Display attachment information about a message in the mailbox listing?")); + 'desc' => _("The From: column of the message should be linked:") +); // Time format for messages dated today $_prefs['time_format'] = array( 'value' => '%X', - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( '%X' => strftime('%X'), @@ -1406,13 +1221,37 @@ $_prefs['time_format'] = array( '%H:%M' => strftime('%H:%M'), '%I:%M%p' => strftime('%I:%M%p'), ), - 'desc' => _("Format of message dates in the mailbox view for messages dated today")); + 'desc' => _("Format of message dates in the mailbox view for messages dated today") +); + +// Display attachment information in mailbox list. +// Disabled by default, and not shown to user, because this display requires +// substantial overhead to parse the message structures of all message in +// the mailbox list at view time. +$_prefs['atc_flag'] = array( + 'value' => 0, + // Locked by default + 'locked' => true, + 'type' => 'checkbox', + 'desc' => _("Display attachment information about a message in the mailbox listing?") +); + + + +// *** Folder Display Preferences *** + +$prefGroups['folderdisplay'] = array( + 'column' => _("Other Options"), + 'label' => _("Folder Display Options"), + 'desc' => _("Change folder navigation display options."), + 'members' => array( + 'nav_expanded', 'tree_view', 'nav_expanded_sidebar', 'nav_poll_all' + ) +); // expand folder tree by default $_prefs['nav_expanded'] = array( 'value' => 2, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("No"), @@ -1424,8 +1263,6 @@ $_prefs['nav_expanded'] = array( // folder tree view style $_prefs['tree_view'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("Combine all namespaces"), @@ -1437,115 +1274,148 @@ $_prefs['tree_view'] = array( // expand folder tree by default in sidebar $_prefs['nav_expanded_sidebar'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 0 => _("No"), 1 => _("Yes"), 2 => _("Current expanded status in the folders view") ), - 'desc' => _("Expand the entire folder tree by default in the sidebar?")); + 'desc' => _("Expand the entire folder tree by default in the sidebar?") +); // poll all folders for new mail? $_prefs['nav_poll_all'] = array( 'value' => 0, - 'locked' => $is_pop3, - 'shared' => false, + 'locked' => false, 'type' => 'checkbox', - 'desc' => _("Poll all folders for new mail?")); + 'desc' => _("Poll all folders for new mail?") +); // list of folders to expand by default $_prefs['expanded_folders'] = array( // value = serialize(array()) - 'value' => 'a:0:{}', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 'a:0:{}' +); // list of folders to poll for new mail $_prefs['nav_poll'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); + + + +// *** Filter Preferences *** + +$prefGroups['filters'] = array( + 'column' => _("Other Options"), + 'label' => _("Filters"), + 'desc' => _("Create filtering rules to organize your incoming mail, sort it into folders, and delete spam."), + 'members' => array( + 'filters_link', 'filters_blacklist_link', 'filters_whitelist_link', + 'filter_on_login', 'filter_on_display', 'filter_any_mailbox', + 'filter_menuitem' + ) +); -// End Display Options preferences +$_prefs['filters_link'] = array( + 'type' => 'link', + 'url' => $GLOBALS['registry']->link('mail/showFilters'), + 'img' => 'filters.png', + 'desc' => _("Edit your Filter Rules"), + 'help' => 'filter-edit-rules' +); +$_prefs['filters_blacklist_link'] = array( + 'type' => 'link', + 'img' => 'filters.png', + 'url' => $GLOBALS['registry']->link('mail/showBlacklist'), + 'desc' => _("Edit your Blacklist"), + 'help' => 'filter-edit-blacklist' +); -// Filter preferences +$_prefs['filters_whitelist_link'] = array( + 'type' => 'link', + 'img' => 'filters.png', + 'url' => $GLOBALS['registry']->link('mail/showWhitelist'), + 'desc' => _("Edit your Whitelist"), + 'help' => 'filter-edit-whitelist' +); // run filters on login? $_prefs['filter_on_login'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Apply filter rules upon logging on?"), + 'help' => 'filter-on-login' +); // run filters with INBOX display? $_prefs['filter_on_display'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Apply filter rules whenever Inbox is displayed?"), + 'help' => 'filter-on-display' +); -// run filters when sidebar updates? -$_prefs['filter_on_sidebar'] = array( +// Allow filters to be applied to any mailbox? +$_prefs['filter_any_mailbox'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Allow filter rules to be applied in any mailbox?"), + 'help' => 'filter-any-mailbox' +); // show filter icon on the menubar? $_prefs['filter_menuitem'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Show the filter icon on the menubar?"), + 'help' => 'filter-menuitem' +); -// Allow filters to be applied to any mailbox? -$_prefs['filter_any_mailbox'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); -// End Filter preferences +// *** Addressbook Preferences *** -// Address book preferences +$prefGroups['addressbooks'] = array( + 'column' => _("Other Options"), + 'label' => _("Address Books"), + 'desc' => _("Select address book sources for adding and searching for addresses."), + 'members' => array( + 'save_recipients', 'display_contact', 'sourceselect', 'add_source' + ) +); // Should recipients of outgoing messages be added automatically to // the address book? $_prefs['save_recipients'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', - 'desc' => _("Save recipients automatically to the default address book?")); + 'desc' => _("Save recipients automatically to the default address book?") +); // By default, display all contacts in the address book when loading // the contacts screen. If your default address book is large and // slow to display, you may want to disable and lock this option. $_prefs['display_contact'] = array( 'value' => 1, - 'locked' => false, 'shared' => true, 'type' => 'checkbox', - 'desc' => _("List all contacts when loading the contacts screen? (if disabled, you will only see contacts that you search for explicitly)")); + 'desc' => _("List all contacts when loading the contacts screen? (if disabled, you will only see contacts that you search for explicitly)") +); // address book selection widget -$_prefs['sourceselect'] = array('type' => 'special'); +$_prefs['sourceselect'] = array( + 'type' => 'special' +); // address book(s) to use when expanding addresses // You can provide default values this way (note the \t and the double quotes): // 'value' => "source_one\tsource_two" // refer to turba/config/sources.php for possible source values $_prefs['search_sources'] = array( - 'value' => "", - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => "" +); // field(s) to use when expanding addresses // This depends on the search_sources preference if you want to provide @@ -1555,126 +1425,175 @@ $_prefs['search_sources'] = array( // 'field_three' in source_two. // refer to turba/config/sources.php for possible source and field values $_prefs['search_fields'] = array( - 'value' => "", - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => "" +); // address book to use for adding addresses // put $cfgSources array element name in the value field. // Setting value to localsql would allow you to add contacts to MySQL database // See turba/config/sources.php for more info $_prefs['add_source'] = array( - 'value' => '', // 'value' => 'localsql', - 'locked' => false, - 'shared' => true, - 'type' => 'implicit' + 'value' => '', + 'shared' => true + 'type' => 'enum', + 'desc' => _("Choose the address book to use when adding addresses.") ); -// End Address book preferences -// Event preferences +// *** Event Request Preferences *** + +$prefGroups['events'] = array( + 'column' => _("Other Options"), + 'label' => _("Event Requests"), + 'desc' => _("Configure how event or meeting requests should be handled."), + 'members' => array('conflict_interval') +); // Amount of minutes to consider a event as a non-conflicting one in iTip $_prefs['conflict_interval'] = array( 'value' => 30, - 'locked' => false, - 'shared' => false, 'type' => 'number', 'desc' => _("Minutes needed to consider a event as a non-conflicting one in iTip") ); -// End Calendar preferences -// PGP options +// *** PGP Preferences *** + +$prefGroups['pgp'] = array( + 'column' => _("Other Options"), + 'label' => _("PGP Options"), + 'desc' => sprintf(_("Control PGP support for %s."), $GLOBALS['registry']->get('name')), + 'members' => array( + 'use_pgp', 'use_pgp_text', 'pgp_attach_pubkey', 'pgp_scan_body', + 'pgp_verify', 'pgppublickey', 'pgpprivatekey' + ) +); // Activate PGP support? $_prefs['use_pgp'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit' + 'type' => 'checkbox', + 'desc' => _("Enable PGP functionality?"), + 'help' => 'pgp-overview' +); + +$_prefs['use_pgp_text'] = array( + 'value' => '
' . _("PGP support requires popup windows to be used. If your browser is currently set to disable popup windows, you must change this setting or else the PGP features will not work correctly.") . '
', + 'type' => 'rawhtml' ); -// You should not manually change the rest of the PGP entries $_prefs['pgp_attach_pubkey'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Should your PGP public key to be attached to your messages by default?"), + 'help' => 'pgp-option-attach-pubkey' +); $_prefs['pgp_scan_body'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Should the body of text/plain messages be scanned for PGP data?"), + 'help' => 'pgp-option-scan-body' +); $_prefs['pgp_verify'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Should PGP signed messages automatically be verified when viewed?"), + 'help' => 'pgp-option-verify' +); -$_prefs['pgp_private_key'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); +$_prefs['pgppublickey'] = array( + 'type' => 'special' +); $_prefs['pgp_public_key'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); + +$_prefs['pgpprivatekey'] = array( + 'type' => 'special' +); + +$_prefs['pgp_private_key'] = array( + 'value' => '' +); + + -// End PGP Options +// *** S/MIME Preferences *** -// S/MIME options +$prefGroups['smime'] = array( + 'column' => _("Other Options"), + 'label' => _("S/MIME Options"), + 'desc' => sprintf(_("Control S/MIME support for %s."), $GLOBALS['registry']->get('name')), + 'members' => array( + 'use_smime', 'use_smime_text', 'smime_verify', 'smimepublickey', + 'smimeprivatekey' + ) +); // Activate S/MIME support? $_prefs['use_smime'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Enable S/MIME functionality?"), + 'help' => 'smime-overview' +); + +$_prefs['use_smime_text'] = array( + 'value' => '
' . _("S/MIME support requires popup windows to be used. If your browser is currently set to disable popup windows, you must change this setting or else the S/MIME features will not work correctly.") . '
', + 'type' => 'rawhtml' +); -// You should not manually change the rest of the S/MIME entries $_prefs['smime_verify'] = array( 'value' => 1, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'type' => 'checkbox', + 'desc' => _("Should S/MIME signed messages automatically be verified when viewed?"), + 'help' => 'smime-option-verify' +); -$_prefs['smime_private_key'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); +// S/MIME public key management widget +$_prefs['smimepublickey'] = array( + 'type' => 'special' +); $_prefs['smime_public_key'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); + +// S/MIME private key management widget +$_prefs['smimeprivatekey'] = array( + 'type' => 'special' +); + +$_prefs['smime_private_key'] = array( + 'value' => '' +); $_prefs['smime_additional_cert'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => '' +); + -// End S/MIME Options -// Minimal View Options +// *** Mobile View (MIMP) Preferences *** + +$prefGroups['mimp'] = array( + 'column' => _("Other Options"), + 'label' => _("Mobile View Options"), + 'desc' => _("Configure options for the mobile view."), + 'members' => array( + 'mimp_preview_msg', 'mimp_download_confirm', 'mimp_inline_all' + ) +); // display only the first 250 characters of a message on first message view? $_prefs['mimp_preview_msg'] = array( 'value' => 0, - 'locked' => false, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Display only the first 250 characters of a message initially?") ); @@ -1683,7 +1602,6 @@ $_prefs['mimp_download_confirm'] = array( 'value' => 0, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'number', 'desc' => _("Only show download confirmation page if message part is greater than this size, in bytes. Set to 0 to always require the confirmation page.") ); @@ -1692,14 +1610,23 @@ $_prefs['mimp_inline_all'] = array( 'value' => 0, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Show all inline parts by default in message view? If unchecked, will treat all but the first viewable inline part as attachments.") ); -// End Minimal View Options -// Standard View Options + +// *** Standard View (IMP) Preferences *** + +$prefGroups['standard'] = array( + 'column' => _("Other Options"), + 'label' => _("Standard View Options"), + 'desc' => _("Configure options for the standard view."), + 'members' => array( + 'preview_enabled', 'preview_maxlen', 'preview_strip_nl', + 'preview_show_unread', 'preview_show_tooltip' + ) +); // Previews are disabled by default as it can be performance intensive, // especially without caching. @@ -1707,7 +1634,6 @@ $_prefs['preview_enabled'] = array( // Disabled and locked by default 'value' => 0, 'locked' => true, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Enable message previews?") ); @@ -1716,7 +1642,6 @@ $_prefs['preview_maxlen'] = array( 'value' => 250, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'enum', 'enum' => array( 100 => _("100 characters"), @@ -1731,7 +1656,6 @@ $_prefs['preview_strip_nl'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Strip linebreaks?") ); @@ -1740,7 +1664,6 @@ $_prefs['preview_show_unread'] = array( 'value' => 1, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Show previews for unread messages only?") ); @@ -1749,20 +1672,24 @@ $_prefs['preview_show_tooltip'] = array( 'value' => 0, // Locked by default 'locked' => true, - 'shared' => false, 'type' => 'checkbox', 'desc' => _("Show previews in tooltips?") ); -// End Standard View Options -// Dynamic View Options + +// *** Dynamic View (DIMP) Preferences *** + +$prefGroups['dimp'] = array( + 'column' => _("Other Options"), + 'label' => _("Dynamic View Options"), + 'desc' => _("Configure options for the dynamic view."), + 'members' => array('dimp_login_view') +); // Login preferences (dimp) $_prefs['dimp_login_view'] = array( 'value' => 'portal', - 'locked' => false, - 'shared' => false, 'type' => 'enum', 'enum' => array( 'portal' => _("Portal"), @@ -1771,38 +1698,19 @@ $_prefs['dimp_login_view'] = array( 'desc' => _("The page to view immediately after login.") ); -// Other implicit dynamic view preferences +// Other dynamic view preferences $_prefs['dimp_qsearch_field'] = array( - 'value' => 'all', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 'all' +); $_prefs['dimp_show_preview'] = array( - 'value' => true, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => true +); $_prefs['dimp_splitbar'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 0 +); $_prefs['dimp_toggle_headers'] = array( - 'value' => 0, - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); - -// End Dynamic View Options - -// Other entries (used internally in IMP) - -// virtual inbox identifier -$_prefs['vinbox_id'] = array( - 'value' => '', - 'locked' => false, - 'shared' => false, - 'type' => 'implicit'); + 'value' => 0 +); diff --git a/imp/contacts.php b/imp/contacts.php index 2dd8cd1ec..ebeef8217 100644 --- a/imp/contacts.php +++ b/imp/contacts.php @@ -40,7 +40,7 @@ if (!isset($vars->formname)) { $vars->formname = 'compose'; } -$search_params = IMP_Compose::getAddressSearchParams(); +$search_params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); $apiargs = array( 'addresses' => array($vars->search), 'addressbooks' => array($vars->source), diff --git a/imp/docs/UPGRADING b/imp/docs/UPGRADING index dd6f6e9e2..405e3fd72 100644 --- a/imp/docs/UPGRADING +++ b/imp/docs/UPGRADING @@ -64,6 +64,7 @@ your ``config/prefs.php`` file and your preferences backend:: alternative_display attachment_display + filter_on_sidebar forward_bodytext diff --git a/imp/filterprefs.php b/imp/filterprefs.php deleted file mode 100644 index cbda88b78..000000000 --- a/imp/filterprefs.php +++ /dev/null @@ -1,126 +0,0 @@ - - * @package IMP - */ - -require_once dirname(__FILE__) . '/lib/Application.php'; -Horde_Registry::appInit('imp'); - -/* Are preferences locked? */ -$login_locked = $prefs->isLocked('filter_on_login') || empty($_SESSION['imp']['filteravail']); -$display_locked = $prefs->isLocked('filter_on_display') || empty($_SESSION['imp']['filteravail']); -$sidebar_locked = $prefs->isLocked('filter_on_sidebar') || empty($_SESSION['imp']['filteravail']); -$anymailbox_locked = $prefs->isLocked('filter_any_mailbox') || empty($_SESSION['imp']['filteravail']); -$menuitem_locked = $prefs->isLocked('filter_menuitem'); - -/* Run through the action handlers. */ -$actionID = Horde_Util::getFormData('actionID'); -switch ($actionID) { -case 'update_prefs': - if (!$login_locked) { - $prefs->setValue('filter_on_login', Horde_Util::getFormData('filter_login') ? 1 : 0); - } - if (!$display_locked) { - $prefs->setValue('filter_on_display', Horde_Util::getFormData('filter_display') ? 1 : 0); - } - if (!$sidebar_locked) { - $prefs->setValue('filter_on_sidebar', Horde_Util::getFormData('filter_sidebar') ? 1 : 0); - } - if (!$anymailbox_locked) { - $prefs->setValue('filter_any_mailbox', Horde_Util::getFormData('filter_any_mailbox') ? 1 : 0); - } - if (!$menuitem_locked) { - $prefs->setValue('filter_menuitem', Horde_Util::getFormData('filter_menuitem') ? 1 : 0); - } - $notification->push(_("Preferences successfully updated."), 'horde.success'); - break; -} - -$chunk = Horde_Util::nonInputVar('chunk'); -$group = 'filters'; -Horde_Prefs_Ui::generateHeader('imp', null, null, $chunk); - -$t = $injector->createInstance('Horde_Template'); -$t->setOption('gettext', true); -$t->set('navcell', Horde_Util::bufferOutput(array('Horde_Prefs_Ui', 'generateNavigationCell'), 'imp', 'filters')); -$t->set('prefsurl', Horde::getServiceLink('options', 'imp')); -$t->set('return_text', _("Return to Options")); - -/* Get filter links. */ -$blacklist_link = $whitelist_link = $filters_link = false; -if ($registry->hasMethod('mail/showBlacklist')) { - $blacklist_link = $registry->link('mail/showBlacklist'); -} -if ($registry->hasMethod('mail/showWhitelist')) { - $whitelist_link = $registry->link('mail/showWhitelist'); -} -if ($registry->hasMethod('mail/showFilters')) { - $filters_link = $registry->link('mail/showFilters'); -} - -/* If filters are disabled. */ -if (!$blacklist_link && !$whitelist_link && !$filters_link) { - $t->set('notactive', true); -} else { - $t->set('selfurl', Horde::applicationUrl('filterprefs.php')); - $t->set('forminput', Horde_Util::formInput()); - $t->set('group', $group); - $t->set('app', $app); - - $link_array = array( - array('g' => _("Edit your Filter Rules"), 'l' => $filters_link, 'h' => 'filter-edit-rules'), - array('g' => _("Edit your Blacklist"), 'l' => $blacklist_link, 'h' => 'filter-edit-blacklist'), - array('g' => _("Edit your Whitelist"), 'l' => $whitelist_link, 'h' => 'filter-edit-whitelist') - ); - $links = array(); - foreach ($link_array as $key => $val) { - if ($val['l']) { - $links[] = array( - 'img' => Horde::img('filters.png', $val['g']), - 'link' => Horde::link(Horde::url($val['l'])), - 'help' => Horde_Help::link('imp', $val['h']), - 'text' => $val['g'] - ); - } - } - $t->set('links', $links); - - $options_array = array( - 'login' => array('g' => _("Apply filter rules upon logging on?"), 'p' => 'filter_on_login', 'h' => 'filter-on-login', 'l' => $login_locked), - 'display' => array('g' => _("Apply filter rules whenever Inbox is displayed?"), 'p' => 'filter_on_display', 'h' => 'filter-on-display', 'l' => $display_locked), - 'sidebar' => array('g' => _("Apply filter rules whenever sidebar is refreshed?"), 'p' => 'filter_on_sidebar', 'h' => 'filter-on-sidebar', 'l' => $sidebar_locked), - 'any_mailbox' => array('g' => _("Allow filter rules to be applied in any mailbox?"), 'p' => 'filter_any_mailbox', 'h' => 'filter-any-mailbox', 'l' => $anymailbox_locked), - 'menuitem' => array('g' => _("Show the filter icon on the menubar?"), 'p' => 'filter_menuitem', 'l' => $menuitem_locked) - ); - - if ($_SESSION['imp']['protocol'] == 'pop') { - unset($options_array['any_mailbox']); - } - - $opts = array(); - foreach ($options_array as $key => $val) { - if (!$val['l']) { - $opts[] = array( - 'key' => $key, - 'checked' => $prefs->getValue($val['p']), - 'label' => Horde::label('filter_' . $key, $val['g']), - 'help' => isset($val['h']) ? Horde_Help::link('imp', $val['h']) : null - ); - } - } - $t->set('opts', $opts); - if (!empty($opts)) { - $t->set('save_opts', _("Save Options")); - } -} - -echo $t->fetch(IMP_TEMPLATES . '/prefs/filters/filters.html'); -if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-footer.inc'; -} diff --git a/imp/js/acl.js b/imp/js/acl.js index 1a7a65550..22475467d 100644 --- a/imp/js/acl.js +++ b/imp/js/acl.js @@ -1,5 +1,5 @@ /** - * Provides the javascript for the acl.php script (standard view). + * Provides the javascript for the ACL preferences management view. * * See the enclosed file COPYING for license information (GPL). If you * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. diff --git a/imp/js/addressbooksprefs.js b/imp/js/addressbooksprefs.js deleted file mode 100644 index 5c3991406..000000000 --- a/imp/js/addressbooksprefs.js +++ /dev/null @@ -1,169 +0,0 @@ -/** - * Provides the javascript for managing addressbooks. - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - */ - -var ImpAddressbooksPrefs = { - // Variables set by other code: fields - - deselectHeaders: function() - { - $('unselected_search_sources').selectedIndex = $('selected_search_sources').selectedIndex = -1; - }, - - resetHidden: function() - { - $('search_sources').setValue($A($('selected_search_sources').options).slice(1).pluck('value').join("\t")); - }, - - addSource: function() - { - this._sourceAction($('unselected_search_sources'), $('selected_search_sources')); - }, - - removeSource: function() - { - this._sourceAction($('selected_search_sources'), $('unselected_search_sources')); - }, - - _sourceAction: function(from, to) - { - var i = 1; - - $A(from.options).slice(1).each(function(s) { - if (s.selected) { - to.appendChild(s.cloneNode(true)); - s.remove(); - } - ++i; - }); - - this.resetHidden(); - }, - - moveSourceUp: function() - { - var sss = $('selected_search_sources'), - sel = sss.selectedIndex; - - if (sel == -1 || sss.length <= 2) { - return; - } - - // Deselect everything but the first selected item - sss.selectedIndex = sel; - - sss.options[sel].previous().insert({ before: sss.options[sel].cloneNode(false) }); - sss.options[sel].remove(); - - this.resetHidden(); - }, - - moveSourceDown: function() - { - var i, - sss = $('selected_search_sources'), - sel = sss.selectedIndex, - l = sss.length, - tmp = []; - - if (sel == -1 || l <= 2) { - return; - } - - // deselect everything but the first selected item - sss.selectedIndex = sel; - - sss.options[sel].next().insert({ after: sss.options[sel].cloneNode(false) }); - sss.options[sel].remove(); - - this.resetHidden(); - }, - - updateSearchFields: function() - { - var sv = this._getSelectedValue(false), - sf = $('search_fields'); - - sf.update(''); - this.fields.each(function(f) { - if (f[0] == sv) { - f.slice(1).each(function(o) { - var tmp = new Option(o[1], o[0]); - if (o[2]) { - tmp.selected = true; - } - sf.insert(tmp); - }); - } - }); - - this.changeSearchFields(); - }, - - _getSelectedValue: function(index) - { - var sss = $('selected_search_sources'); - if (sss) { - if (index) { - return sss.selectedIndex; - } - if (sss.selectedIndex >= 0) { - return sss.options[sss.selectedIndex].value; - } - return ''; - } else { - return index ? 0 : this.fields[0][0]; - } - }, - - changeSearchFields: function() - { - var data = [], - i = 0, - sf = $('search_fields'), - sv = this._getSelectedValue(true); - - $A(sf.options).each(function(o) { - this.fields[sv][i][2] = o.selected; - ++i; - }.bind(this)); - - this.fields.each(function(f) { - var tmp = [ f[0] ]; - f.slice(1).each(function(o) { - if (o[2]) { - tmp.push(o[0]); - } - }); - data.push(tmp.join("\t")); - }); - $('search_fields_string').setValue(data.join("\n")); - }, - - onDomLoad: function() - { - this.updateSearchFields(); - - if ($('search_fields')) { - $('search_fields').observe('change', this.changeSearchFields.bind(this)); - } - - if ($('unselected_search_sources')) { - //$('unselected_search_sources').observe('change', this.deselectHeaders.bind(this)); - $('selected_search_sources').observe('change', function() { - //this.deselectHeaders(); - this.updateSearchFields(); - }.bind(this)); - $('addsource').observe('click', this.addSource.bind(this)); - $('removesource').observe('click', this.removeSource.bind(this)); - $('moveup').observe('click', this.moveSourceUp.bind(this)); - $('movedown').observe('click', this.moveSourceDown.bind(this)); - } - } - -}; - -document.observe('dom:loaded', ImpAddressbooksPrefs.onDomLoad.bind(ImpAddressbooksPrefs)); diff --git a/imp/lib/Ajax/Imple/ContactAutoCompleter.php b/imp/lib/Ajax/Imple/ContactAutoCompleter.php index a848bcbb2..cad00ec61 100644 --- a/imp/lib/Ajax/Imple/ContactAutoCompleter.php +++ b/imp/lib/Ajax/Imple/ContactAutoCompleter.php @@ -40,7 +40,7 @@ class IMP_Ajax_Imple_ContactAutoCompleter extends Horde_Ajax_Imple_AutoCompleter if ($ac_browser && !isset($_SESSION['imp']['cache']['ac_ajax'])) { $success = $use_ajax = true; - $sparams = IMP_Compose::getAddressSearchParams(); + $sparams = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); foreach ($sparams['fields'] as $val) { array_map('strtolower', $val); sort($val); diff --git a/imp/lib/Application.php b/imp/lib/Application.php index ef334a84c..77608d3cd 100644 --- a/imp/lib/Application.php +++ b/imp/lib/Application.php @@ -56,13 +56,6 @@ class IMP_Application extends Horde_Registry_Application public $version = 'H4 (5.0-git)'; /** - * Cached data for prefs pages. - * - * @var array - */ - static public $prefsCache = array(); - - /** * Constructor. */ public function __construct() @@ -414,556 +407,65 @@ class IMP_Application extends Horde_Registry_Application return $auth->listUsers(); } - /* Preferences display/handling methods. */ + /* Preferences display/handling methods. Code is contained in + * IMP_Prefs_Ui so it doesn't have to be loaded on every page load. */ /** - * Code to run when viewing prefs for this application. + * Code to run on init when viewing prefs for this application. * - * @param string $group The prefGroup name. - * - * @return array A list of variables to export to the prefs display page. + * @param Horde_Core_Prefs_Ui $ui The UI object. */ - public function prefsInit($group) + public function prefsInit($ui) { - /* Add necessary javascript files here (so they are added to the - * document HEAD). */ - switch ($group) { - case 'accounts': - Horde::addScriptFile('accountsprefs.js', 'imp'); - - Horde::addInlineScript(array( - 'ImpAccountsPrefs.confirm_delete = ' . Horde_Serialize::serialize(_("Are you sure you want to delete this account?"), Horde_Serialize::JSON, Horde_Nls::getCharset()) - )); - break; - - case 'addressbooks': - $this->_prefsPrepareSourceselect(); - break; - - case 'display': - /* Set the timezone on this page so the 'time_format' output uses - * the configured time zone's time, not the system's time zone. */ - Horde_Nls::setTimeZone(); - break; - - case 'flags': - Horde::addScriptFile('colorpicker.js', 'horde'); - Horde::addScriptFile('flagprefs.js', 'imp'); - - Horde::addInlineScript(array( - 'ImpFlagPrefs.new_prompt = ' . Horde_Serialize::serialize(_("Please enter the label for the new flag:"), Horde_Serialize::JSON, Horde_Nls::getCharset()), - 'ImpFlagPrefs.confirm_delete = ' . Horde_Serialize::serialize(_("Are you sure you want to delete this flag?"), Horde_Serialize::JSON, Horde_Nls::getCharset()) - )); - break; - - case 'identities': - if (!$GLOBALS['prefs']->isLocked('sent_mail_folder')) { - Horde::addScriptFile('folderprefs.js', 'imp'); - Horde::addInlineScript(array( - 'ImpFolderPrefs.folders = ' . Horde_Serialize::serialize(array('sent_mail_folder', 'sent_mail_new', _("Enter the name for your new sent-mail folder"), _("Create a new sent-mail folder")), Horde_Serialize::JSON, Horde_Nls::getCharset()) - )); - } - break; - - case 'server': - $code = array(); - - if (!$GLOBALS['prefs']->isLocked('drafts_folder')) { - $code[] = array('drafts', 'drafts_new', _("Enter the name for your new drafts folder"), _("Create a new drafts folder")); - } - - if (!$GLOBALS['prefs']->isLocked('spam_folder')) { - $code[] = array('spam', 'spam_new', _("Enter the name for your new spam folder"), _("Create a new spam folder")); - } - - if (!$GLOBALS['prefs']->isLocked('trash_folder') && - !$GLOBALS['prefs']->isLocked('use_vtrash')) { - $code[] = array('trash', 'trash_new', _("Enter the name for your new trash folder"), _("Create a new trash folder")); - } - - if (!empty($code)) { - Horde::addScriptFile('folderprefs.js', 'imp'); - Horde::addInlineScript(array( - 'ImpFolderPrefs.folders = ' . Horde_Serialize::serialize($code, Horde_Serialize::JSON, Horde_Nls::getCharset()) - )); - } - break; - } + $GLOBALS['injector']->getInstance('IMP_Prefs_Ui')->prefsInit($ui); } /** - * Special preferences handling on update. + * Generate code used to display a special preference. * - * @param string $item The preference name. - * @param boolean $updated Set to true if preference was updated. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. * - * @return boolean True if preference was updated. + * @return string The HTML code to display on the options page. */ - public function prefsSpecial($item, $updated) + public function prefsSpecial($ui, $item) { - switch ($item) { - case 'sentmailselect': - return $this->_prefsSentmailSelect($updated); - - case 'draftsselect': - return $updated | $this->_prefsSpecialFolders($updated, 'drafts_folder', 'drafts', 'drafts_new'); - - case 'spamselect': - return $updated | $this->_prefsSpecialFolders($updated, 'spam_folder', 'spam', 'spam_new'); - - case 'trashselect': - return $this->_prefsTrashSelect($updated); - - case 'sourceselect': - return $this->_prefsSourceSelect($updated); - - case 'initialpageselect': - $this->_prefsInitialPageSelect(); - return true; - - case 'encryptselect': - $this->_prefsEncryptSelect(); - return true; - - case 'soundselect': - return $GLOBALS['prefs']->setValue('nav_audio', Horde_Util::getFormData('nav_audio')); - - case 'flagmanagement': - $this->_prefsFlagManagement(); - return false; - - case 'accountsmanagement': - $this->_prefsAccountsManagement(); - return false; - } + return $GLOBALS['injector']->getInstance('IMP_Prefs_Ui')->prefsSpecial($ui, $item); } /** - * Special preferences handling on UI display. + * Special preferences handling on update. * - * @param string $item The preference name. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. * - * @return boolean True if the preference item should be displayed. + * @return boolean True if preference was updated. */ - public function prefsSpecialGenerate($item) + public function prefsSpecialUpdate($ui, $item) { - switch ($item) { - case 'sentmailselect': - return !$GLOBALS['prefs']->isLocked('sent_mail_folder'); - - case 'draftsselect': - return !$GLOBALS['prefs']->isLocked('drafts_folder'); - - case 'spamselect': - return !$GLOBALS['prefs']->isLocked('spam_folder'); - - case 'trashselect': - return (!$GLOBALS['prefs']->isLocked('trash_folder') && !$GLOBALS['prefs']->isLocked('use_vtrash')); - - case 'initialpageselect': - return !$GLOBALS['prefs']->isLocked('initial_page'); - - case 'encryptselect': - return !$GLOBALS['prefs']->isLocked('default_encrypt'); - - case 'soundselect': - return !$GLOBALS['prefs']->isLocked('nav_audio'); - - case 'accountsmanagement': - $GLOBALS['prefsui_no_save'] = true; - return !empty($GLOBALS['conf']['user']['allow_accounts']); - - default: - return true; - } + return $GLOBALS['injector']->getInstance('IMP_Prefs_Ui')->prefsSpecialUpdate($ui, $item); } /** - * Do anything that we need to do as a result of certain preferences - * changing. + * Called when preferences are changed. * - * @param string $group The prefGroup name. + * @param Horde_Core_Prefs_Ui $ui The UI object. */ - public function prefsCallback($group) + public function prefsCallback($ui) { - global $prefs; - - /* Always check to make sure we have a valid trash folder if delete to - * trash is active. */ - if (($prefs->isDirty('use_trash') || $prefs->isDirty('trash_folder')) && - $prefs->getValue('use_trash') && - !$prefs->getValue('trash_folder') && - !$prefs->getValue('use_vtrash')) { - $GLOBALS['notification']->push(_("You have activated move to Trash but no Trash folder is defined. You will be unable to delete messages until you set a Trash folder in the preferences."), 'horde.warning'); - } - - switch ($group) { - case 'compose': - if ($prefs->isDirty('mail_domain')) { - $maildomain = preg_replace('/[^-\.a-z0-9]/i', '', $prefs->getValue('mail_domain')); - $prefs->setValue('maildomain', $maildomain); - if (!empty($maildomain)) { - $_SESSION['imp']['maildomain'] = $maildomain; - } - } - - if ($prefs->isDirty('compose_popup')) { - Horde::addInlineScript(array( - 'if (window.parent.frames.horde_menu) window.parent.frames.horde_menu.location.reload();' - )); - } - break; - - case 'delmove': - if ($prefs->isDirty('use_vtrash')) { - $GLOBALS['imp_search']->initialize(true); - } - break; - - case 'display': - if ($prefs->isDirty('tree_view')) { - $this->_mailboxesChanged(); - } - break; - - case 'server': - if ($prefs->isDirty('use_vinbox')) { - $GLOBALS['imp_search']->initialize(true); - } - - if ($prefs->isDirty('subscribe')) { - $this->_mailboxesChanged(); - } - break; - } + $GLOBALS['injector']->getInstance('IMP_Prefs_Ui')->prefsCallback($ui); } /** * Generate the menu to use on the prefs page. * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * * @return Horde_Menu A Horde_Menu object. */ - public function prefsMenu() - { - return IMP::getMenu(); - } - - /** - * TODO - */ - protected function _prefsSentmailSelect($updated) - { - if (!$GLOBALS['conf']['user']['allow_folders'] || - $GLOBALS['prefs']->isLocked('sent_mail_folder')) { - return $updated; - } - - $sent_mail_folder = Horde_Util::getFormData('sent_mail_folder'); - $sent_mail_new = Horde_String::convertCharset(Horde_Util::getFormData('sent_mail_new'), Horde_Nls::getCharset(), 'UTF7-IMAP'); - $sent_mail_default = $GLOBALS['prefs']->getValue('sent_mail_folder'); - - if (empty($sent_mail_folder) && !empty($sent_mail_new)) { - $sent_mail_folder = $GLOBALS['imp_imap']->appendNamespace($sent_mail_new); - } elseif (($sent_mail_folder == '-1') && !empty($sent_mail_default)) { - $sent_mail_folder = $GLOBALS['imp_imap']->appendNamespace($sent_mail_default); - } - - if (!empty($sent_mail_folder)) { - $imp_folder = $GLOBALS['injector']->getInstance('IMP_Folder'); - if (!$imp_folder->exists($sent_mail_folder)) { - $imp_folder->create($sent_mail_folder, $GLOBALS['prefs']->getValue('subscribe')); - } - } - $GLOBALS['identity']->setValue('sent_mail_folder', IMP::folderPref($sent_mail_folder, false)); - - return true; - } - - /** - * TODO - */ - protected function _prefsSpecialFolders($updated, $pref, $folder, $new) + public function prefsMenu($ui) { - if (!$GLOBALS['conf']['user']['allow_folders']) { - return $updated; - } - - $folder = Horde_Util::getFormData($folder); - if (isset($folder) && !$GLOBALS['prefs']->isLocked($pref)) { - $new = Horde_String::convertCharset(Horde_Util::getFormData($new), Horde_Nls::getCharset(), 'UTF7-IMAP'); - if ($folder == IMP::PREF_NO_FOLDER) { - $GLOBALS['prefs']->setValue($pref, ''); - } else { - if (empty($folder) && !empty($new)) { - $folder = $GLOBALS['imp_imap']->appendNamespace($new); - if (!$GLOBALS['injector']->getInstance('IMP_Folder')->create($folder, $GLOBALS['prefs']->getValue('subscribe'))) { - $folder = null; - } - } - if (!empty($folder)) { - $GLOBALS['prefs']->setValue($pref, IMP::folderPref($folder, false)); - return true; - } - } - } - - return $updated; - } - - /** - * TODO - */ - protected function _prefsTrashSelect($updated) - { - global $prefs; - - if (Horde_Util::getFormData('trash') == IMP::PREF_VTRASH) { - if ($prefs->isLocked('use_vtrash')) { - return false; - } - - $prefs->setValue('use_vtrash', 1); - $prefs->setValue('trash_folder', ''); - } else { - if ($prefs->isLocked('trash_folder')) { - return false; - } - - $updated = $updated | $this->_prefsSpecialFolders($updated, 'trash_folder', 'trash', 'trash_new'); - if ($updated) { - $prefs->setValue('use_vtrash', 0); - $prefs->setDirty('trash_folder', true); - } - } - - return $updated; - } - - /** - * TODO - */ - protected function _prefsSourceSelect($updated) - { - $search_sources = Horde_Util::getFormData('search_sources'); - if (!is_null($search_sources)) { - $GLOBALS['prefs']->setValue('search_sources', $search_sources); - unset($_SESSION['imp']['cache']['ac_ajax']); - $updated = true; - } - - $search_fields_string = Horde_Util::getFormData('search_fields_string'); - if (!is_null($search_fields_string)) { - $GLOBALS['prefs']->setValue('search_fields', $search_fields_string); - $updated = true; - } - - $add_source = Horde_Util::getFormData('add_source'); - if (!is_null($add_source)) { - $GLOBALS['prefs']->setValue('add_source', $add_source); - $updated = true; - } - - return $updated; - } - - /** - * TODO - */ - protected function _prefsInitialPageSelect() - { - $initial_page = Horde_Util::getFormData('initial_page'); - $GLOBALS['prefs']->setValue('initial_page', $initial_page); - } - - /** - * TODO - */ - protected function _prefsEncryptSelect() - { - $default_encrypt = Horde_Util::getFormData('default_encrypt'); - $GLOBALS['prefs']->setValue('default_encrypt', $default_encrypt); - } - - /** - * TODO - */ - protected function _prefsFlagManagement() - { - $imp_flags = $GLOBALS['injector']->getInstance('IMP_Imap_Flags'); - $action = Horde_Util::getFormData('flag_action'); - $data = Horde_Util::getFormData('flag_data'); - - if ($action == 'add') { - $GLOBALS['notification']->push(sprintf(_("Added flag \"%s\"."), $data), 'horde.success'); - $imp_flags->addFlag($data); - return; - } - - $def_color = $GLOBALS['prefs']->getValue('msgflags_color'); - - // Don't set updated on these actions. User may want to do more actions. - foreach ($imp_flags->getList() as $key => $val) { - $md5 = hash('md5', $key); - - switch ($action) { - case 'delete': - if ($data == ('bg_' . $md5)) { - $imp_flags->deleteFlag($key); - $GLOBALS['notification']->push(sprintf(_("Deleted flag \"%s\"."), $val['l']), 'horde.success'); - } - break; - - default: - /* Change labels for user-defined flags. */ - if ($val['t'] == 'imapp') { - $label = Horde_Util::getFormData('label_' . $md5); - if (strlen($label) && ($label != $val['l'])) { - $imp_flags->updateFlag($key, array('l' => $label)); - } - } - - /* Change background for all flags. */ - $bg = strtolower(Horde_Util::getFormData('bg_' . $md5)); - if ((isset($val['b']) && ($bg != $val['b'])) || - (!isset($val['b']) && ($bg != $def_color))) { - $imp_flags->updateFlag($key, array('b' => $bg)); - } - break; - } - } - } - - /** - * TODO - */ - protected function _prefsAccountsManagement() - { - $success = false; - $vars = Horde_Variables::getDefaultVariables(); - - switch ($vars->accounts_action) { - case 'add': - if (!$vars->accounts_server || - !$vars->accounts_username) { - $GLOBALS['notification']->push(_("Missing required values."), 'horde.error'); - } else { - /* Port is not required. */ - $port = $vars->accounts_port; - if (!$port) { - $port = ($vars->accounts_type == 'imap') ? 143 : 110; - } - - /* Label is not required. */ - $label = $vars->accounts_label; - if (!strlen($label)) { - $label = $vars->accounts_server . ':' . $port . ' [' . $vars->accounts_type . ']'; - } - - $imp_accounts = $GLOBALS['injector']->getInstance('IMP_Accounts'); - $imp_accounts->addAccount(array( - 'label' => $label, - 'port' => $port, - 'secure' => $vars->accounts_secure, - 'server' => $vars->accounts_server, - 'type' => $vars->accounts_type, - 'username' => $vars->accounts_username - )); - $GLOBALS['notification']->push(sprintf(_("Account \"%s\" added."), $vars->accounts_server), 'horde.success'); - - $success = true; - } - break; - - case 'delete': - $imp_accounts = $GLOBALS['injector']->getInstance('IMP_Accounts'); - $tmp = $imp_accounts->getAccount($vars->accounts_data); - if ($imp_accounts->deleteAccount($vars->accounts_data)) { - $GLOBALS['notification']->push(sprintf(_("Account \"%s\" deleted."), $tmp['server']), 'horde.success'); - $success = true; - } - break; - } - - if ($success) { - $this->_mailboxesChanged(); - } - } - - /** - * TODO - */ - protected function _prefsPrepareSourceselect() - { - self::$prefsCache['sourceselect'] = array(); - - if (!$GLOBALS['registry']->hasMethod('contacts/sources') || - $GLOBALS['prefs']->isLocked('search_sources')) { - return; - } - - $readable = $search_fields = $prefSelect = $writeable = $writeSelect = array(); - - try { - $readable = $GLOBALS['registry']->call('contacts/sources'); - } catch (Horde_Exception $e) {} - - try { - $writeable = $GLOBALS['registry']->call('contacts/sources', array(true)); - } catch (Horde_Exception $e) {} - - $search = IMP_Compose::getAddressSearchParams(); - - if (count($readable) == 1) { - // Only one source, no need to display the selection widget - $search['sources'] = array_keys($readable); - } - - foreach ($search['sources'] as $source) { - if (!empty($readable[$source])) { - $prefSelect[$source] = $readable[$source]; - } - } - - $readSelect = array_diff(array_keys($readable), $search['sources']); - - if (!$GLOBALS['prefs']->isLocked('add_source')) { - foreach ($writeable as $source => $name) { - $writeSelect[] = array( - 'val' => $source, - 'sel' => ($GLOBALS['prefs']->getValue('add_source') == $source), - 'name' => $name - ); - } - } - - $source_count = 0; - - foreach (array_keys($readable) as $source) { - $search_fields[$source_count][] = $source; - - try { - foreach ($GLOBALS['registry']->call('contacts/fields', array($source)) as $field) { - if ($field['search']) { - $search_fields[$source_count][] = array($field['name'], $field['label'], isset($search['fields'][$source]) && in_array($field['name'], $search['fields'][$source])); - } - } - } catch (Horde_Exception $e) {} - - ++$source_count; - } - - Horde::addScriptFile('addressbooksprefs.js', 'imp'); - Horde::addInlineScript(array( - 'ImpAddressbooksPrefs.fields = ' . Horde_Serialize::serialize($search_fields, Horde_Serialize::JSON, Horde_Nls::getCharset()) - )); - self::$prefsCache['sourceselect'] = array( - 'prefSelect' => $prefSelect, - 'readable' => $readable, - 'readSelect' => $readSelect, - 'search' => $search, - 'writeable' => $writeable, - 'writeSelect' => $writeSelect - ); + return $GLOBALS['injector']->getInstance('IMP_Prefs_Ui')->prefsMenu($ui); } /* Language change callback. */ @@ -975,56 +477,16 @@ class IMP_Application extends Horde_Registry_Application public function changeLanguage() { $this->init(); - $this->_mailboxesChanged(); + $this->mailboxesChanged(); $GLOBALS['imp_search']->initialize(true); } - /* Horde_Prefs_Credentials:: methods. */ - - /** - * Returns a list of authentication credentials, i.e. server settings that - * can be specified by the user on the login screen. - * - * @return array A hash with credentials, suited for the preferences - * interface. - */ - public function authCredentials() - { - $app_name = $GLOBALS['registry']->get('name'); - - $servers = IMP_Imap::loadServerConfig(); - $server_list = array(); - foreach ($servers as $key => $val) { - $server_list[$key] = $val['name']; - } - reset($server_list); - - $credentials = array( - 'username' => array( - 'desc' => sprintf(_("%s for %s"), _("Username"), $app_name), - 'type' => 'text' - ), - 'password' => array( - 'desc' => sprintf(_("%s for %s"), _("Password"), $app_name), - 'type' => 'password' - ), - 'server' => array( - 'desc' => sprintf(_("%s for %s"), _("Server"), $app_name), - 'type' => 'enum', - 'enum' => $server_list, - 'value' => key($server_list) - ) - ); - - return $credentials; - } - /* Helper methods. */ /** * Run tasks when the mailbox list has changed. */ - protected function _mailboxesChanged() + public function mailboxesChanged() { $GLOBALS['injector']->getInstance('IMP_Folder')->clearFlistCache(); $GLOBALS['injector']->getInstance('IMP_Imap_Tree')->init(); diff --git a/imp/lib/Auth.php b/imp/lib/Auth.php index 71aa90ce6..fd02805f1 100644 --- a/imp/lib/Auth.php +++ b/imp/lib/Auth.php @@ -478,6 +478,7 @@ class IMP_Auth /* Suppress menus in options screen and indicate that notifications * should use the ajax mode. */ if ($sess['view'] == 'dimp') { + Horde_Core_Prefs_Ui::hideMenu(true); $_SESSION['horde_prefs']['nomenu'] = true; $_SESSION['horde_notification']['override'] = array( IMP_BASE . '/lib/Notification/Listener/AjaxStatus.php', diff --git a/imp/lib/Block/tree_folders.php b/imp/lib/Block/tree_folders.php index bee7a48f7..3fa98f1ef 100644 --- a/imp/lib/Block/tree_folders.php +++ b/imp/lib/Block/tree_folders.php @@ -18,7 +18,7 @@ class Horde_Block_imp_tree_folders extends Horde_Block protected function _buildTree(&$tree, $indent = 0, $parent = null) { /* Run filters now */ - if ($GLOBALS['prefs']->getValue('filter_on_sidebar')) { + if ($GLOBALS['prefs']->getValue('filter_on_display')) { $imp_filter = new IMP_Filter(); $imp_filter->filter('INBOX'); } diff --git a/imp/lib/Compose.php b/imp/lib/Compose.php index 5e9693e8b..c7851a0fd 100644 --- a/imp/lib/Compose.php +++ b/imp/lib/Compose.php @@ -2838,7 +2838,7 @@ class IMP_Compose */ static public function getAddressList($search = '') { - $sparams = self::getAddressSearchParams(); + $sparams = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); try { $res = $GLOBALS['registry']->call('contacts/search', array($search, $sparams['sources'], $sparams['fields'], false)); } catch (Horde_Exception $e) { @@ -2869,34 +2869,4 @@ class IMP_Compose return $search; } - /** - * Determines parameters needed to do an address search - * - * @return array An array with two keys: 'sources' and 'fields'. - */ - static public function getAddressSearchParams() - { - $src = explode("\t", $GLOBALS['prefs']->getValue('search_sources')); - if ((count($src) == 1) && empty($src[0])) { - $src = array(); - } - - $fields = array(); - if (($val = $GLOBALS['prefs']->getValue('search_fields'))) { - $field_arr = explode("\n", $val); - foreach ($field_arr as $field) { - $field = trim($field); - if (!empty($field)) { - $tmp = explode("\t", $field); - if (count($tmp) > 1) { - $source = array_splice($tmp, 0, 1); - $fields[$source[0]] = $tmp; - } - } - } - } - - return array('sources' => $src, 'fields' => $fields); - } - } diff --git a/imp/lib/Crypt/Pgp.php b/imp/lib/Crypt/Pgp.php index c271a9981..4db65f36c 100644 --- a/imp/lib/Crypt/Pgp.php +++ b/imp/lib/Crypt/Pgp.php @@ -177,7 +177,7 @@ class IMP_Crypt_Pgp extends Horde_Crypt_Pgp } /* Try retrieving by e-mail only first. */ - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); try { $result = $GLOBALS['registry']->call('contacts/getField', array($address, self::PUBKEY_FIELD, $params['sources'], false, true)); } catch (Horde_Exception $e) { @@ -226,7 +226,7 @@ class IMP_Crypt_Pgp extends Horde_Crypt_Pgp */ public function listPublicKeys() { - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); if (empty($params['sources'])) { return array(); } @@ -243,7 +243,7 @@ class IMP_Crypt_Pgp extends Horde_Crypt_Pgp */ public function deletePublicKey($email) { - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); return $GLOBALS['registry']->call('contacts/deleteField', array($email, self::PUBKEY_FIELD, $params['sources'])); } @@ -637,7 +637,7 @@ class IMP_Crypt_Pgp extends Horde_Crypt_Pgp $t->set('import_public_key', $target == 'process_import_public_key'); $t->set('import_personal_public_key', $target == 'process_import_personal_public_key'); $t->set('import_personal_private_key', $target == 'process_import_personal_private_key'); - echo $t->fetch(IMP_TEMPLATES . '/prefs/pgp/import_key.html'); + echo $t->fetch(IMP_TEMPLATES . '/pgp/import_key.html'); } /** diff --git a/imp/lib/Crypt/Smime.php b/imp/lib/Crypt/Smime.php index 19340c281..ae8e79a4d 100644 --- a/imp/lib/Crypt/Smime.php +++ b/imp/lib/Crypt/Smime.php @@ -162,7 +162,7 @@ class IMP_Crypt_Smime extends Horde_Crypt_Smime } catch (Horde_Exception_HookNotSet $e) { } - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); try { $key = $GLOBALS['registry']->call('contacts/getField', array($address, self::PUBKEY_FIELD, $params['sources'], false, true)); @@ -191,7 +191,7 @@ class IMP_Crypt_Smime extends Horde_Crypt_Smime */ public function listPublicKeys() { - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); if (empty($params['sources'])) { return array(); } @@ -207,7 +207,7 @@ class IMP_Crypt_Smime extends Horde_Crypt_Smime */ public function deletePublicKey($email) { - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); $GLOBALS['registry']->call('contacts/deleteField', array($email, self::PUBKEY_FIELD, $params['sources'])); } @@ -474,7 +474,7 @@ class IMP_Crypt_Smime extends Horde_Crypt_Smime $t->set('forminput', Horde_Util::formInput()); $t->set('import_public_key', $target == 'process_import_public_key'); $t->set('import_personal_certs', $target == 'process_import_personal_certs'); - echo $t->fetch(IMP_TEMPLATES . '/prefs/smime/import_key.html'); + echo $t->fetch(IMP_TEMPLATES . '/smime/import_key.html'); } /** diff --git a/imp/lib/Imap/Acl.php b/imp/lib/Imap/Acl.php index c327910e0..fe766db23 100644 --- a/imp/lib/Imap/Acl.php +++ b/imp/lib/Imap/Acl.php @@ -39,6 +39,10 @@ class IMP_Imap_Acl throw new Horde_Exception(_("ACL requires an IMAP server.")); } + if (empty($_SESSION['imp']['imap']['acl'])) { + throw new Horde_Exception(_("ACLs not configured for this server.")); + } + if (!$GLOBALS['imp_imap']->ob()->queryCapability('ACL')) { throw new Horde_Exception(_("IMAP server does not support ACLs.")); } diff --git a/imp/lib/Mime/Viewer/Html.php b/imp/lib/Mime/Viewer/Html.php index 2f5478e4c..a44bcc1b0 100644 --- a/imp/lib/Mime/Viewer/Html.php +++ b/imp/lib/Mime/Viewer/Html.php @@ -310,7 +310,7 @@ class IMP_Horde_Mime_Viewer_Html extends Horde_Mime_Viewer_Html return false; } - $params = IMP_Compose::getAddressSearchParams(); + $params = Horde_Core_Prefs_Utils::getAddressbookSearchParams(); $headers = $this->_params['contents']->getHeaderOb(); /* Try to get back a result from the search. */ diff --git a/imp/lib/Prefs/Ui.php b/imp/lib/Prefs/Ui.php new file mode 100644 index 000000000..6b43e957f --- /dev/null +++ b/imp/lib/Prefs/Ui.php @@ -0,0 +1,1572 @@ + + * @package IMP + */ +class IMP_Prefs_Ui +{ + /** + * Code to run on init when viewing prefs for this application. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + public function prefsInit($ui) + { + global $conf, $prefs, $registry; + + $pop3 = (isset($_SESSION['imp']['protocol']) && ($_SESSION['imp']['protocol'] == 'pop')); + + switch ($ui->group) { + case 'accounts': + if (empty($conf['user']['allow_accounts'])) { + $ui->suppress[] = 'accountsmanagement'; + } else { + Horde::addScriptFile('accountsprefs.js', 'imp'); + } + break; + + case 'acl': + Horde::addScriptFile('acl.js', 'imp'); + break; + + case 'addressbooks': + if (!$prefs->isLocked('sourceselect')) { + Horde_Core_Prefs_Ui_Widgets::addressbooksInit($ui); + } + + if (!$prefs->isLocked('add_source')) { + try { + $sources = array(); + foreach ($registry->call('contacts/sources', array(true)) as $source => $name) { + $sources[$source] = $name; + } + $ui->override['add_source'] = $sources; + } catch (Horde_Exception $e) { + $ui->suppress[] = 'add_source'; + } + } + break; + + case 'compose': + if ($prefs->isLocked('default_encrypt')) { + $ui->suppress[] = 'encryptselect'; + } + if (empty($conf['compose']['allow_receipts'])) { + $ui->suppress[] = 'disposition_request_read'; + } + break; + + case 'delmove': + if ($pop3) { + $ui->suppress[] = 'move_ham_after_report'; + $ui->suppress[] = 'use_trash'; + $ui->suppress[] = 'trashselect'; + $ui->suppress[] = 'use_vtrash'; + $ui->suppress[] = 'empty_trash_menu'; + + $tmp = $ui->prefs['delete_spam_after_report']['enum']; + unset($tmp[2]); + $ui->override['delete_spam_after_report'] = $tmp; + } + break; + + case 'display': + /* Set the timezone on this page so the 'time_format' output uses + * the configured time zone's time, not the system's time zone. */ + Horde_Nls::setTimeZone(); + if ($pop3) { + $ui->suppress[] = 'nav_expanded'; + $ui->suppress[] = 'tree_view'; + $ui->suppress[] = 'nav_expanded_sidebar'; + } + break; + + case 'filters': + if (empty($_SESSION['imp']['filteravail'])) { + $ui->suppress[] = 'filter_on_login'; + $ui->suppress[] = 'filter_on_display'; + $ui->suppress[] = 'filter_any_mailbox'; + } + if (!$registry->hasMethod('mail/showFilters')) { + $ui->suppress[] = 'filters_link'; + } + if (!$registry->hasMethod('mail/showBlacklist')) { + $ui->suppress[] = 'filters_blacklist_link'; + } + if (!$registry->hasMethod('mail/showWhitelist')) { + $ui->suppress[] = 'filters_whitelist_link'; + } + break; + + case 'flags': + Horde::addScriptFile('colorpicker.js', 'horde'); + Horde::addScriptFile('flagprefs.js', 'imp'); + break; + + case 'identities': + if ($prefs->isLocked('sent_mail_folder')) { + $ui->suppress[] = 'sentmailselect'; + } else { + Horde::addScriptFile('folderprefs.js', 'imp'); + } + break; + + case 'logintasks': + if ($prefs->isLocked('initial_page')) { + $ui->suppress[] = 'initialpageselect'; + } + if ($pop3) { + $ui->suppress[] = 'initialpageselect'; + $ui->suppress[] = 'rename_sentmail_monthly'; + $ui->suppress[] = 'delete_sentmail_monthly'; + $ui->suppress[] = 'delete_sentmail_monthly_keep'; + $ui->suppress[] = 'purge_sentmail'; + $ui->suppress[] = 'purge_sentmail_interval'; + $ui->suppress[] = 'purge_sentmail_keep'; + $ui->suppress[] = 'purge_trash'; + $ui->suppress[] = 'purge_trash_interval'; + $ui->suppress[] = 'purge_trash_keep'; + $ui->suppress[] = 'purge_spam'; + $ui->suppress[] = 'purge_spam_interval'; + $ui->suppress[] = 'purge_spam_keep'; + } + break; + + case 'newmail': + if ($prefs->isLocked('nav_audio')) { + $ui->suppress[] = 'soundselect'; + } + if ($pop3) { + $ui->suppress[] = 'nav_poll_all'; + } + break; + + case 'pgp': + if ($prefs->getValue('use_pgp')) { + Horde::addScriptFile('imp.js', 'imp'); + } else { + $ui->suppress[] = 'use_pgp_text'; + $ui->suppress[] = 'pgp_attach_pubkey'; + $ui->suppress[] = 'pgp_scan_body'; + $ui->suppress[] = 'pgp_verify'; + $ui->suppress[] = 'pgppublickey'; + $ui->suppress[] = 'pgpprivatekey'; + } + break; + + case 'server': + $code = array(); + + if ($prefs->isLocked('drafts_folder')) { + $ui->suppress[] = 'draftsselect'; + } else { + $code[] = array('drafts', 'drafts_new', _("Enter the name for your new drafts folder"), _("Create a new drafts folder")); + } + + if ($prefs->isLocked('spam_folder')) { + $ui->suppress[] = 'spamselect'; + } else { + $code[] = array('spam', 'spam_new', _("Enter the name for your new spam folder"), _("Create a new spam folder")); + } + + if (!$prefs->isLocked('trash_folder') && + !$prefs->isLocked('use_vtrash')) { + $code[] = array('trash', 'trash_new', _("Enter the name for your new trash folder"), _("Create a new trash folder")); + } else { + $ui->suppress[] = 'trashselect'; + } + + if (!empty($code)) { + Horde::addScriptFile('folderprefs.js', 'imp'); + Horde::addInlineScript(array( + 'ImpFolderPrefs.folders = ' . Horde_Serialize::serialize($code, Horde_Serialize::JSON, Horde_Nls::getCharset()) + )); + } + break; + + case 'smime': + $use_smime = false; + if ($prefs->getValue('use_smime')) { + try { + $GLOBALS['injector']->getInstance('IMP_Crypt_Smime')->checkForOpenSSL(); + $use_smime = true; + } catch (Horde_Exception $e) {} + } + + if ($use_smime) { + Horde::addScriptFile('imp.js', 'imp'); + } else { + $ui->suppress[] = 'use_smime_text'; + $ui->suppress[] = 'smime_verify'; + $ui->suppress[] = 'smimepublickey'; + $ui->suppress[] = 'smimeprivatekey'; + } + break; + + case 'stationery': + if ($prefs->isLocked('stationery')) { + $ui->suppress[] = 'stationerymanagement'; + } else { + $ui->nobuttons = true; + } + break; + + case 'viewing': + if (empty($conf['maillog']['use_maillog'])) { + $ui->suppress[] = 'disposition_send_mdn'; + } + break; + } + + /* Hide appropriate prefGroups. */ + if ($pop3) { + $ui->suppressGroups[] = 'server'; + $ui->suppressGroups[] = 'flags'; + } + + try { + $GLOBALS['injector']->getInstance('IMP_Imap_Acl'); + } catch (Exception $e) { + $ui->suppressGroups[] = 'acl'; + } + + if (empty($conf['user']['allow_accounts'])) { + $ui->suppressGroups[] = 'accounts'; + } + + $contacts_app = $registry->hasInterface('contacts'); + if (!$contacts_app || !$registry->hasPermission($contacts_app)) { + $ui->suppressGroups[] = 'addressbooks'; + } + + if (!isset($GLOBALS['conf']['gnupg']['path'])) { + $ui->suppressGroups[] = 'pgp'; + } + + if (!Horde_Util::extensionExists('openssl') || + !isset($conf['openssl']['path'])) { + $ui->suppressGroups[] = 'smime'; + } + + // TODO: For now, disable this group since accounts code has not + // yet been fully written. + $ui->suppressGroups[] = 'accounts'; + } + + /** + * Generate code used to display a special preference. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return string The HTML code to display on the options page. + */ + public function prefsSpecial($ui, $item) + { + switch ($item) { + case 'accountsmanagement': + return $this->_accountsManagement($ui); + + case 'aclmanagement': + return $this->_aclManagement($ui); + + case 'draftsselect': + return $this->_drafts(); + + case 'encryptselect': + return $this->_encrypt(); + + case 'flagmanagement': + return $this->_flagManagement(); + + case 'initialpageselect': + return $this->_initialPage(); + + case 'pgpprivatekey': + return $this->_pgpPrivateKey($ui); + + case 'pgppublickey': + return $this->_pgpPublicKey($ui); + + case 'sentmailselect': + return $this->_sentmail(); + + case 'smimeprivatekey': + return $this->_smimePrivateKey($ui); + + case 'smimepublickey': + return $this->_smimePublicKey($ui); + + case 'soundselect': + return $this->_sound(); + + case 'sourceselect': + return Horde_Core_Prefs_Ui_Widgets::addressbooks($ui); + + case 'spamselect': + return $this->_spam(); + + case 'stationerymanagement': + return $this->_stationeryManagement($ui); + + case 'trashselect': + return $this->_trash(); + } + + return ''; + } + + /** + * Special preferences handling on update. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * @param string $item The preference name. + * + * @return boolean True if preference was updated. + */ + public function prefsSpecialUpdate($ui, $item) + { + global $prefs; + + switch ($item) { + case 'accountsmanagement': + $this->_updateAccountsManagement($ui); + return false; + + case 'aclmanagement': + $this->_updateAclManagement($ui); + return false; + + case 'draftsselect': + return $this->_updateSpecialFolders('drafts_folder', $ui->vars->drafts, $ui->vars->drafts_new, $ui); + + case 'encryptselect': + $prefs->setValue('default_encrypt', $ui->vars->default_encrypt); + return true; + + case 'flagmanagement': + $this->_updateFlagManagement($ui); + return false; + + case 'initialpageselect': + $prefs->setValue('initial_page', $ui->vars->initial_page); + return true; + + case 'pgpprivatekey': + $this->_updatePgpPrivateKey($ui); + return false; + + case 'pgppublickey': + $this->_updatePgpPublicKey($ui); + return false; + + case 'sentmailselect': + return $this->_updateSentmail($ui); + + case 'smimeprivatekey': + $this->_updateSmimePrivateKey($ui); + return false; + + case 'smimepublickey': + $this->_updateSmimePublicKey($ui); + return false; + + case 'soundselect': + return $prefs->setValue('nav_audio', $ui->vars->nav_audio); + + case 'sourceselect': + if (isset($ui->vars->sources)) { + unset($_SESSION['imp']['cache']['ac_ajax']); + } + return Horde_Core_Prefs_Ui_Widgets::addressbooksUpdate($ui); + + case 'spamselect': + return $this->_updateSpecialFolders('spam_folder', $vars->spam, $vars->spam_new, $ui); + + case 'stationerymanagement': + return $this->_updateStationeryManagement($ui); + + case 'trashselect': + return $this->_updateTrash($ui); + } + + return false; + } + + /** + * Called when preferences are changed. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + public function prefsCallback($ui) + { + global $prefs; + + /* Always check to make sure we have a valid trash folder if delete to + * trash is active. */ + if (($prefs->isDirty('use_trash') || $prefs->isDirty('trash_folder')) && + $prefs->getValue('use_trash') && + !$prefs->getValue('trash_folder') && + !$prefs->getValue('use_vtrash')) { + $GLOBALS['notification']->push(_("You have activated move to Trash but no Trash folder is defined. You will be unable to delete messages until you set a Trash folder in the preferences."), 'horde.warning'); + } + + switch ($ui->group) { + case 'compose': + if ($prefs->isDirty('mail_domain')) { + $maildomain = preg_replace('/[^-\.a-z0-9]/i', '', $prefs->getValue('mail_domain')); + $prefs->setValue('maildomain', $maildomain); + if (!empty($maildomain)) { + $_SESSION['imp']['maildomain'] = $maildomain; + } + } + + if ($prefs->isDirty('compose_popup')) { + Horde::addInlineScript(array( + 'if (window.parent.frames.horde_menu) window.parent.frames.horde_menu.location.reload();' + )); + } + break; + + case 'delmove': + if ($prefs->isDirty('use_vtrash')) { + $GLOBALS['imp_search']->initialize(true); + } + break; + + case 'display': + if ($prefs->isDirty('tree_view')) { + $GLOBALS['registry']->getApiInstance('imp', 'application')->mailboxesChanged(); + } + break; + + case 'server': + if ($prefs->isDirty('use_vinbox')) { + $GLOBALS['imp_search']->initialize(true); + } + + if ($prefs->isDirty('subscribe')) { + $GLOBALS['registry']->getApiInstance('imp', 'application')->mailboxesChanged(); + } + break; + } + } + + /** + * Generate the menu to use on the prefs page. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return Horde_Menu A Horde_Menu object. + */ + public function prefsMenu($ui) + { + return IMP::getMenu(); + } + + /* Accounts management handling. */ + + /** + * Create code for accounts management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _accountsManagement($ui) + { + $ui->nobuttons = true; + + Horde::addInlineScript(array( + 'ImpAccountsPrefs.confirm_delete = ' . Horde_Serialize::serialize(_("Are you sure you want to delete this account?"), Horde_Serialize::JSON, Horde_Nls::getCharset()) + )); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + if ($ui->vars->accounts_action == 'new') { + $t->set('new', true); + } else { + $accounts_list = $GLOBALS['injector']->getInstance('IMP_Accounts')->getList(); + if (!empty($accounts_list)) { + $t->set('delete_img', Horde::img('delete.png')); + + $out = array(); + foreach ($accounts_list as $key => $val) { + $out[] = array( + 'id' => $key, + 'label' => htmlspecialchars($val['label']), + 'port' => htmlspecialchars($val['port']), + 'secure' => ($val['secure'] == 'yes'), + 'secure_auto' => ($val['secure'] == 'auto'), + 'server' => htmlspecialchars($val['server']), + 'type' => htmlspecialchars($val['type']), + ); + } + $t->set('accounts', $out); + } + } + + return $t->fetch(IMP_TEMPLATES . '/prefs/accounts.html'); + } + + /** + * Update accounts related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateAccountsManagement($ui) + { + $success = false; + + switch ($ui->vars->accounts_action) { + case 'add': + if (!$ui->vars->accounts_server || + !$ui->vars->accounts_username) { + $GLOBALS['notification']->push(_("Missing required values."), 'horde.error'); + } else { + /* Port is not required. */ + $port = $ui->vars->accounts_port; + if (!$port) { + $port = ($ui->vars->accounts_type == 'imap') ? 143 : 110; + } + + /* Label is not required. */ + $label = $ui->vars->accounts_label; + if (!strlen($label)) { + $label = $ui->vars->accounts_server . ':' . $port . ' [' . $ui->vars->accounts_type . ']'; + } + + $imp_accounts = $GLOBALS['injector']->getInstance('IMP_Accounts'); + $imp_accounts->addAccount(array( + 'label' => $label, + 'port' => $port, + 'secure' => $ui->vars->accounts_secure, + 'server' => $ui->vars->accounts_server, + 'type' => $ui->vars->accounts_type, + 'username' => $ui->vars->accounts_username + )); + $GLOBALS['notification']->push(sprintf(_("Account \"%s\" added."), $ui->vars->accounts_server), 'horde.success'); + + $success = true; + } + break; + + case 'delete': + $imp_accounts = $GLOBALS['injector']->getInstance('IMP_Accounts'); + $tmp = $imp_accounts->getAccount($ui->vars->accounts_data); + if ($imp_accounts->deleteAccount($ui->vars->accounts_data)) { + $GLOBALS['notification']->push(sprintf(_("Account \"%s\" deleted."), $tmp['server']), 'horde.success'); + $success = true; + } + break; + } + + if ($success) { + $GLOBALS['registry']->getApiInstance('imp', 'application')->mailboxesChanged(); + } + } + + /* ACL management. */ + + /** + * Create code for ACL management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _aclManagement($ui) + { + $ACL = $GLOBALS['injector']->getInstance('IMP_Imap_Acl'); + $imp_folder = $GLOBALS['injector']->getInstance('IMP_Folder'); + $rights = $ACL->getRights(); + + $folder = empty($ui->vars->folder) + ? 'INBOX' + : $ui->vars->folder; + + $curr_acl = $ACL->getACL($folder); + $canEdit = $ACL->canEdit($folder, Horde_Auth::getAuth()); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('options', IMP::flistSelect(array('selected' => $folder))); + $t->set('current', sprintf(_("Current access to %s"), IMP::displayFolder($folder))); + $t->set('folder', $folder); + $t->set('noacl', !count($curr_acl)); + $t->set('maxrule', 1); + + if (!$t->get('noacl')) { + $i = 0; + $cval = array(); + $protected = $ACL->getProtected(); + + foreach ($curr_acl as $index => $rule) { + $entry = array( + 'i' => ++$i, + 'num_val' => ($i - 1), + 'disabled' => in_array($index, $protected) || !$canEdit, + 'index' => $index + ); + + /* Create table of each ACL option for each user granted + * permissions; enabled indicates the right has been given to + * the user */ + foreach (array_keys($rights) as $val) { + $entry['rule'][] = array( + 'enabled' => in_array($val, $rule), + 'val' => $val + ); + } + $cval[] = $entry; + } + + $t->set('curr_acl', $cval); + $t->set('maxval', count($curr_acl)); + + /* Number of individual ACL options, for table rendering. */ + $t->set('maxrule', count($rights)); + } + + $t->set('canedit', $canEdit); + + if (empty($_SESSION['imp']['admin'])) { + $t->set('noadmin', true); + } else { + $current_users = array_keys($curr_acl); + $new_user = array(); + + foreach ($GLOBALS['registry']->callByPackage('listUsers', 'imp') as $user) { + if (in_array($user, $current_users)) { + continue; + } + $new_user[] = htmlspecialchars($user); + } + $t->set('new_user', $new_user); + } + + $rightsval = array(); + foreach ($rights as $right => $val) { + $rightsval[] = array( + 'right' => $right, + 'desc' => $val['desc'], + 'title' => $val['title'] + ); + } + + $t->set('rights', $rightsval); + $t->set('width', round(100 / (count($rightsval) + 1)) . '%'); + + return $t->fetch(IMP_TEMPLATES . '/prefs/acl.html'); + } + + /** + * Update ACL related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateAclManagement($ui) + { + if ($ui->vars->change_acl_folder) { + return; + } + + $ACL = $GLOBALS['injector']->getInstance('IMP_Imap_Acl'); + + $acl_list = $ui->vars->acl; + $new_user = $ui->vars->new_user; + + /* Check to see if $new_user already has an acl on the folder. */ + if ($new_user && isset($acl_list[$new_user])) { + $acl_list[$new_user] = $ui->vars->new_acl; + } elseif ($new_user) { + try { + $ACL->editACL($ui->vars->folder, $new_user, $ui->vars->new_acl); + if (count($ui->vars->new_acl)) { + $GLOBALS['notification']->push(sprintf(_("User \"%s\" successfully given the specified rights for the folder \"%s\"."), $new_user, $ui->vars->folder), 'horde.success'); + } else { + $GLOBALS['notification']->push(sprintf(_("All rights on folder \"%s\" successfully removed for user \"%s\"."), $ui->vars->folder, $new_user), 'horde.success'); + } + } catch (Horde_Exception $e) { + $GLOBALS['notification']->push($e); + } + } + + $curr_acl = $ACL->getACL($ui->vars->folder); + $protected = $ACL->getProtected(); + + foreach ($acl_list as $user => $val) { + if ($val) { + $val = array_flip($val); + + /* We had to have an empty value submitted to make sure all + * users with acls were sent back, so we can remove those + * without checkmarks. */ + unset($val['']); + } else { + $val = array(); + } + + if (!$user) { + $GLOBALS['notification']->push(_("No user specified."), 'horde.error'); + continue; + } + + if (in_array($user, $protected)) { + if ($val) { + $GLOBALS['notification']->push(sprintf(_("Rights for user \"%s\" cannot be modified."), $user), 'horde.error'); + } + continue; + } + + /* Check to see if ACL changed. */ + if ((isset($curr_acl[$user])) && + (array_keys($curr_acl[$user]) == array_keys($val))) { + continue; + } + + try { + unset($curr_acl); + $ACL->editACL($ui->vars->folder, $user, $val); + if (!count($val)) { + $GLOBALS['notification']->push(sprintf(_("All rights on folder \"%s\" successfully removed for user \"%s\"."), $ui->vars->folder, $user), 'horde.success'); + } else { + $GLOBALS['notification']->push(sprintf(_("User \"%s\" successfully given the specified rights for the folder \"%s\"."), $user, $ui->vars->folder), 'horde.success'); + } + } catch (Horde_Exception $e) { + $GLOBALS['notification']->push($e); + } + } + } + + /* Drafts selection. */ + + /** + * Create code for drafts selection. + * + * @return string HTML UI code. + */ + protected function _drafts() + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('label', Horde::label('drafts', _("Drafts folder:"))); + $t->set('nofolder', IMP::PREF_NO_FOLDER); + $t->set('flist', IMP::flistSelect(array( + 'filter' => array('INBOX'), + 'heading' => _("Create a new drafts folder"), + 'new_folder' => true, + 'selected' => IMP::folderPref($GLOBALS['prefs']->getValue('drafts_folder'), true) + ))); + + return $t->fetch(IMP_TEMPLATES . '/prefs/drafts.html'); + } + + /* Message encryption selection. */ + + /** + * Create code for message encryption selection. + * + * @return string HTML UI code. + */ + protected function _encrypt() + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + + $t->set('label', Horde::label('default_encrypt', _("Your default encryption method for sending messages:"))); + $t->set('elist', IMP::encryptList()); + + return $t->fetch(IMP_TEMPLATES . '/prefs/encrypt.html'); + } + + /* IMAP Flag (keyword) management. */ + + /** + * Create code for flag management. + * + * @return string HTML UI code. + */ + protected function _flagManagement() + { + Horde::addInlineScript(array( + 'ImpFlagPrefs.new_prompt = ' . Horde_Serialize::serialize(_("Please enter the label for the new flag:"), Horde_Serialize::JSON, Horde_Nls::getCharset()), + 'ImpFlagPrefs.confirm_delete = ' . Horde_Serialize::serialize(_("Are you sure you want to delete this flag?"), Horde_Serialize::JSON, Horde_Nls::getCharset()) + )); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $out = array(); + $flaglist = $GLOBALS['injector']->getInstance('IMP_Imap_Flags')->getList(array('div' => true, 'fgcolor' => true)); + foreach ($flaglist as $key => $val) { + $hash = hash('md5', $key); + $bgid = 'bg_' . $hash; + $color = htmlspecialchars($val['b']); + $label = htmlspecialchars($val['l']); + $bgstyle = 'background-color:' . $color; + $tmp = array(); + + if ($val['t'] == 'imapp') { + $tmp['imapp'] = true; + $tmp['label_name'] = 'label_' . $hash; + $tmp['label'] = $label; + $tmp['icon'] = $bgstyle; + } else { + $tmp['label'] = Horde::label($bgid, $label); + $tmp['icon'] = $val['div']; + } + + $tmp['colorstyle'] = $bgstyle . ';color:' . htmlspecialchars($val['f']); + $tmp['colorid'] = $bgid; + $tmp['color'] = $color; + + $out[] = $tmp; + } + $t->set('flags', $out); + + $t->set('picker_img', Horde::img('colorpicker.png', _("Color Picker"))); + $t->set('flag_del', !empty($val['d'])); + + return $t->fetch(IMP_TEMPLATES . '/prefs/flags.html'); + } + + /** + * Update IMAP flag related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateFlagManagement($ui) + { + $imp_flags = $GLOBALS['injector']->getInstance('IMP_Imap_Flags'); + + if ($ui->vars->action == 'add') { + $GLOBALS['notification']->push(sprintf(_("Added flag \"%s\"."), $ui->vars->data), 'horde.success'); + $imp_flags->addFlag($ui->vars->data); + return; + } + + $def_color = $GLOBALS['prefs']->getValue('msgflags_color'); + + // Don't set updated on these actions. User may want to do more actions. + foreach ($imp_flags->getList() as $key => $val) { + $md5 = hash('md5', $key); + + switch ($ui->vars->action) { + case 'delete': + if ($ui->vars->data == ('bg_' . $md5)) { + $imp_flags->deleteFlag($key); + $GLOBALS['notification']->push(sprintf(_("Deleted flag \"%s\"."), $val['l']), 'horde.success'); + } + break; + + default: + /* Change labels for user-defined flags. */ + if ($val['t'] == 'imapp') { + $label = $ui->vars->get('label_' . $md5); + if (strlen($label) && ($label != $val['l'])) { + $imp_flags->updateFlag($key, array('l' => $label)); + } + } + + /* Change background for all flags. */ + $bg = strtolower($ui->vars->get('bg_' . $md5)); + if ((isset($val['b']) && ($bg != $val['b'])) || + (!isset($val['b']) && ($bg != $def_color))) { + $imp_flags->updateFlag($key, array('b' => $bg)); + } + break; + } + } + } + + /* Initial page selection. */ + + /** + * Create code for initial page selection. + * + * @return string HTML UI code. + */ + protected function _initialPage() + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + if (empty($GLOBALS['conf']['user']['allow_folders'])) { + $t->set('nofolder', true); + } else { + $mailbox_selected = $GLOBALS['prefs']->getValue('initial_page'); + $t->set('folder_sel', $mailbox_selected == 'folders.php'); + $t->set('flist', IMP::flistSelect(array( + 'inc_vfolder' => true, + 'selected' => $mailbox_selected + ))); + } + + $t->set('label', Horde::label('initial_page', _("View or mailbox to display after login:"))); + + return $t->fetch(IMP_TEMPLATES . '/prefs/initialpage.html'); + } + + /* PGP Private Key management. */ + + /** + * Create code for personal PGP key management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _pgpPrivateKey($ui) + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('personalkey-help', Horde_Help::link('imp', 'pgp-overview-personalkey')); + + if (!Horde::isConnectionSecure()) { + $t->set('notsecure', true); + } else { + $pgp_url = Horde::applicationUrl('pgp.php'); + + $t->set('has_key', $GLOBALS['prefs']->getValue('pgp_public_key') && $GLOBALS['prefs']->getValue('pgp_private_key')); + if ($t->get('has_key')) { + $t->set('viewpublic', Horde::link($pgp_url->copy()->add('actionID', 'view_personal_public_key'), _("View Personal Public Key"), null, 'view_key')); + $t->set('infopublic', Horde::link($pgp_url->copy()->add('actionID', 'info_personal_public_key'), _("Information on Personal Public Key"), null, 'info_key')); + $t->set('sendkey', Horde::link($ui->selfUrl(array('special' => true))->add('send_pgp_key', 1), _("Send Key to Public Keyserver"))); + $t->set('personalkey-public-help', Horde_Help::link('imp', 'pgp-personalkey-public')); + + $imple = Horde_Ajax_Imple::factory(array('imp', 'PassphraseDialog'), array('type' => 'pgpPersonal')); + $imple->attach(); + + $imp_pgp = $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp'); + $passphrase = $imp_pgp->getPassphrase('personal'); + $t->set('passphrase', empty($passphrase) ? Horde::link('#', _("Enter Passphrase"), null, null, null, null, null, array('id' => $imple->getPassphraseId())) . _("Enter Passphrase") : Horde::link($ui->selfUrl(array('special' => true))->add('unset_pgp_passphrase', 1), _("Unload Passphrase")) . _("Unload Passphrase")); + + $t->set('viewprivate', Horde::link($pgp_url->copy()->add('actionID', 'view_personal_private_key'), _("View Personal Private Key"), null, 'view_key')); + $t->set('infoprivate', Horde::link($pgp_url->copy()->add('actionID', 'info_personal_private_key'), _("Information on Personal Private Key"), null, 'info_key')); + $t->set('personalkey-private-help', Horde_Help::link('imp', 'pgp-personalkey-private')); + $t->set('deletekeypair', addslashes(_("Are you sure you want to delete your keypair? (This is NOT recommended!)"))); + $t->set('personalkey-delete-help', Horde_Help::link('imp', 'pgp-personalkey-delete')); + } else { + $imp_identity = Horde_Prefs_Identity::singleton(array('imp', 'imp')); + $t->set('fullname', $imp_identity->getFullname()); + $t->set('personalkey-create-name-help', Horde_Help::link('imp', 'pgp-personalkey-create-name')); + $t->set('personalkey-create-comment-help', Horde_Help::link('imp', 'pgp-personalkey-create-comment')); + $t->set('fromaddr', $imp_identity->getFromAddress()); + $t->set('personalkey-create-email-help', Horde_Help::link('imp', 'pgp-personalkey-create-email')); + $t->set('personalkey-create-keylength-help', Horde_Help::link('imp', 'pgp-personalkey-create-keylength')); + $t->set('personalkey-create-passphrase-help', Horde_Help::link('imp', 'pgp-personalkey-create-passphrase')); + $t->set('keygen', addslashes(_("Key generation may take a long time to complete. Continue with key generation?"))); + + if ($_SESSION['imp']['file_upload']) { + $cacheSess = Horde_SessionObjects::singleton(); + $t->set('import_url', Horde::popupJs($pgp_url, array('params' => array('actionID' => 'import_personal_public_key', 'reload' => $cacheSess->storeOid($ui->selfUrl()->setRaw(true), false)), 'height' => 275, 'width' => 750, 'urlencode' => true))); + } + + $t->set('personalkey-create-actions-help', Horde_Help::link('imp', 'pgp-personalkey-create-actions')); + } + } + + return $t->fetch(IMP_TEMPLATES . '/prefs/pgpprivatekey.html'); + } + + /** + * Update personal PGP related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updatePgpPrivateKey($ui) + { + if (isset($ui->vars->delete_pgp_privkey)) { + $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp')->deletePersonalKeys(); + $GLOBALS['notification']->push(_("Personal PGP keys deleted successfully."), 'horde.success'); + } elseif (isset($ui->vars->create_pgp_key)) { + /* Check that fields are filled out (except for Comment) and that + * the passphrases match. */ + if (empty($ui->vars->generate_realname) || + empty($ui->vars->generate_email)) { + $GLOBALS['notification']->push(_("Name and/or email cannot be empty"), 'horde.error'); + } elseif (empty($ui->vars->generate_passphrase1) || + empty($ui->vars->generate_passphrase2)) { + $GLOBALS['notification']->push(_("Passphrases cannot be empty"), 'horde.error'); + } elseif ($ui->vars->generate_passphrase1 !== $ui->vars->generate_passphrase2) { + $GLOBALS['notification']->push(_("Passphrases do not match"), 'horde.error'); + } else { + try { + $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp')->generatePersonalKeys($ui->vars->generate_realname, $ui->vars->generate_email, $ui->vars->generate_passphrase1, $ui->vars->_generate_comment, $ui->vars->generate_keylength); + $GLOBALS['notification']->push(_("Personal PGP keypair generated successfully."), 'horde.success'); + } catch (Exception $e) { + $GLOBALS['notification']->push($e); + } + } + } elseif (isset($ui->vars->send_pgp_key)) { + try { + $imp_pgp = $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp'); + $imp_pgp->sendToPublicKeyserver($imp_pgp->getPersonalPublicKey()); + $GLOBALS['notification']->push(_("Key successfully sent to the public keyserver."), 'horde.success'); + } catch (Exception $e) { + $GLOBALS['notification']->push($e); + } + } elseif (isset($ui->vars->unset_pgp_passphrase)) { + $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp')->unsetPassphrase('personal'); + $GLOBALS['notification']->push(_("PHP passphrase successfully unloaded."), 'horde.success'); + } + } + + /* PGP Public Key management. */ + + /** + * Create code for PGP public key management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _pgpPublicKey($ui) + { + $imp_pgp = $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp'); + + /* Get list of Public Keys on keyring. */ + try { + $pubkey_list = $imp_pgp->listPublicKeys(); + } catch (Horde_Exception $e) { + $pubkey_list = array(); + } + + $pgp_url = Horde::applicationUrl('pgp.php'); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('manage_pubkey-help', Horde_Help::link('imp', 'pgp-manage-pubkey')); + + if (!empty($pubkey_list)) { + $plist = array(); + $self_url = $ui->selfUrl(array('special' => true)); + + foreach ($pubkey_list as $val) { + $plist[] = array( + 'name' => $val['name'], + 'email' => $val['email'], + 'view' => Horde::link($pgp_url->copy()->add(array('actionID' => 'view_public_key', 'email' => $val['email'])), sprintf(_("View %s Public Key"), $val['name']), null, 'view_key'), + 'info' => Horde::link($pgp_url->copy()->add(array('actionID' => 'info_public_key', 'email' => $val['email'])), sprintf(_("Information on %s Public Key"), $val['name']), null, 'info_key'), + 'delete' => Horde::link($self_url->copy()->add(array('delete_pgp_pubkey' => 1, 'email' => $val['email'])), sprintf(_("Delete %s Public Key"), $val['name']), null, null, "confirm('" . addslashes(_("Are you sure you want to delete this public key?")) . "')") + ); + } + $t->set('pubkey_list', $plist); + } + + if ($_SESSION['imp']['file_upload']) { + $t->set('no_source', !$GLOBALS['prefs']->getValue('add_source')); + if (!$t->get('no_source')) { + $cacheSess = Horde_SessionObjects::singleton(); + $t->set('import_url', Horde::popupJs($pgp_url, array('params' => array('actionID' => 'import_public_key', 'reload' => $cacheSess->storeOid($ui->selfUrl()->setRaw(true), false)), 'height' => 275, 'width' => 750, 'urlencode' => true))); + $t->set('import_pubkey-help', Horde_Help::link('imp', 'pgp-import-pubkey')); + } + } + + return $t->fetch(IMP_TEMPLATES . '/prefs/pgppublickey.html'); + } + + /** + * Update PGP public key related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updatePgpPublicKey($ui) + { + if (isset($ui->vars->delete_pgp_pubkey)) { + try { + $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp')->deletePublicKey($ui->vars->email); + $GLOBALS['notification']->push(sprintf(_("PGP Public Key for \"%s\" was successfully deleted."), $ui->vars->email), 'horde.success'); + } catch (Horde_Exception $e) { + $GLOBALS['notification']->push($e); + } + } + } + + /* Sentmail selection. */ + + /** + * Create code for sentmail selection. + * + * @return string HTML UI code. + */ + protected function _sentmail() + { + Horde::addInlineScript(array( + 'ImpFolderPrefs.folders = ' . Horde_Serialize::serialize(array('sent_mail_folder', 'sent_mail_new', _("Enter the name for your new sent-mail folder"), _("Create a new sent-mail folder")), Horde_Serialize::JSON, Horde_Nls::getCharset()) + )); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('label', Horde::label('sent_mail_folder', _("Sent mail folder:"))); + $t->set('flist', IMP::flistSelect(array( + 'filter' => array('INBOX'), + 'heading' => _("Create a new sent mail folder") + ))); + + return $t->fetch(IMP_TEMPLATES . '/prefs/sentmail.html'); + } + + /** + * Update sentmail related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return boolean True if preferences were updated. + */ + protected function _updateSentmail($ui) + { + if (!$GLOBALS['conf']['user']['allow_folders'] || + $GLOBALS['prefs']->isLocked('sent_mail_folder')) { + return false; + } + + $sent_mail_folder = $ui->vars->sent_mail_folder; + $sent_mail_new = Horde_String::convertCharset($ui->vars->sent_mail_new, Horde_Nls::getCharset(), 'UTF7-IMAP'); + $sent_mail_default = $GLOBALS['prefs']->getValue('sent_mail_folder'); + + if (empty($sent_mail_folder) && !empty($sent_mail_new)) { + $sent_mail_folder = $GLOBALS['imp_imap']->appendNamespace($sent_mail_new); + } elseif (($sent_mail_folder == '-1') && !empty($sent_mail_default)) { + $sent_mail_folder = $GLOBALS['imp_imap']->appendNamespace($sent_mail_default); + } + + if (!empty($sent_mail_folder)) { + $imp_folder = $GLOBALS['injector']->getInstance('IMP_Folder'); + if (!$imp_folder->exists($sent_mail_folder)) { + $imp_folder->create($sent_mail_folder, $GLOBALS['prefs']->getValue('subscribe')); + } + } + + $imp_identity = Horde_Prefs_Identity::singleton(array('imp', 'imp')); + $imp_identity->setValue('sent_mail_folder', IMP::folderPref($sent_mail_folder, false)); + + return true; + } + + /* Personal S/MIME certificate management. */ + + /** + * Create code for personal S/MIME certificate management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _smimePrivateKey($ui) + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('personalkey-help', Horde_Help::link('imp', 'smime-overview-personalkey')); + + if (!Horde::isConnectionSecure()) { + $t->set('notsecure', true); + } else { + $smime_url = Horde::applicationUrl('smime.php'); + + $t->set('has_key', $GLOBALS['prefs']->getValue('smime_public_key') && $GLOBALS['prefs']->getValue('smime_private_key')); + if ($t->get('has_key')) { + $t->set('viewpublic', Horde::link($smime_url->copy()->add('actionID', 'view_personal_public_key'), _("View Personal Public Certificate"), null, 'view_key')); + $t->set('infopublic', Horde::link($smime_url->copy()->add('actionID', 'info_personal_public_key'), _("Information on Personal Public Certificate"), null, 'info_key')); + + $imple = Horde_Ajax_Imple::factory(array('imp', 'PassphraseDialog'), array('type' => 'smimePersonal')); + $imple->attach(); + + $imp_smime = $GLOBALS['injector']->getInstance('IMP_Crypt_Smime'); + $passphrase = $imp_smime->getPassphrase(); + $t->set('passphrase', empty($passphrase) ? Horde::link('#', _("Enter Passphrase"), null, null, null, null, null, array('id' => $imple->getPassphraseId())) . _("Enter Passphrase") : Horde::link($ui->selfUrl(array('special' => true))->add('unset_smime_passphrase', 1), _("Unload Passphrase")) . _("Unload Passphrase")); + + $t->set('viewprivate', Horde::link($smime_url->copy()->add('actionID', 'view_personal_private_key'), _("View Personal Private Key"), null, 'view_key')); + $t->set('deletekeypair', addslashes(_("Are you sure you want to delete your keypair? (This is NOT recommended!)"))); + $t->set('personalkey-delete-help', Horde_Help::link('imp', 'smime-delete-personal-certs')); + } elseif ($_SESSION['imp']['file_upload']) { + $cacheSess = Horde_SessionObjects::singleton(); + $t->set('import_url', Horde::popupJs($smime_url, array('params' => array('actionID' => 'import_personal_public_key', 'reload' => $cacheSess->storeOid($ui->selfUrl()->setRaw(true), false)), 'height' => 275, 'width' => 750, 'urlencode' => true))); + $t->set('import-cert-help', Horde_Help::link('imp', 'smime-import-personal-certs')); + } + } + + return $t->fetch(IMP_TEMPLATES . '/prefs/smimeprivatekey.html'); + } + + /** + * Update personal S/MIME certificate related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateSmimePrivateKey($ui) + { + if (isset($ui->vars->delete_smime_personal)) { + $GLOBALS['injector']->getInstance('IMP_Crypt_Smime')->deletePersonalKeys(); + $GLOBALS['notification']->push(_("Personal S/MIME keys deleted successfully."), 'horde.success'); + } elseif (isset($ui->vars->unset_smime_passphrase)) { + $GLOBALS['injector']->getInstance('IMP_Crypt_Smime')->unsetPassphrase(); + $GLOBALS['notification']->push(_("S/MIME passphrase successfully unloaded."), 'horde.success'); + } + } + + /* S/MIME public certificate management. */ + + /** + * Create code for S/MIME public certificate management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _smimePublicKey($ui) + { + $imp_smime = $GLOBALS['injector']->getInstance('IMP_Crypt_Smime'); + + /* Get list of Public Keys on keyring. */ + try { + $pubkey_list = $imp_smime->listPublicKeys(); + } catch (Horde_Exception $e) { + $pubkey_list = array(); + } + + $smime_url = Horde::applicationUrl('smime.php'); + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('manage_pubkey-help', Horde_Help::link('imp', 'smime-manage-pubkey')); + + if (!empty($pubkey_list)) { + $plist = array(); + $self_url = $ui->selfUrl(array('special' => true)); + + foreach ($pubkey_list as $val) { + $plist[] = array( + 'name' => $val['name'], + 'email' => $val['email'], + 'view' => Horde::link($smime_url->copy()->add(array('actionID' => 'view_public_key', 'email' => $val['email'])), sprintf(_("View %s Public Key"), $val['name']), null, 'view_key'), + 'info' => Horde::link($smime_url->copy()->add(array('actionID' => 'info_public_key', 'email' => $val['email'])), sprintf(_("Information on %s Public Key"), $val['name']), null, 'info_key'), + 'delete' => Horde::link($self_url->copy()->add(array('delete_smime_pubkey' => 1, 'email' => $val['email'])), sprintf(_("Delete %s Public Key"), $val['name']), null, null, "confirm('" . addslashes(_("Are you sure you want to delete this public key?")) . "')") + ); + } + $t->set('pubkey_list', $plist); + } + + if ($_SESSION['imp']['file_upload']) { + $t->set('no_source', !$GLOBALS['prefs']->getValue('add_source')); + if (!$t->get('no_source')) { + $cacheSess = Horde_SessionObjects::singleton(); + $t->set('import_url', Horde::popupJs($smime_url, array('params' => array('actionID' => 'import_public_key', 'reload' => $cacheSess->storeOid($ui->selfUrl()->setRaw(true), false)), 'height' => 275, 'width' => 750, 'urlencode' => true))); + $t->set('import_pubkey-help', Horde_Help::link('imp', 'smime-import-pubkey')); + } + } + + return $t->fetch(IMP_TEMPLATES . '/prefs/smimepublickey.html'); + } + + /** + * Update S/MIME public key related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateSmimePublicKey($ui) + { + if (isset($ui->vars->delete_smime_pubkey)) { + try { + $GLOBALS['injector']->getInstance('IMP_Crypt_Smime')->deletePublicKey($ui->vars->email); + $GLOBALS['notification']->push(sprintf(_("S/MIME Public Key for \"%s\" was successfully deleted."), $ui->vars->email), 'horde.success'); + } catch (Horde_Exception $e) { + $GLOBALS['notification']->push($e); + } + } + } + + /* Sound selection. */ + + /** + * Create code for sound selection. + * + * @return string HTML UI code. + */ + protected function _sound() + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $nav_audio = $GLOBALS['prefs']->getValue('nav_audio'); + + $t->set('nav_audio', $nav_audio); + + $sounds = array(); + foreach (Horde_Themes::soundList() as $key => $val) { + $sounds[] = array( + 'c' => ($nav_audio == $key), + 'l' => htmlspecialchars($key), + 's' => htmlspecialchars($val->uri), + 'v' => htmlspecialchars($key) + ); + } + $t->set('sounds', $sounds); + + return $t->fetch(IMP_TEMPLATES . '/prefs/sound.html'); + } + + /* Spam selection. */ + + /** + * Create code for spam selection. + * + * @return string HTML UI code. + */ + protected function _spam() + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $t->set('label', Horde::label('spam', _("Spam folder:"))); + $t->set('nofolder', IMP::PREF_NO_FOLDER); + $t->set('flist', IMP::flistSelect(array( + 'filter' => array('INBOX'), + 'heading' => _("Create a new Spam folder"), + 'new_folder' => true, + 'selected' => IMP::folderPref($GLOBALS['prefs']->getValue('spam_folder'), true) + ))); + + return $t->fetch(IMP_TEMPLATES . '/prefs/spam.html'); + } + + /* Stationery management. */ + + /** + * Create code for stationery management. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return string HTML UI code. + */ + protected function _stationeryManagement($ui) + { + $ob = $this->_parseStationeryVars($ui); + + if ($ob->stationery['t'] == 'html') { + $GLOBALS['injector']->getInstance('Horde_Editor')->getEditor('Ckeditor', array('id' => 'content')); + } + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $slist = array(); + foreach ($ob->stationery_list as $key => $choice) { + $slist[] = array( + 'selected' => ($ob->selected === $key), + 'text' => $choice['n'] . ' ' . ($choice['t'] == 'html' ? _("(HTML)") : _("(Plain Text)")), + 'val' => $key + ); + } + $t->set('slist', $slist); + + $t->set('selected', strlen($ob->selected)); + $t->set('last_type', $ob->stationery['t']); + $t->set('name_label', Horde::label('name', _("Stationery name:"))); + $t->set('name', $ob->stationery['n']); + $t->set('type_label', Horde::label('name', _("Stationery type:"))); + $t->set('plain', $ob->stationery['t'] == 'plain'); + $t->set('html', $ob->stationery['t'] == 'html'); + $t->set('content_label', Horde::label('content', _("Stationery:"))); + $t->set('content', $ob->stationery['c']); + + return $t->fetch(IMP_TEMPLATES . '/prefs/stationery.html'); + } + + /** + * Update stationery related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + */ + protected function _updateStationeryManagement($ui) + { + $updated = false; + + if ($ui->vars->delete) { + /* Delete stationery. */ + $ob = $this->_parseStationeryVars($ui); + + if (isset($ob->stationery_list[$ob->selected])) { + $updated = sprintf(_("The stationery \"%s\" has been deleted."), $ob->stationery_list[$ob->selected]['n']); + unset($ob->stationery_list[$ob->selected]); + } + } elseif ($ui->vars->save) { + /* Saving stationery. */ + $ob = $this->_parseStationeryVars($ui); + + if (strlen($ob->selected)) { + $ob->stationery_list[$ob->selected] = $ob->stationery; + $updated = sprintf(_("The stationery \"%s\" has been updated."), $ob->stationery['n']); + } else { + $ob->stationery_list[] = $ob->stationery; + $updated = sprintf(_("The stationery \"%s\" has been added."), $ob->stationery['n']); + } + } + + if ($updated) { + $GLOBALS['prefs']->setValue('stationery', serialize(Horde_String::convertCharset(array_values($ob->stationery_list), Horde_Nls::getCharset(), $GLOBALS['prefs']->getCharset())), false); + $GLOBALS['notification']->push($updated, 'horde.success'); + } + } + + /** + * Parse the variables for the stationery management screen. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return object Object with the following properties: + *
+     * 'selected' - (integer) The currently selected value.
+     * 'stationery' - (array) The current stationery entry.
+     * 'stationery_list' - (array) The list of all stationery values.
+     * 
+ */ + protected function _parseStationeryVars($ui) + { + $ob = new stdClass; + + $ob->selected = strlen($ui->vars->stationery) + ? intval($ui->vars->stationery) + : null; + + $stationery_list = @unserialize($GLOBALS['prefs']->getValue('stationery', false)); + $ob->stationery_list = is_array($stationery_list) + ? Horde_String::convertCharset($stationery_list, $GLOBALS['prefs']->getCharset()) + : array(); + + $content = strval($ui->vars->content); + $type = isset($ui->vars->type) + ? $ui->vars->type + : 'plain'; + + if ($ui->vars->last_type != $type) { + $content = ($type == 'plain') + ? Horde_Text_Filter::filter($content, 'Html2text', array('charset' => Horde_Nls::getCharset())) + : nl2br(htmlspecialchars(htmlspecialchars($content))); + } + + $ob->stationery = array( + 'c' => $content, + 'n' => strval($ui->vars->name), + 't' => $type + ); + + return $ob; + } + + /* Trash selection. */ + + /** + * Create code for trash selection. + * + * @return string HTML UI code. + */ + protected function _trash() + { + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + + $use_vtrash = $GLOBALS['prefs']->getValue('use_vtrash'); + + $t->set('label', Horde::label('trash', _("Trash folder:"))); + $t->set('nofolder', IMP::PREF_NO_FOLDER); + $t->set('vtrash', IMP::PREF_VTRASH); + $t->set('vtrash_select', $use_vtrash); + $t->set('flist', IMP::flistSelect(array( + 'filter' => array('INBOX'), + 'heading' => _("Create a new trash folder"), + 'new_folder' => true, + 'selected' => ($use_vtrash ? null : IMP::folderPref($GLOBALS['prefs']->getValue('trash_folder'), true)) + ))); + + return $t->fetch(IMP_TEMPLATES . '/prefs/trash.html'); + } + + /** + * Update trash related preferences. + * + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return boolean True if preferences were updated. + */ + protected function _updateTrash($ui) + { + global $prefs; + + if ($ui->vars->trash == IMP::PREF_VTRASH) { + if ($prefs->isLocked('use_vtrash')) { + return false; + } + + $prefs->setValue('use_vtrash', 1); + $prefs->setValue('trash_folder', ''); + } else { + if ($prefs->isLocked('trash_folder')) { + return false; + } + + if ($this->_updateSpecialFolders('trash_folder', $ui->vars->trash, $ui->vars->trash_new, $ui)) { + $prefs->setValue('use_vtrash', 0); + $prefs->setDirty('trash_folder', true); + return true; + } + } + } + + /* Utility functions. */ + + /** + * Update special folder preferences. + * + * @param string $pref The pref name to update. + * @param string $folder The old name. + * @param string $new The new name. + * @param Horde_Core_Prefs_Ui $ui The UI object. + * + * @return boolean True if preferences were updated. + */ + protected function _updateSpecialFolders($pref, $folder, $new, $ui) + { + global $prefs; + + if (!$GLOBALS['conf']['user']['allow_folders'] || + (strlen($folder) == 0) || + $prefs->isLocked($pref)) { + return false; + } + + $new = Horde_String::convertCharset($new, Horde_Nls::getCharset(), 'UTF7-IMAP'); + + if ($folder == IMP::PREF_NO_FOLDER) { + $prefs->setValue($pref, ''); + } else { + if (empty($folder) && !empty($new)) { + $folder = $GLOBALS['imp_imap']->appendNamespace($new); + if (!$GLOBALS['injector']->getInstance('IMP_Folder')->create($folder, $GLOBALS['prefs']->getValue('subscribe'))) { + $folder = null; + } + } + + if (!empty($folder)) { + $prefs->setValue($pref, IMP::folderPref($folder, false)); + return true; + } + } + } + +} diff --git a/imp/pgp.php b/imp/pgp.php index c1f8cda2a..1402b5ef1 100644 --- a/imp/pgp.php +++ b/imp/pgp.php @@ -1,6 +1,6 @@ getInstance('IMP_Crypt_Pgp'); +$imp_pgp = $injector->getInstance('IMP_Crypt_Pgp'); $secure_check = Horde::isConnectionSecure(); +$vars = Horde_Variables::getDefaultVariables(); /* Run through the action handlers */ -$actionID = Horde_Util::getFormData('actionID'); -switch ($actionID) { -case 'generate_key': - /* Check that fields are filled out (except for Comment) and that the - passphrases match. */ - $realname = Horde_Util::getFormData('generate_realname'); - $email = Horde_Util::getFormData('generate_email'); - $comment = Horde_Util::getFormData('generate_comment'); - $keylength = Horde_Util::getFormData('generate_keylength'); - $passphrase1 = Horde_Util::getFormData('generate_passphrase1'); - $passphrase2 = Horde_Util::getFormData('generate_passphrase2'); - - if (empty($realname) || empty($email)) { - $notification->push(_("Name and/or email cannot be empty"), 'horde.error'); - } elseif (empty($passphrase1) || empty($passphrase2)) { - $notification->push(_("Passphrases cannot be empty"), 'horde.error'); - } elseif ($passphrase1 !== $passphrase2) { - $notification->push(_("Passphrases do not match"), 'horde.error'); - } else { - try { - $imp_pgp->generatePersonalKeys($realname, $email, $passphrase1, $comment, $keylength); - $notification->push(_("Personal PGP keypair generated successfully."), 'horde.success'); - } catch (Horde_Exception $e) { - $notification->push($e); - } - } - break; - -case 'delete_key': - $imp_pgp->deletePersonalKeys(); - $notification->push(_("Personal PGP keys deleted successfully."), 'horde.success'); - break; - +switch ($vars->actionID) { case 'import_public_key': - $imp_pgp->importKeyDialog('process_import_public_key', Horde_Util::getFormData('reload')); - exit; + $imp_pgp->importKeyDialog('process_import_public_key', $vars->reload); + break; case 'process_import_public_key': try { - $publicKey = $imp_pgp->getImportKey(Horde_Util::getFormData('import_key')); + $publicKey = $imp_pgp->getImportKey($vars->import_key); /* Add the public key to the storage system. */ $key_info = $imp_pgp->addPublicKey($publicKey); foreach ($key_info['signature'] as $sig) { $notification->push(sprintf(_("PGP Public Key for \"%s (%s)\" was successfully added."), $sig['name'], $sig['email']), 'horde.success'); } - $imp_pgp->reloadWindow(Horde_Util::getFormData('reload')); + $imp_pgp->reloadWindow($vars->reload); } catch (Horde_Browser_Exception $e) { $notification->push(_("No PGP public key imported."), 'horde.error'); throw new Horde_Exception_Prior($e); } catch (Horde_Exception $e) { $notification->push($e); - $actionID = 'import_public_key'; - $imp_pgp->importKeyDialog('process_import_public_key', Horde_Util::getFormData('reload')); + $vars->actionID = 'import_public_key'; + $imp_pgp->importKeyDialog('process_import_public_key', $vars->reload); } - exit; + break; case 'import_personal_public_key': - $imp_pgp->importKeyDialog('process_import_personal_public_key', Horde_Util::getFormData('reload')); - exit; + $imp_pgp->importKeyDialog('process_import_personal_public_key', $vars->reload); + break; case 'process_import_personal_public_key': - $actionID = 'import_personal_public_key'; + $vars->actionID = 'import_personal_public_key'; /* Check the public key. */ try { - $publicKey = $imp_pgp->getImportKey(Horde_Util::getFormData('import_key')); + $publicKey = $imp_pgp->getImportKey($vars->import_key); if (($key_info = $imp_pgp->pgpPacketInformation($publicKey)) && isset($key_info['public_key'])) { if (isset($key_info['secret_key'])) { /* Key contains private key too, don't allow to add this * as public key. */ $notification->push(_("Imported key contains your PGP private key. Only add your public key in the first step!"), 'horde.error'); - $imp_pgp->importKeyDialog('process_import_personal_public_key', Horde_Util::getFormData('reload')); + $imp_pgp->importKeyDialog('process_import_personal_public_key', $vars->reload); } else { /* Success in importing public key - Move on to private * key now. */ $imp_pgp->addPersonalPublicKey($publicKey); $notification->push(_("PGP public key successfully added."), 'horde.success'); - $actionID = 'import_personal_private_key'; - $imp_pgp->importKeyDialog('process_import_personal_private_key', Horde_Util::getFormData('reload')); + $vars->actionID = 'import_personal_private_key'; + $imp_pgp->importKeyDialog('process_import_personal_private_key', $vars->reload); } } else { /* Invalid public key imported - Redo public key import * screen. */ $notification->push(_("Invalid personal PGP public key."), 'horde.error'); - $imp_pgp->importKeyDialog('process_import_personal_public_key', Horde_Util::getFormData('reload')); + $imp_pgp->importKeyDialog('process_import_personal_public_key', $vars->reload); } } catch (Horde_Browser_Exception $e) { $notification->push(_("No personal PGP public key imported."), 'horde.error'); throw new Horde_Exception_Prior($e); } catch (Horde_Exception $e) { $notification->push($e); - $imp_pgp->importKeyDialog('process_import_personal_public_key', Horde_Util::getFormData('reload')); + $imp_pgp->importKeyDialog('process_import_personal_public_key', $vars->reload); } - exit; + break; case 'process_import_personal_private_key': - $actionID = 'import_personal_private_key'; + $vars->actionID = 'import_personal_private_key'; /* Check the private key. */ try { - $privateKey = $imp_pgp->getImportKey(Horde_Util::getFormData('import_key')); + $privateKey = $imp_pgp->getImportKey($vars->import_key); if (($key_info = $imp_pgp->pgpPacketInformation($privateKey)) && isset($key_info['secret_key'])) { /* Personal public and private keys have been imported * successfully - close the import popup window. */ $imp_pgp->addPersonalPrivateKey($privateKey); $notification->push(_("PGP private key successfully added."), 'horde.success'); - $imp_pgp->reloadWindow(Horde_Util::getFormData('reload')); + $imp_pgp->reloadWindow($vars->reload); } else { /* Invalid private key imported - Redo private key import * screen. */ $notification->push(_("Invalid personal PGP private key."), 'horde.error'); - $imp_pgp->importKeyDialog('process_import_personal_private_key', Horde_Util::getFormData('reload')); + $imp_pgp->importKeyDialog('process_import_personal_private_key', $vars->reload); } } catch (Horde_Browser_Exception $e) { $notification->push(_("No personal PGP private key imported."), 'horde.error'); throw new Horde_Exception_Prior($e); } catch (Horde_Exception $e) { $notification->push($e); - $imp_pgp->importKeyDialog('process_import_personal_private_key', Horde_Util::getFormData('reload')); + $imp_pgp->importKeyDialog('process_import_personal_private_key', $vars->reload); } - exit; + break; case 'view_public_key': case 'info_public_key': try { - $key = $imp_pgp->getPublicKey(Horde_Util::getFormData('email'), array('noserver' => true)); + $key = $imp_pgp->getPublicKey($vars->email, array('noserver' => true)); } catch (Horde_Exception $e) { $key = $e->getMessage(); } - if ($actionID == 'view_public_key') { + if ($vars->actionID == 'view_public_key') { $imp_pgp->textWindowOutput('PGP Public Key', $key); } else { $imp_pgp->printKeyInfo($key); } - exit; + break; case 'view_personal_public_key': $imp_pgp->textWindowOutput('PGP Personal Public Key', $imp_pgp->getPersonalPublicKey()); - exit; + break; case 'info_personal_public_key': $imp_pgp->printKeyInfo($imp_pgp->getPersonalPublicKey()); - exit; + break; case 'view_personal_private_key': $imp_pgp->textWindowOutput('PGP Personal Private Key', $imp_pgp->getPersonalPrivateKey()); - exit; + break; case 'info_personal_private_key': $imp_pgp->printKeyInfo($imp_pgp->getPersonalPrivateKey()); - exit; - -case 'delete_public_key': - try { - $imp_pgp->deletePublicKey(Horde_Util::getFormData('email')); - $notification->push(sprintf(_("PGP Public Key for \"%s\" was successfully deleted."), Horde_Util::getFormData('email')), 'horde.success'); - } catch (Horde_Exception $e) { - $notification->push($e); - } - break; - -case 'save_options': - $prefs->setValue('use_pgp', Horde_Util::getFormData('use_pgp') ? 1 : 0); - $prefs->setValue('pgp_attach_pubkey', Horde_Util::getFormData('pgp_attach_pubkey') ? 1 : 0); - $prefs->setValue('pgp_scan_body', Horde_Util::getFormData('pgp_scan_body') ? 1 : 0); - $prefs->setValue('pgp_verify', Horde_Util::getFormData('pgp_verify') ? 1 : 0); - $notification->push(_("Preferences successfully updated."), 'horde.success'); break; case 'save_attachment_public_key': /* Retrieve the key from the message. */ - $contents = IMP_Contents::singleton(Horde_Util::getFormData('uid') . IMP::IDX_SEP . Horde_Util::getFormData('mailbox')); - $mime_part = $contents->getMIMEPart(Horde_Util::getFormData('mime_id')); + $contents = IMP_Contents::singleton($vars->uid . IMP::IDX_SEP . $vars->mailbox); + $mime_part = $contents->getMIMEPart($vars->mime_id); if (empty($mime_part)) { throw new IMP_Exception('Cannot retrieve public key from message.'); } @@ -202,131 +154,5 @@ case 'save_attachment_public_key': } catch (Horde_Exception $e) { $notification->push($e, $key_info->getCode()); } - exit; - -case 'unset_passphrase': - $imp_pgp->unsetPassphrase('personal'); - $notification->push(_("Passphrase successfully unloaded."), 'horde.success'); - break; - -case 'send_public_key': - try { - $imp_pgp->sendToPublicKeyserver($imp_pgp->getPersonalPublicKey()); - $notification->push(_("Key successfully sent to the public keyserver."), 'horde.success'); - } catch (Horde_Exception $e) { - $notification->push($e); - } break; } - -$selfURL = Horde::applicationUrl('pgp.php'); - -/* Get list of Public Keys on keyring. */ -try { - $pubkey_list = $imp_pgp->listPublicKeys(); -} catch (Horde_Exception $e) { - $pubkey_list = array(); - $notification->push($e); -} - -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('imp', null, 'pgp', $chunk); - -/* If PGP preference not active, do NOT show PGP Admin screen. */ -$t = $injector->createInstance('Horde_Template'); -$t->setOption('gettext', true); -if ($prefs->getValue('use_pgp')) { - Horde::addScriptFile('imp.js', 'imp'); - $t->set('pgpactive', true); - $t->set('overview-help', Horde_Help::link('imp', 'pgp-overview')); - $t->set('attach_pubkey_notlocked', !$prefs->isLocked('pgp_attach_pubkey')); - if ($t->get('attach_pubkey_notlocked')) { - $t->set('attach_pubkey', $prefs->getValue('pgp_attach_pubkey')); - $t->set('attach_pubkey-help', Horde_Help::link('imp', 'pgp-option-attach-pubkey')); - } - $t->set('scan_body_notlocked', !$prefs->isLocked('pgp_scan_body')); - if ($t->get('scan_body_notlocked')) { - $t->set('scan_body', $prefs->getValue('pgp_scan_body')); - $t->set('scan_body-help', Horde_Help::link('imp', 'pgp-option-scan-body')); - } - $t->set('verify_notlocked', !$prefs->isLocked('pgp_verify')); - if ($t->get('verify_notlocked')) { - $t->set('pgp_verify', $prefs->getValue('pgp_verify')); - $t->set('pgp_verify-help', Horde_Help::link('imp', 'pgp-option-verify')); - } - $t->set('manage_pubkey-help', Horde_Help::link('imp', 'pgp-manage-pubkey')); - - $t->set('empty_pubkey_list', empty($pubkey_list)); - if (!$t->get('empty_pubkey_list')) { - $plist = array(); - foreach ($pubkey_list as $val) { - $linkurl = $selfURL->copy()->add('email', $val['email']); - $plist[] = array( - 'name' => $val['name'], - 'email' => $val['email'], - 'view' => Horde::link($linkurl->copy()->add('actionID', 'view_public_key'), sprintf(_("View %s Public Key"), $val['name']), null, 'view_key'), - 'info' => Horde::link($linkurl->copy()->add('actionID', 'info_public_key'), sprintf(_("Information on %s Public Key"), $val['name']), null, 'info_key'), - 'delete' => Horde::link($linkurl->copy()->add('actionID', 'delete_public_key'), sprintf(_("Delete %s Public Key"), $val['name']), null, null, "if (confirm('" . addslashes(_("Are you sure you want to delete this public key?")) . "')) { return true; } else { return false; }") - ); - } - $t->set('pubkey_list', $plist); - } - - $t->set('no_file_upload', !$_SESSION['imp']['file_upload']); - if (!$t->get('no_file_upload')) { - $t->set('no_source', !$GLOBALS['prefs']->getValue('add_source')); - if (!$t->get('no_source')) { - $cacheSess = Horde_SessionObjects::singleton(); - $t->set('public_import_url', Horde::popupJs($selfURL, array('params' => array('actionID' => 'import_public_key', 'reload' => $cacheSess->storeOid($selfURL, false)), 'height' => 275, 'width' => 750, 'urlencode' => true))); - $t->set('import_pubkey-help', Horde_Help::link('imp', 'pgp-import-pubkey')); - } - } - $t->set('personalkey-help', Horde_Help::link('imp', 'pgp-overview-personalkey')); - - $t->set('secure_check', !$secure_check); - if ($secure_check) { - $t->set('has_key', $prefs->getValue('pgp_public_key') && $prefs->getValue('pgp_private_key')); - if ($t->get('has_key')) { - $t->set('viewpublic', Horde::link($selfURL->copy()->add('actionID', 'view_personal_public_key'), _("View Personal Public Key"), null, 'view_key')); - $t->set('infopublic', Horde::link($selfURL->copy()->add('actionID', 'info_personal_public_key'), _("Information on Personal Public Key"), null, 'info_key')); - $t->set('sendkey', Horde::link($selfURL->copy()->add('actionID', 'send_public_key'), _("Send Key to Public Keyserver"))); - $t->set('personalkey-public-help', Horde_Help::link('imp', 'pgp-personalkey-public')); - - $imple = Horde_Ajax_Imple::factory(array('imp', 'PassphraseDialog'), array('type' => 'pgpPersonal')); - $imple->attach(); - $passphrase = $imp_pgp->getPassphrase('personal'); - $t->set('passphrase', (empty($passphrase)) ? Horde::link('#', _("Enter Passphrase"), null, null, null, null, null, array('id' => $imple->getPassphraseId())) . _("Enter Passphrase") : Horde::link($selfURL->copy()->add('actionID', 'unset_passphrase'), _("Unload Passphrase")) . _("Unload Passphrase")); - - $t->set('viewprivate', Horde::link($selfURL->copy()->add('actionID', 'view_personal_private_key'), _("View Personal Private Key"), null, 'view_key')); - $t->set('infoprivate', Horde::link($selfURL->copy()->add('actionID', 'info_personal_private_key'), _("Information on Personal Private Key"), null, 'info_key')); - $t->set('personalkey-private-help', Horde_Help::link('imp', 'pgp-personalkey-private')); - $t->set('deletekeypair', addslashes(_("Are you sure you want to delete your keypair? (This is NOT recommended!)"))); - $t->set('personalkey-delete-help', Horde_Help::link('imp', 'pgp-personalkey-delete')); - } else { - $imp_identity = Horde_Prefs_Identity::singleton(array('imp', 'imp')); - $t->set('fullname', $imp_identity->getFullname()); - $t->set('personalkey-create-name-help', Horde_Help::link('imp', 'pgp-personalkey-create-name')); - $t->set('personalkey-create-comment-help', Horde_Help::link('imp', 'pgp-personalkey-create-comment')); - $t->set('fromaddr', $imp_identity->getFromAddress()); - $t->set('personalkey-create-email-help', Horde_Help::link('imp', 'pgp-personalkey-create-email')); - $t->set('personalkey-create-keylength-help', Horde_Help::link('imp', 'pgp-personalkey-create-keylength')); - $t->set('personalkey-create-passphrase-help', Horde_Help::link('imp', 'pgp-personalkey-create-passphrase')); - $t->set('keygen', addslashes(_("Key generation may take a long time to complete. Continue with key generation?"))); - $t->set('personal_import_url', Horde::popupJs($selfURL, array('params' => array('actionID' => 'import_personal_public_key'), 'height' => 275, 'width' => 750, 'urlencode' => true))); - $t->set('personalkey-create-actions-help', Horde_Help::link('imp', 'pgp-personalkey-create-actions')); - } - } - -} else { - $t->set('use_pgp_locked', $prefs->isLocked('use_pgp')); - if (!$t->get('use_pgp_locked')) { - $t->set('use_pgp_label', Horde::label('use_pgp', _("Enable PGP functionality?"))); - $t->set('use_pgp_help', Horde_Help::link('imp', 'pgp-overview')); - } -} -$t->set('prefsurl', Horde::getServiceLink('options', 'imp')); - -echo $t->fetch(IMP_TEMPLATES . '/prefs/pgp/pgp.html'); -if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-footer.inc'; -} diff --git a/imp/smime.php b/imp/smime.php index 84ec9d507..4be7867b5 100644 --- a/imp/smime.php +++ b/imp/smime.php @@ -1,6 +1,6 @@ getInstance('IMP_Crypt_Smime'); +$imp_smime = $injector->getInstance('IMP_Crypt_Smime'); +$vars = Horde_Variables::getDefaultVariables(); /* Run through the action handlers */ -$actionID = Horde_Util::getFormData('actionID'); -switch ($actionID) { -case 'delete_key': - $imp_smime->deletePersonalKeys(); - $notification->push(_("Personal S/MIME keys deleted successfully."), 'horde.success'); - break; - -case 'delete_public_key': - try { - $imp_smime->deletePublicKey(Horde_Util::getFormData('email')); - $notification->push(sprintf(_("S/MIME Public Key for \"%s\" was successfully deleted."), Horde_Util::getFormData('email')), 'horde.success'); - } catch (Horde_Exception $e) { - $notification->push($e); - } - break; - +switch ($vars->actionID) { case 'import_public_key': - $imp_smime->importKeyDialog('process_import_public_key', Horde_Util::getFormData('reload')); + $imp_smime->importKeyDialog('process_import_public_key', $vars->reload); exit; case 'process_import_public_key': try { - $publicKey = $imp_smime->getImportKey(Horde_Util::getFormData('import_key')); + $publicKey = $imp_smime->getImportKey($vars->import_key); /* Add the public key to the storage system. */ $imp_smime->addPublicKey($publicKey); $notification->push(_("S/MIME Public Key successfully added."), 'horde.success'); - $imp_smime->reloadWindow(Horde_Util::getFormData('reload')); + $imp_smime->reloadWindow($vars->reload); } catch (Horde_Browser_Exception $e) { $notification->push(_("No S/MIME public key imported."), 'horde.error'); throw new Horde_Exception_Prior($e); } catch (Horde_Exception $e) { $notification->push($e); - $actionID = 'import_public_key'; - $imp_smime->importKeyDialog('process_import_public_key', Horde_Util::getFormData('reload')); + $vars->actionID = 'import_public_key'; + $imp_smime->importKeyDialog('process_import_public_key', $vars->reload); } exit; case 'view_public_key': case 'info_public_key': try { - $key = $imp_smime->getPublicKey(Horde_Util::getFormData('email')); + $key = $imp_smime->getPublicKey($vars->email); } catch (Horde_Exception $e) { $key = $e->getMessage(); } - if ($actionID == 'view_public_key') { + if ($vars->actionID == 'view_public_key') { $imp_smime->textWindowOutput('S/MIME Public Key', $key); } else { $imp_smime->printCertInfo($key); @@ -83,28 +69,28 @@ case 'view_personal_private_key': exit; case 'import_personal_certs': - $imp_smime->importKeyDialog('process_import_personal_certs', Horde_Util::getFormData('reload')); + $imp_smime->importKeyDialog('process_import_personal_certs', $vars->reload); exit; case 'process_import_personal_certs': try { - $pkcs12 = $imp_smime->getImportKey(Horde_Util::getFormData('import_key')); - $imp_smime->addFromPKCS12($pkcs12, Horde_Util::getFormData('upload_key_pass'), Horde_Util::getFormData('upload_key_pk_pass')); + $pkcs12 = $imp_smime->getImportKey($vars->import_key); + $imp_smime->addFromPKCS12($pkcs12, $vars->upload_key_pass, $vars->upload_key_pk_pass); $notification->push(_("S/MIME Public/Private Keypair successfully added."), 'horde.success'); - $imp_smime->reloadWindow(Horde_Util::getFormData('reload')); + $imp_smime->reloadWindow($vars->reload); } catch (Horde_Browser_Exception $e) { throw new Horde_Exception_Prior($e); } catch (Horde_Exception $e) { $notification->push(_("Personal S/MIME certificates NOT imported: ") . $e->getMessage(), 'horde.error'); - $actionID = 'import_personal_certs'; - $imp_smime->importKeyDialog('process_import_personal_certs', Horde_Util::getFormData('reload')); + $vars->actionID = 'import_personal_certs'; + $imp_smime->importKeyDialog('process_import_personal_certs', $vars->reload); } exit; case 'save_attachment_public_key': /* Retrieve the key from the message. */ - $contents = IMP_Contents::singleton(Horde_Util::getFormData('uid') . IMP::IDX_SEP . Horde_Util::getFormData('mailbox')); - $mime_part = $contents->getMIMEPart(Horde_Util::getFormData('mime_id')); + $contents = IMP_Contents::singleton($vars->uid . IMP::IDX_SEP . $vars->mailbox); + $mime_part = $contents->getMIMEPart($vars->mime_id); if (empty($mime_part)) { throw new IMP_Exception('Cannot retrieve public key from message.'); } @@ -117,113 +103,4 @@ case 'save_attachment_public_key': $notification->push(_("No Certificate found"), 'horde.error'); } exit; - -case 'unset_passphrase': - if ($imp_smime->getPassphrase() !== false) { - $imp_smime->unsetPassphrase(); - $notification->push(_("Passphrase successfully unloaded."), 'horde.success'); - } - break; - -case 'save_options': - $prefs->setValue('use_smime', Horde_Util::getFormData('use_smime') ? 1 : 0); - $prefs->setValue('smime_verify', Horde_Util::getFormData('smime_verify') ? 1 : 0); - $notification->push(_("Preferences successfully updated."), 'horde.success'); - break; -} - -/* Get list of Public Keys. */ -try { - $pubkey_list = $imp_smime->listPublicKeys(); -} catch (Horde_Exception $e) { - $pubkey_list = array(); - $notification->push($e); -} - -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('imp', null, 'smime', $chunk); - -$selfURL = Horde::applicationUrl('smime.php'); - -/* If S/MIME preference not active, or openssl PHP extension not available, do - * NOT show S/MIME Admin screen. */ -try { - $imp_smime->checkForOpenSSL(); - $openssl_check = true; -} catch (Horde_Exception $e) { - $openssl_check = false; -} - -/* If S/MIME preference not active, do NOT show S/MIME Admin screen. */ -$t = $injector->createInstance('Horde_Template'); -$t->setOption('gettext', true); -$t->set('use_smime_help', Horde_Help::link('imp', 'smime-overview')); -if ($openssl_check && $prefs->getValue('use_smime')) { - Horde::addScriptFile('imp.js', 'imp'); - $t->set('smimeactive', true); - $t->set('manage_pubkey-help', Horde_Help::link('imp', 'smime-manage-pubkey')); - - $t->set('verify_notlocked', !$prefs->isLocked('smime_verify')); - if ($t->get('verify_notlocked')) { - $t->set('smime_verify', $prefs->getValue('smime_verify')); - $t->set('smime_verify-help', Horde_Help::link('imp', 'smime-option-verify')); - } - - $t->set('empty_pubkey_list', empty($pubkey_list)); - if (!$t->get('empty_pubkey_list')) { - $plist = array(); - foreach ($pubkey_list as $val) { - $linkurl = $selfURL->copy()->add('email', $val['email']); - $plist[] = array( - 'name' => $val['name'], - 'email' => $val['email'], - 'view' => Horde::link($linkurl->copy()->add('actionID', 'view_public_key'), sprintf(_("View %s Public Key"), $val['name']), null, 'view_key'), - 'info' => Horde::link($linkurl->copy()->add('actionID', 'info_public_key'), sprintf(_("Information on %s Public Key"), $val['name']), null, 'info_key'), - 'delete' => Horde::link($linkurl->copy()->add('actionID', 'delete_public_key'), sprintf(_("Delete %s Public Key"), $val['name']), null, null, "if (confirm('" . addslashes(_("Are you sure you want to delete this public key?")) . "')) { return true; } else { return false; }") - ); - } - $t->set('pubkey_list', $plist); - } - - $t->set('no_file_upload', !$_SESSION['imp']['file_upload']); - if (!$t->get('no_file_upload')) { - $t->set('no_source', !$GLOBALS['prefs']->getValue('add_source')); - if (!$t->get('no_source')) { - $cacheSess = Horde_SessionObjects::singleton(); - $t->set('public_import_url', Horde::popupJs($selfURL, array('params' => array('actionID' => 'import_public_key', 'reload' => $cacheSess->storeOid($selfURL, false)), 'height' => 275, 'width' => 750, 'urlencode' => true))); - $t->set('import_pubkey-help', Horde_Help::link('imp', 'smime-import-pubkey')); - } - } - $t->set('personalkey-help', Horde_Help::link('imp', 'smime-overview-personalkey')); - - $t->set('secure_check', Horde::isConnectionSecure()); - if ($t->get('secure_check')) { - $t->set('has_key', $prefs->getValue('smime_public_key') && $prefs->getValue('smime_private_key')); - if ($t->get('has_key')) { - $t->set('viewpublic', Horde::link($selfURL->copy()->add('actionID', 'view_personal_public_key'), _("View Personal Public Key"), null, 'view_key')); - $t->set('infopublic', Horde::link($selfURL->copy()->add('actionID', 'info_personal_public_key'), _("Information on Personal Public Key"), null, 'info_key')); - $imple = Horde_Ajax_Imple::factory(array('imp', 'PassphraseDialog'), array('type' => 'smimePersonal')); - $imple->attach(); - $passphrase = $imp_smime->getPassphrase(); - $t->set('passphrase', (empty($passphrase)) ? Horde::link('#', _("Enter Passphrase"), null, null, null, null, null, array('id' => $imple->getPassphraseId())) . _("Enter Passphrase") : Horde::link($selfURL->copy()->add('actionID', 'unset_passphrase'), _("Unload Passphrase")) . _("Unload Passphrase")); - - $t->set('viewprivate', Horde::link($selfURL->copy()->add('actionID', 'view_personal_private_key'), _("View Personal Private Key"), null, 'view_key')); - $t->set('deletekeypair', addslashes(_("Are you sure you want to delete your keypair? (This is NOT recommended!)"))); - $t->set('personalkey-delete-help', Horde_Help::link('imp', 'smime-delete-personal-certs')); - } else { - $t->set('personal_import_url', Horde::popupJs($selfURL, array('params' => array('actionID' => 'import_personal_certs'), 'height' => 275, 'width' => 750, 'urlencode' => true))); - $t->set('import-cert-help', Horde_Help::link('imp', 'smime-import-personal-certs')); - } - } -} else { - $t->set('use_smime_locked', $prefs->isLocked('use_smime')); - if (!$t->get('use_smime_locked')) { - $t->set('use_smime_label', Horde::label('use_smime', _("Enable S/MIME functionality?"))); - } -} -$t->set('prefsurl', Horde::getServiceLink('options', 'imp')); - -echo $t->fetch(IMP_TEMPLATES . '/prefs/smime/smime.html'); -if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-footer.inc'; } diff --git a/imp/stationery.php b/imp/stationery.php deleted file mode 100644 index 27bf6945f..000000000 --- a/imp/stationery.php +++ /dev/null @@ -1,137 +0,0 @@ - - * @package IMP - */ - -require_once dirname(__FILE__) . '/lib/Application.php'; -Horde_Registry::appInit('imp', array('authentication' => 'horde')); - -$compose_url = Horde::getServiceLink('options', 'imp'); - -/* Is the preference locked? */ -if ($prefs->isLocked('stationery')) { - header('Location: ' . $compose_url); - exit; -} - -/* Retrieve stationery. */ -$stationery_list = @unserialize($prefs->getValue('stationery', false)); -$stationery_list = is_array($stationery_list) - ? Horde_String::convertCharset($stationery_list, $prefs->getCharset()) - : array(); - -/* Get form data. */ -$selected = Horde_Util::getFormData('stationery'); -if (strlen($selected)) { - $selected = (int)$selected; -} - -/* Always check for stationery type switches. */ -$content = Horde_Util::getFormData('content', ''); -$last_type = Horde_Util::getFormData('last_type'); -$name = Horde_Util::getFormData('name', ''); -$type = Horde_Util::getFormData('type', 'plain'); -if (!empty($last_type) && $last_type != $type) { - $content = ($type == 'plain') - ? Horde_Text_Filter::filter($content, 'Html2text', array('charset' => Horde_Nls::getCharset())) - : nl2br(htmlspecialchars(htmlspecialchars($content))); -} -$stationery = array('n' => $name, 't' => $type, 'c' => $content); - -/* Run through the action handlers. */ -$actionID = Horde_Util::getFormData('actionID'); -$updated = false; -switch ($actionID) { -case 'update': - if (Horde_Util::getFormData('edit')) { - /* Stationery has been switched. */ - if (strlen($selected)) { - /* Edit existing. */ - $stationery = array( - 'n' => $stationery_list[$selected]['n'], - 't' => $stationery_list[$selected]['t'], - 'c' => $stationery_list[$selected]['c'] - ); - } else { - $stationery = array( - 'n' => '', - 't' => 'plain', - 'c' => '' - ); - } - } elseif (Horde_Util::getFormData('delete')) { - /* Delete stationery. */ - if (isset($stationery_list[$selected])) { - $updated = sprintf(_("The stationery \"%s\" has been deleted."), $stationery_list[$selected]['n']); - unset($stationery_list[$selected]); - $selected = null; - } - $stationery = array( - 'n' => '', - 't' => 'plain', - 'c' => '' - ); - } elseif (Horde_Util::getFormData('save')) { - /* Saving stationery. */ - if (!strlen($selected)) { - $selected = count($stationery_list); - $stationery_list[] = $stationery; - $updated = sprintf(_("The stationery \"%s\" has been added."), $stationery['n']); - } else { - $stationery_list[$selected] = $stationery; - $updated = sprintf(_("The stationery \"%s\" has been updated."), $stationery['n']); - } - } - break; -} - -if ($updated) { - $prefs->setValue('stationery', serialize(Horde_String::convertCharset($stationery_list, Horde_Nls::getCharset(), $prefs->getCharset())), false); - $notification->push($updated, 'horde.success'); -} - -if ($stationery['t'] == 'html') { - $injector->getInstance('Horde_Editor')->getEditor('Ckeditor', array('id' => 'content')); -} - -/* Show the header. */ -$chunk = Horde_Util::nonInputVar('chunk'); -Horde_Prefs_Ui::generateHeader('imp', null, null, $chunk); - -$t = $injector->createInstance('Horde_Template'); -$t->setOption('gettext', true); -$t->set('action', Horde::selfUrl()); -$t->set('forminput', Horde_Util::formInput()); -$t->set('navcell', Horde_Util::bufferOutput(array('Horde_Prefs_Ui', 'generateNavigationCell'), 'imp', 'compose')); - -$slist = array(); -foreach ($stationery_list as $key => $choice) { - $slist[] = array( - 'val' => $key, - 'selected' => ($selected === $key), - 'text' => $choice['n'] . ' ' . ($choice['t'] == 'html' ? _("(HTML)") : _("(Plain Text)")) - ); -} -$t->set('slist', $slist); -$t->set('selected', strlen($selected)); -$t->set('last_type', $stationery['t']); -$t->set('name_label', Horde::label('name', _("Stationery name:"))); -$t->set('name', $stationery['n']); -$t->set('type_label', Horde::label('name', _("Stationery type:"))); -$t->set('plain', $stationery['t'] == 'plain'); -$t->set('html', $stationery['t'] == 'html'); -$t->set('content_label', Horde::label('content', _("Stationery:"))); -$t->set('content', $stationery['c']); -$t->set('button_href', $compose_url->copy()->add('group', 'compose')); -$t->set('button_val', htmlspecialchars(_("Return to Message Composition"), ENT_COMPAT, Horde_Nls::getCharset())); - -echo $t->fetch(IMP_TEMPLATES . '/prefs/stationery/stationery.html'); -if (!$chunk) { - require $registry->get('templates', 'horde') . '/common-footer.inc'; -} diff --git a/imp/templates/imp/acl/acl.html b/imp/templates/imp/acl/acl.html deleted file mode 100644 index 9fd0a26df..000000000 --- a/imp/templates/imp/acl/acl.html +++ /dev/null @@ -1,102 +0,0 @@ -
- - - -
- - Share mail folders -
- -
-
    -
  • - - -
  • -
- -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- The current list of users with access to this folder could not be retrieved. -  
- -  
-

User

-
-

-
- - disabled="disabled" name="acl[][]" value="" disabled="disabled" checked="checked" /> -
- - - -
 
- - - -  
- You do not have permission to change access to this folder. -  
- -  
- diff --git a/imp/templates/pgp/import_key.html b/imp/templates/pgp/import_key.html new file mode 100644 index 000000000..823311590 --- /dev/null +++ b/imp/templates/pgp/import_key.html @@ -0,0 +1,56 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Import Public PGP KeyImport Personal Public PGP KeyImport Personal Private PGP Key
+ + + + + + + +
+ +
+
--OR--
+ + + + +
+   + +
+
+ + +
+ + + + diff --git a/imp/templates/prefs/accounts.html b/imp/templates/prefs/accounts.html new file mode 100644 index 000000000..f7135e5d3 --- /dev/null +++ b/imp/templates/prefs/accounts.html @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Label:
Type: + + *
Server:*
Username:*
Port:
Use secure connection? + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LabelServerTypePortSecure?
AutoYesNo
No accounts configured
+ + +
diff --git a/imp/templates/prefs/accountsmanagement.inc b/imp/templates/prefs/accountsmanagement.inc deleted file mode 100644 index 05eb85cad..000000000 --- a/imp/templates/prefs/accountsmanagement.inc +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
:
: - - *
:*
:*
:
- -
- -" /> -" /> - -getInstance('IMP_Accounts')->getList(); -$delete_img = Horde::img('delete.png'); -?> - - - - - - - - - - - - - - - - - - - $val): ?> - - - - - - - - - - - - - - - - - -
?
- -" /> - diff --git a/imp/templates/prefs/acl.html b/imp/templates/prefs/acl.html new file mode 100644 index 000000000..b7d47867e --- /dev/null +++ b/imp/templates/prefs/acl.html @@ -0,0 +1,79 @@ + + +
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ The current list of users with access to this folder could not be retrieved. +
+

User

+
+

+
+ + disabled="disabled" name="acl[][]" value="" disabled="disabled" checked="checked" /> +
+ + + + + + + + +
+ You do not have permission to change access to this folder. +
+ +
+ + + +
diff --git a/imp/templates/prefs/drafts.html b/imp/templates/prefs/drafts.html new file mode 100644 index 000000000..dc253dcc8 --- /dev/null +++ b/imp/templates/prefs/drafts.html @@ -0,0 +1,12 @@ +
+
+ +
+
+ + +
+
diff --git a/imp/templates/prefs/draftsselect.inc b/imp/templates/prefs/draftsselect.inc deleted file mode 100644 index 499ccd433..000000000 --- a/imp/templates/prefs/draftsselect.inc +++ /dev/null @@ -1,12 +0,0 @@ -
-
- -
-
- - -
-
diff --git a/imp/templates/prefs/encrypt.html b/imp/templates/prefs/encrypt.html new file mode 100644 index 000000000..ae2f85b6c --- /dev/null +++ b/imp/templates/prefs/encrypt.html @@ -0,0 +1,10 @@ +
+
+ +
+
+ +
+
diff --git a/imp/templates/prefs/encryptselect.inc b/imp/templates/prefs/encryptselect.inc deleted file mode 100644 index 8bfc7d0fc..000000000 --- a/imp/templates/prefs/encryptselect.inc +++ /dev/null @@ -1,8 +0,0 @@ -
-
-
- -
-
diff --git a/imp/templates/prefs/filters/filters.html b/imp/templates/prefs/filters/filters.html deleted file mode 100644 index 5864cc1a9..000000000 --- a/imp/templates/prefs/filters/filters.html +++ /dev/null @@ -1,37 +0,0 @@ -
- Filter Settings -
- - -
- Filter support is disabled on this system. - -

-
- -
-
- - - - - - -    
-
- - -
- -checked="checked" />    
-
- -

-    - -

-
- - -
-
diff --git a/imp/templates/prefs/flagmanagement.inc b/imp/templates/prefs/flagmanagement.inc deleted file mode 100644 index b3a11ca4d..000000000 --- a/imp/templates/prefs/flagmanagement.inc +++ /dev/null @@ -1,54 +0,0 @@ -getInstance('IMP_Imap_Flags')->getList(array('div' => true, 'fgcolor' => true)); - -/* Get the graphics. */ -$picker_img = Horde::img('colorpicker.png', _("Color Picker")); - -?> - - - - - - - - - - - - $val): - $hash = hash('md5', $key); - $bgid = 'bg_' . $hash; - $color = htmlspecialchars($val['b']); - $fgcolor = htmlspecialchars($val['f']); - $label = htmlspecialchars($val['l']); - $bgstyle = 'background-color:' . $color; -?> - - - - - - - -
LabelIconColor
- - - - - - - -
- - - -
- - - - - -
-" /> diff --git a/imp/templates/prefs/flags.html b/imp/templates/prefs/flags.html new file mode 100644 index 000000000..0fdd4fe12 --- /dev/null +++ b/imp/templates/prefs/flags.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + +
LabelIconColor
+ + + + + + + +
+ + +
+
+ + + + + +
+ diff --git a/imp/templates/prefs/initialpage.html b/imp/templates/prefs/initialpage.html new file mode 100644 index 000000000..88e6bf8c1 --- /dev/null +++ b/imp/templates/prefs/initialpage.html @@ -0,0 +1,15 @@ +
+
+ +
+
+ +
+
diff --git a/imp/templates/prefs/initialpageselect.inc b/imp/templates/prefs/initialpageselect.inc deleted file mode 100644 index 1dc7b6587..000000000 --- a/imp/templates/prefs/initialpageselect.inc +++ /dev/null @@ -1,23 +0,0 @@ -' . _("Inbox") . ''; -} else { - $mailbox_selected = $prefs->getValue('initial_page'); - $mailbox_option = '