From 0d69a0076ef7e6da85afff8bfaa82f917424bcf6 Mon Sep 17 00:00:00 2001 From: Michael M Slusarz Date: Fri, 20 Aug 2010 16:47:28 -0600 Subject: [PATCH] Add support for setting/retrieving special-use mailboxes from IMAP server --- imp/docs/CHANGES | 2 + imp/docs/RFCS | 5 +- imp/lib/Folder.php | 33 ++++++++++++- imp/lib/Prefs/Ui.php | 98 ++++++++++++++++++++++++++++--------- imp/templates/prefs/drafts.html | 1 + imp/templates/prefs/sentmail.html | 1 + imp/templates/prefs/spam.html | 1 + imp/templates/prefs/specialuse.html | 5 ++ imp/templates/prefs/trash.html | 1 + 9 files changed, 122 insertions(+), 25 deletions(-) create mode 100644 imp/templates/prefs/specialuse.html diff --git a/imp/docs/CHANGES b/imp/docs/CHANGES index 9e99a7c38..8a6154bfb 100644 --- a/imp/docs/CHANGES +++ b/imp/docs/CHANGES @@ -2,6 +2,8 @@ v5.0-git -------- +[mms] Add support for setting/retrieving special-use mailboxes from IMAP + server. [mms] Add preference to control if we check for recipient PGP public keys when replying (Request #7962). [mms] Add preference to allow for automatic spam reporting when explicitly diff --git a/imp/docs/RFCS b/imp/docs/RFCS index e81860b04..91d50437d 100644 --- a/imp/docs/RFCS +++ b/imp/docs/RFCS @@ -51,8 +51,9 @@ RFC 5530 IMAP Response Codes RFC 5550 Lemonade Profile (specifically [2.8] - $Forwarded flag) RFC 5819 LIST-STATUS -draft-ietf-morg-sortdisplay-02 SORT=DISPLAY -draft-ietf-morg-inthread-00 THREAD=REFS +draft-ietf-morg-list-specialuse-02 CREATE-SPECIAL-USE +draft-ietf-morg-sortdisplay-02 SORT=DISPLAY +draft-ietf-morg-inthread-00 THREAD=REFS POP3 diff --git a/imp/lib/Folder.php b/imp/lib/Folder.php index 560ea4d06..f8534baa1 100644 --- a/imp/lib/Folder.php +++ b/imp/lib/Folder.php @@ -20,6 +20,18 @@ class IMP_Folder { /** + * Mapping of special-use keys to their IMP equivalents. + * + * @var array + */ + static public $specialUse = array( + 'drafts' => '\\drafts', + 'sent' => '\\sent', + 'spam' => '\\junk', + 'trash' => '\\trash' + ); + + /** * Keep around identical lists so that we don't hit the server more that * once in the same page for the same thing. * @@ -212,6 +224,17 @@ class IMP_Folder * * @param string $folder The folder to be created (UTF7-IMAP). * @param boolean $subscribe Subscribe to folder? + * @param array $opts Additional options: + *
+     * 'drafts' - (boolean) Is this a drafts mailbox?
+     *            DEFAULT: false
+     * 'spam' - (boolean) Is this a spam mailbox?
+     *          DEFAULT: false
+     * 'sent' - (boolean) Is this a sent-mail mailbox?
+     *          DEFAULT: false
+     * 'trash' - (boolean) Is this a trash mailbox?
+     *          DEFAULT: false
+     * 
* * @return boolean Whether or not the folder was successfully created. * @throws Horde_Exception @@ -245,9 +268,17 @@ class IMP_Folder return false; } + /* Special use flags. */ + $special_use = array(); + foreach ($this->specialUse as $key => $val) { + if (!empty($this->_opts[$key])) { + $special_use[] = $val; + } + } + /* Attempt to create the mailbox. */ try { - $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->createMailbox($folder); + $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->createMailbox($folder, array('special_use' => $special_use)); } catch (Horde_Imap_Client_Exception $e) { $notification->push(sprintf(_("The folder \"%s\" was not created. This is what the server said"), IMP::displayFolder($folder)) . ': ' . $e->getMessage(), 'horde.error'); return false; diff --git a/imp/lib/Prefs/Ui.php b/imp/lib/Prefs/Ui.php index 7b6954d75..ff1a9b945 100644 --- a/imp/lib/Prefs/Ui.php +++ b/imp/lib/Prefs/Ui.php @@ -14,6 +14,16 @@ */ class IMP_Prefs_Ui { + /* Mailbox identifiers. */ + const FLIST_SPECIALUSE = "specialuse\0"; + + /** + * Cached folder list. + * + * @var array + */ + protected $_cache = null; + /** * Populate dynamically-generated preference values. * @@ -430,7 +440,7 @@ class IMP_Prefs_Ui return false; case 'draftsselect': - return $this->_updateSpecialFolders('drafts_folder', IMP::formMbox($ui->vars->drafts, false), $ui->vars->drafts_folder_new, $ui); + return $this->_updateSpecialFolders('drafts_folder', IMP::formMbox($ui->vars->drafts, false), $ui->vars->drafts_folder_new, 'drafts', $ui); case 'encryptselect': return $prefs->setValue('default_encrypt', $ui->vars->default_encrypt); @@ -471,7 +481,7 @@ class IMP_Prefs_Ui return $this->_updateSource($ui); case 'spamselect': - return $this->_updateSpecialFolders('spam_folder', IMP::formMbox($ui->vars->spam, false), $ui->vars->spam_new, $ui); + return $this->_updateSpecialFolders('spam_folder', IMP::formMbox($ui->vars->spam, false), $ui->vars->spam_new, 'spam', $ui); case 'stationerymanagement': return $this->_updateStationeryManagement($ui); @@ -870,6 +880,7 @@ class IMP_Prefs_Ui 'new_folder' => true, 'selected' => IMP::folderPref($GLOBALS['prefs']->getValue('drafts_folder'), true) ))); + $t->set('special_use', $this->_getSpecialUse(IMP_Folder::$specialUse['drafts'])); return $t->fetch(IMP_TEMPLATES . '/prefs/drafts.html'); } @@ -1253,6 +1264,7 @@ class IMP_Prefs_Ui 'filter' => array('INBOX'), 'new_folder' => true ))); + $t->set('special_use', $this->_getSpecialUse(IMP_Folder::$specialUse['sentmail'])); return $t->fetch(IMP_TEMPLATES . '/prefs/sentmail.html'); } @@ -1275,16 +1287,20 @@ class IMP_Prefs_Ui $sent_mail_folder = IMP::formMbox($ui->vars->sent_mail_folder, false); if (empty($sent_mail_folder) && $ui->vars->sent_mail_folder_new) { - $sent_mail_folder = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->appendNamespace(Horde_String::convertCharset($ui->vars->sent_mail_folder_new, $GLOBALS['registry']->getCharset(), 'UTF7-IMAP')); + $sent_mail_folder = Horde_String::convertCharset($ui->vars->sent_mail_folder_new, $GLOBALS['registry']->getCharset(), 'UTF7-IMAP'); + } elseif (strpos($sent_mail_folder, self::FLIST_SPECIALUSE) === 0) { + $sent_mail_folder = substr($folder, strlen(self::FLIST_SPECIALUSE)); } elseif (($sent_mail_folder == IMP::PREF_DEFAULT) && ($sm_default = $prefs->getDefault('sent_mail_folder'))) { - $sent_mail_folder = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->appendNamespace($sm_default); + $sent_mail_folder = $sm_default; } + $sent_mail_folder = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->appendNamespace($sent_mail_folder); + if ($sent_mail_folder) { $imp_folder = $GLOBALS['injector']->getInstance('IMP_Folder'); if (!$imp_folder->exists($sent_mail_folder) && - !$imp_folder->create($sent_mail_folder, $prefs->getValue('subscribe'))) { + !$imp_folder->create($sent_mail_folder, $prefs->getValue('subscribe'), array('sent' => true))) { return false; } } @@ -1542,6 +1558,7 @@ class IMP_Prefs_Ui 'new_folder' => true, 'selected' => IMP::folderPref($GLOBALS['prefs']->getValue('spam_folder'), true) ))); + $t->set('special_use', $this->_getSpecialUse(IMP_Folder::$specialUse['junk'])); return $t->fetch(IMP_TEMPLATES . '/prefs/spam.html'); } @@ -1693,6 +1710,7 @@ class IMP_Prefs_Ui 'new_folder' => true, 'selected' => ($use_vtrash ? null : IMP::folderPref($GLOBALS['prefs']->getValue('trash_folder'), true)) ))); + $t->set('special_use', $this->_getSpecialUse(IMP_Folder::$specialUse['trash'])); return $t->fetch(IMP_TEMPLATES . '/prefs/trash.html'); } @@ -1711,23 +1729,18 @@ class IMP_Prefs_Ui $trash = IMP::formMbox($ui->vars->trash, false); if ($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', $trash, $ui->vars->trash_new, $ui)) { - $prefs->setValue('use_vtrash', 0); - $prefs->setDirty('trash_folder', true); + if (!$prefs->isLocked('use_vtrash')) { + $prefs->setValue('use_vtrash', 1); + $prefs->setValue('trash_folder', ''); return true; } + } elseif ($this->_updateSpecialFolders('trash_folder', $trash, $ui->vars->trash_new, 'trash', $ui)) { + $prefs->setValue('use_vtrash', 0); + $prefs->setDirty('trash_folder', true); + return true; } + + return false; } /* Utility functions. */ @@ -1738,11 +1751,12 @@ class IMP_Prefs_Ui * @param string $pref The pref name to update. * @param string $folder The old name. * @param string $new The new name. + * @param string $type Folder type: 'drafts', 'spam', 'trash'. * @param Horde_Core_Prefs_Ui $ui The UI object. * * @return boolean True if preferences were updated. */ - protected function _updateSpecialFolders($pref, $folder, $new, $ui) + protected function _updateSpecialFolders($pref, $folder, $new, $type, $ui) { global $prefs; @@ -1755,10 +1769,12 @@ class IMP_Prefs_Ui return $prefs->setValue($pref, ''); } - if (!empty($new)) { + if (strpos($folder, self::FLIST_SPECIALUSE) === 0) { + $folder = substr($folder, strlen(self::FLIST_SPECIALUSE)); + } elseif (!empty($new)) { $new = Horde_String::convertCharset($new, $GLOBALS['registry']->getCharset(), 'UTF7-IMAP'); $folder = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->appendNamespace($new); - if (!$GLOBALS['injector']->getInstance('IMP_Folder')->create($folder, $prefs->getValue('subscribe'))) { + if (!$GLOBALS['injector']->getInstance('IMP_Folder')->create($folder, $prefs->getValue('subscribe'), array($type => true))) { $folder = null; } } @@ -1768,4 +1784,42 @@ class IMP_Prefs_Ui : false; } + /** + * Get the list of special use mailboxes of a certain type. + * + * @param string $use The special-use flag. + * + * @return string HTML code. + */ + protected function _getSpecialUse($use) + { + if (is_null($this->_cache)) { + $this->_cache = $GLOBALS['injector']->getInstance('IMP_Imap')->getOb()->listMailboxes('*', Horde_Imap_Client::MBOX_ALL, array( + 'attributes' => true, + 'special_use' => true, + 'sort' => true + )); + } + + $special_use = array(); + foreach ($this->_cache as $key => $val) { + if (in_array($use, $val['attributes'])) { + $special_use[] = array( + 'l' => htmlspecialchars(IMP::getLabel($val)), + 'v' => IMP::formMbox(FLIST_SPECIALUSE . $key, true) + ); + } + } + + if (empty($special_use)) { + return ''; + } + + $t = $GLOBALS['injector']->createInstance('Horde_Template'); + $t->setOption('gettext', true); + $t->set('special_use', $special_use); + + return $t->fetch(IMP_TEMPLATES . '/prefs/specialuse.html'); + } + } diff --git a/imp/templates/prefs/drafts.html b/imp/templates/prefs/drafts.html index f47179912..ddc999fde 100644 --- a/imp/templates/prefs/drafts.html +++ b/imp/templates/prefs/drafts.html @@ -5,6 +5,7 @@
diff --git a/imp/templates/prefs/sentmail.html b/imp/templates/prefs/sentmail.html index 16c6f9211..b24ffd03b 100644 --- a/imp/templates/prefs/sentmail.html +++ b/imp/templates/prefs/sentmail.html @@ -6,6 +6,7 @@ diff --git a/imp/templates/prefs/spam.html b/imp/templates/prefs/spam.html index d3d9ae699..6ceb5d89f 100644 --- a/imp/templates/prefs/spam.html +++ b/imp/templates/prefs/spam.html @@ -5,6 +5,7 @@
diff --git a/imp/templates/prefs/specialuse.html b/imp/templates/prefs/specialuse.html new file mode 100644 index 000000000..cf34f3389 --- /dev/null +++ b/imp/templates/prefs/specialuse.html @@ -0,0 +1,5 @@ + + + + + diff --git a/imp/templates/prefs/trash.html b/imp/templates/prefs/trash.html index 3706418f5..5994d6990 100644 --- a/imp/templates/prefs/trash.html +++ b/imp/templates/prefs/trash.html @@ -6,6 +6,7 @@ -- 2.11.0