Overview

Packages

  • IMP

Classes

  • IMP
  • IMP_Ajax_Addresses
  • IMP_Ajax_Application
  • IMP_Ajax_Application_Compose
  • IMP_Ajax_Application_Handler_Common
  • IMP_Ajax_Application_Handler_ComposeAttach
  • IMP_Ajax_Application_Handler_Draft
  • IMP_Ajax_Application_Handler_Dynamic
  • IMP_Ajax_Application_Handler_ImageUnblock
  • IMP_Ajax_Application_Handler_Mboxtoggle
  • IMP_Ajax_Application_Handler_Passphrase
  • IMP_Ajax_Application_Handler_Remote
  • IMP_Ajax_Application_Handler_RemotePrefs
  • IMP_Ajax_Application_Handler_Search
  • IMP_Ajax_Application_Handler_Smartmobile
  • IMP_Ajax_Application_ListMessages
  • IMP_Ajax_Application_ShowMessage
  • IMP_Ajax_Application_Viewport
  • IMP_Ajax_Application_Viewport_Error
  • IMP_Ajax_Imple_ImportEncryptKey
  • IMP_Ajax_Imple_ItipRequest
  • IMP_Ajax_Imple_PassphraseDialog
  • IMP_Ajax_Imple_VcardImport
  • IMP_Ajax_Queue
  • IMP_Api
  • IMP_Application
  • IMP_Auth
  • IMP_Basic_Base
  • IMP_Basic_Compose
  • IMP_Basic_Contacts
  • IMP_Basic_Error
  • IMP_Basic_Folders
  • IMP_Basic_Listinfo
  • IMP_Basic_Mailbox
  • IMP_Basic_Message
  • IMP_Basic_Pgp
  • IMP_Basic_Saveimage
  • IMP_Basic_Search
  • IMP_Basic_Searchbasic
  • IMP_Basic_Smime
  • IMP_Basic_Thread
  • IMP_Block_Newmail
  • IMP_Block_Summary
  • IMP_Compose
  • IMP_Compose_Attachment
  • IMP_Compose_Attachment_Linked_Metadata
  • IMP_Compose_Attachment_Metadata
  • IMP_Compose_Attachment_Storage
  • IMP_Compose_Attachment_Storage_AutoDetermine
  • IMP_Compose_Attachment_Storage_Temp
  • IMP_Compose_Attachment_Storage_VfsLinked
  • IMP_Compose_Exception
  • IMP_Compose_Exception_Address
  • IMP_Compose_HtmlSignature
  • IMP_Compose_Link
  • IMP_Compose_LinkedAttachment
  • IMP_Compose_Ui
  • IMP_Compose_View
  • IMP_Contacts
  • IMP_Contacts_Avatar_Addressbook
  • IMP_Contacts_Avatar_Gravatar
  • IMP_Contacts_Avatar_Unknown
  • IMP_Contacts_Flag_Host
  • IMP_Contacts_Image
  • IMP_Contents
  • IMP_Contents_InlineOutput
  • IMP_Contents_View
  • IMP_Crypt_Pgp
  • IMP_Crypt_Smime
  • IMP_Dynamic_AddressList
  • IMP_Dynamic_Base
  • IMP_Dynamic_Compose
  • IMP_Dynamic_Compose_Common
  • IMP_Dynamic_Helper_Base
  • IMP_Dynamic_Mailbox
  • IMP_Dynamic_Message
  • IMP_Exception
  • IMP_Factory_AuthImap
  • IMP_Factory_Compose
  • IMP_Factory_ComposeAtc
  • IMP_Factory_Contacts
  • IMP_Factory_Contents
  • IMP_Factory_Flags
  • IMP_Factory_Ftree
  • IMP_Factory_Identity
  • IMP_Factory_Imap
  • IMP_Factory_Mail
  • IMP_Factory_MailAutoconfig
  • IMP_Factory_Mailbox
  • IMP_Factory_MailboxCache
  • IMP_Factory_MailboxList
  • IMP_Factory_Maillog
  • IMP_Factory_MimeViewer
  • IMP_Factory_Pgp
  • IMP_Factory_PrefsSort
  • IMP_Factory_Quota
  • IMP_Factory_Search
  • IMP_Factory_Sentmail
  • IMP_Factory_Smime
  • IMP_Factory_Spam
  • IMP_Filter
  • IMP_Flag_Base
  • IMP_Flag_Imap
  • IMP_Flag_Imap_Answered
  • IMP_Flag_Imap_Deleted
  • IMP_Flag_Imap_Draft
  • IMP_Flag_Imap_Flagged
  • IMP_Flag_Imap_Forwarded
  • IMP_Flag_Imap_Junk
  • IMP_Flag_Imap_NotJunk
  • IMP_Flag_Imap_Seen
  • IMP_Flag_System_Attachment
  • IMP_Flag_System_Encrypted
  • IMP_Flag_System_HighPriority
  • IMP_Flag_System_List
  • IMP_Flag_System_LowPriority
  • IMP_Flag_System_Match_Address
  • IMP_Flag_System_Match_Flag
  • IMP_Flag_System_Match_Header
  • IMP_Flag_System_Personal
  • IMP_Flag_System_Signed
  • IMP_Flag_System_Unseen
  • IMP_Flag_User
  • IMP_Flags
  • IMP_Ftree
  • IMP_Ftree_Account
  • IMP_Ftree_Account_Imap
  • IMP_Ftree_Account_Inboxonly
  • IMP_Ftree_Account_Remote
  • IMP_Ftree_Account_Vfolder
  • IMP_Ftree_Element
  • IMP_Ftree_Eltdiff
  • IMP_Ftree_Iterator
  • IMP_Ftree_Iterator_Ancestors
  • IMP_Ftree_IteratorFilter
  • IMP_Ftree_IteratorFilter_Children
  • IMP_Ftree_IteratorFilter_Containers
  • IMP_Ftree_IteratorFilter_Expanded
  • IMP_Ftree_IteratorFilter_Invisible
  • IMP_Ftree_IteratorFilter_Mailboxes
  • IMP_Ftree_IteratorFilter_Nonimap
  • IMP_Ftree_IteratorFilter_Polled
  • IMP_Ftree_IteratorFilter_Remote
  • IMP_Ftree_IteratorFilter_Special
  • IMP_Ftree_IteratorFilter_Subscribed
  • IMP_Ftree_IteratorFilter_Vfolder
  • IMP_Ftree_Prefs
  • IMP_Ftree_Prefs_Expanded
  • IMP_Ftree_Prefs_Poll
  • IMP_Ftree_Select
  • IMP_Images
  • IMP_Imap
  • IMP_Imap_Acl
  • IMP_Imap_Cache_Wrapper
  • IMP_Imap_Config
  • IMP_Imap_Exception
  • IMP_Imap_Password
  • IMP_Imap_PermanentFlags
  • IMP_Imap_Remote
  • IMP_Indices
  • IMP_Indices_Mailbox
  • IMP_LoginTasks_SystemTask_GarbageCollection
  • IMP_LoginTasks_SystemTask_Upgrade
  • IMP_LoginTasks_SystemTask_UpgradeAuth
  • IMP_LoginTasks_Task_Autocreate
  • IMP_LoginTasks_Task_DeleteAttachmentsMonthly
  • IMP_LoginTasks_Task_DeleteSentmailMonthly
  • IMP_LoginTasks_Task_FilterOnLogin
  • IMP_LoginTasks_Task_PurgeSentmail
  • IMP_LoginTasks_Task_PurgeSpam
  • IMP_LoginTasks_Task_PurgeTrash
  • IMP_LoginTasks_Task_RecoverDraft
  • IMP_LoginTasks_Task_RenameSentmailMonthly
  • IMP_Mailbox
  • IMP_Mailbox_List
  • IMP_Mailbox_List_Pop3
  • IMP_Mailbox_List_Thread
  • IMP_Mailbox_List_Virtual
  • IMP_Mailbox_SessionCache
  • IMP_Mailbox_Ui
  • IMP_Maillog
  • IMP_Maillog_Log_Base
  • IMP_Maillog_Log_Forward
  • IMP_Maillog_Log_Mdn
  • IMP_Maillog_Log_Redirect
  • IMP_Maillog_Log_Reply
  • IMP_Maillog_Log_Replyall
  • IMP_Maillog_Log_Replylist
  • IMP_Maillog_Message
  • IMP_Maillog_Storage_Base
  • IMP_Maillog_Storage_Composite
  • IMP_Maillog_Storage_History
  • IMP_Maillog_Storage_Mdnsent
  • IMP_Maillog_Storage_Null
  • IMP_Mbox_Generate
  • IMP_Mbox_Import
  • IMP_Mbox_Size
  • IMP_Message
  • IMP_Message_Date
  • IMP_Message_Ui
  • IMP_Mime_Headers
  • IMP_Mime_Status
  • IMP_Mime_Status_RenderIssue
  • IMP_Mime_Status_RenderIssue_Display
  • IMP_Mime_Viewer_Alternative
  • IMP_Mime_Viewer_Appledouble
  • IMP_Mime_Viewer_Audio
  • IMP_Mime_Viewer_Enriched
  • IMP_Mime_Viewer_Externalbody
  • IMP_Mime_Viewer_Html
  • IMP_Mime_Viewer_Images
  • IMP_Mime_Viewer_Itip
  • IMP_Mime_Viewer_Mdn
  • IMP_Mime_Viewer_Partial
  • IMP_Mime_Viewer_Pdf
  • IMP_Mime_Viewer_Pgp
  • IMP_Mime_Viewer_Plain
  • IMP_Mime_Viewer_Related
  • IMP_Mime_Viewer_Rfc822
  • IMP_Mime_Viewer_Smil
  • IMP_Mime_Viewer_Smime
  • IMP_Mime_Viewer_Status
  • IMP_Mime_Viewer_Vcard
  • IMP_Mime_Viewer_Video
  • IMP_Mime_Viewer_Zip
  • IMP_Minimal_Base
  • IMP_Minimal_Compose
  • IMP_Minimal_Error
  • IMP_Minimal_Folders
  • IMP_Minimal_Mailbox
  • IMP_Minimal_Message
  • IMP_Minimal_Messagepart
  • IMP_Minimal_Search
  • IMP_Notification_Event_Status
  • IMP_Notification_Handler_Decorator_ImapAlerts
  • IMP_Notification_Handler_Decorator_NewmailNotify
  • IMP_Perms
  • IMP_Prefs_AttribText
  • IMP_Prefs_Identity
  • IMP_Prefs_Sort
  • IMP_Prefs_Sort_FixedDate
  • IMP_Prefs_Sort_None
  • IMP_Prefs_Sort_Sortpref
  • IMP_Prefs_Sort_Sortpref_Locked
  • IMP_Prefs_Special_Acl
  • IMP_Prefs_Special_ComposeTemplates
  • IMP_Prefs_Special_Drafts
  • IMP_Prefs_Special_Encrypt
  • IMP_Prefs_Special_Flag
  • IMP_Prefs_Special_HtmlSignature
  • IMP_Prefs_Special_ImageReplacement
  • IMP_Prefs_Special_InitialPage
  • IMP_Prefs_Special_Mailto
  • IMP_Prefs_Special_NewmailSound
  • IMP_Prefs_Special_PgpPrivateKey
  • IMP_Prefs_Special_PgpPublicKey
  • IMP_Prefs_Special_Remote
  • IMP_Prefs_Special_Searches
  • IMP_Prefs_Special_Sentmail
  • IMP_Prefs_Special_SmimePrivateKey
  • IMP_Prefs_Special_SmimePublicKey
  • IMP_Prefs_Special_Sourceselect
  • IMP_Prefs_Special_Spam
  • IMP_Prefs_Special_SpecialMboxes
  • IMP_Prefs_Special_Trash
  • IMP_Quota
  • IMP_Quota_Hook
  • IMP_Quota_Imap
  • IMP_Quota_Null
  • IMP_Quota_Ui
  • IMP_Remote
  • IMP_Remote_Account
  • IMP_Script_Package_Autocomplete
  • IMP_Script_Package_ComposeBase
  • IMP_Script_Package_DynamicBase
  • IMP_Script_Package_Editor
  • IMP_Script_Package_Imp
  • IMP_Search
  • IMP_Search_Element
  • IMP_Search_Element_Attachment
  • IMP_Search_Element_Autogenerated
  • IMP_Search_Element_Bulk
  • IMP_Search_Element_Contacts
  • IMP_Search_Element_Daterange
  • IMP_Search_Element_Flag
  • IMP_Search_Element_Header
  • IMP_Search_Element_Mailinglist
  • IMP_Search_Element_Or
  • IMP_Search_Element_Personal
  • IMP_Search_Element_Recipient
  • IMP_Search_Element_Size
  • IMP_Search_Element_Text
  • IMP_Search_Element_Within
  • IMP_Search_Filter
  • IMP_Search_Filter_Attachment
  • IMP_Search_Filter_Autogenerated
  • IMP_Search_Filter_Builtin
  • IMP_Search_Filter_Bulk
  • IMP_Search_Filter_Contacts
  • IMP_Search_Filter_Mailinglist
  • IMP_Search_Filter_Personal
  • IMP_Search_IteratorFilter
  • IMP_Search_Query
  • IMP_Search_Ui
  • IMP_Search_Vfolder
  • IMP_Search_Vfolder_Builtin
  • IMP_Search_Vfolder_Vinbox
  • IMP_Search_Vfolder_Vtrash
  • IMP_Sentmail
  • IMP_Sentmail_Mongo
  • IMP_Sentmail_Null
  • IMP_Sentmail_Sql
  • IMP_Smartmobile
  • IMP_Spam
  • IMP_Spam_Email
  • IMP_Spam_Null
  • IMP_Spam_Program
  • IMP_Test
  • IMP_Tree_Flist
  • IMP_Tree_Jquerymobile
  • IMP_Tree_Simplehtml
  • IMP_View_Subinfo

Interfaces

  • IMP_Compose_Attachment_Linked
  • IMP_Contacts_Avatar_Backend
  • IMP_Contacts_Flag_Backend
  • IMP_Spam_Base
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * Copyright 2012-2014 Horde LLC (http://www.horde.org/)
   4:  *
   5:  * See the enclosed file COPYING for license information (GPL). If you
   6:  * did not receive this file, see http://www.horde.org/licenses/gpl.
   7:  *
   8:  * @category  Horde
   9:  * @copyright 2012-2014 Horde LLC
  10:  * @license   http://www.horde.org/licenses/gpl GPL
  11:  * @package   IMP
  12:  */
  13: 
  14: /**
  15:  * Defines AJAX actions used exclusively in the IMP dynamic view.
  16:  *
  17:  * @author    Michael Slusarz <slusarz@horde.org>
  18:  * @category  Horde
  19:  * @copyright 2012-2014 Horde LLC
  20:  * @license   http://www.horde.org/licenses/gpl GPL
  21:  * @package   IMP
  22:  */
  23: class IMP_Ajax_Application_Handler_Dynamic
  24: extends Horde_Core_Ajax_Application_Handler
  25: {
  26:     /**
  27:      * The list of actions that require readonly access to the session.
  28:      *
  29:      * @var array
  30:      */
  31:     protected $_readOnly = array(
  32:         'html2Text', 'text2Html'
  33:     );
  34: 
  35:     /**
  36:      * AJAX action: Check access rights for creation of a submailbox.
  37:      *
  38:      * Variables used:
  39:      *   - mbox: (string) The name of the mailbox to check (base64url
  40:      *           encoded).
  41:      *
  42:      * @return object  Object with the following properties:
  43:      *   - result: (boolean) True if submailboxes can be created.
  44:      */
  45:     public function createMailboxPrepare()
  46:     {
  47:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
  48:         $ret = new stdClass;
  49:         $ret->result = true;
  50: 
  51:         if (!$mbox->access_creatembox) {
  52:             $GLOBALS['notification']->push(sprintf(_("You may not create child mailboxes in \"%s\"."), $mbox->display), 'horde.error');
  53:             $ret->result = false;
  54:         }
  55: 
  56:         return $ret;
  57:     }
  58: 
  59:     /**
  60:      * AJAX action: Create a mailbox.
  61:      *
  62:      * Variables used:
  63:      *   - create_poll: (boolean) If true, add new mailbox to poll list.
  64:      *   - mbox: (string) The name of the new mailbox.
  65:      *   - parent: (string) The parent mailbox (base64url encoded).
  66:      *
  67:      * @return boolean  True on success, false on failure.
  68:      */
  69:     public function createMailbox()
  70:     {
  71:         global $injector, $notification;
  72: 
  73:         if (!isset($this->vars->mbox)) {
  74:             return false;
  75:         }
  76: 
  77:         $result = false;
  78: 
  79:         $parent = isset($this->vars->parent)
  80:             ? IMP_Mailbox::formFrom($this->vars->parent)
  81:             : IMP_Mailbox::get(IMP_Ftree::BASE_ELT);
  82:         $new_mbox = $parent->createMailboxName($this->vars->mbox);
  83: 
  84:         if ($new_mbox->exists) {
  85:             $notification->push(sprintf(_("Mailbox \"%s\" already exists."), $new_mbox->display), 'horde.warning');
  86:         } elseif ($new_mbox->create()) {
  87:             $result = true;
  88: 
  89:             if ($this->vars->create_poll) {
  90:                 $injector->getInstance('IMP_Ftree')->poll->addPollList($new_mbox);
  91:                 $this->_base->queue->poll($new_mbox);
  92:             }
  93:         }
  94: 
  95:         return $result;
  96:     }
  97: 
  98:     /**
  99:      * AJAX action: Check access rights for deletion/rename of mailbox.
 100:      *
 101:      * Variables used:
 102:      *   - mbox: (string) The name of the mailbox to check (base64url
 103:      *           encoded).
 104:      *   - type: (string) Either 'delete' or 'rename'.
 105:      *
 106:      * @return object  Object with the following properties:
 107:      *   - result: (boolean) True if mailbox can be deleted/renamed.
 108:      */
 109:     public function deleteMailboxPrepare()
 110:     {
 111:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
 112:         $ret = new stdClass;
 113: 
 114:         if ($mbox->access_deletembox) {
 115:             $ret->result = true;
 116:             return $ret;
 117:         }
 118: 
 119:         switch ($this->vars->type) {
 120:         case 'delete':
 121:             $GLOBALS['notification']->push(sprintf(_("You may not delete \"%s\"."), $mbox->display), 'horde.error');
 122:             break;
 123: 
 124:         case 'rename':
 125:             $GLOBALS['notification']->push(sprintf(_("You may not rename \"%s\"."), $mbox->display), 'horde.error');
 126:             break;
 127:         }
 128: 
 129:         $ret->result = false;
 130:         return $ret;
 131:     }
 132: 
 133:     /**
 134:      * AJAX action: Delete a mailbox.
 135:      *
 136:      * Variables used:
 137:      *   - container: (boolean) True if base element is a container.
 138:      *   - mbox: (string) The full mailbox name to delete (base64url encoded).
 139:      *   - subfolders: (boolean) Delete all subfolders?
 140:      *
 141:      * @return boolean  True on success, false on failure.
 142:      */
 143:     public function deleteMailbox()
 144:     {
 145:         return ($this->vars->mbox && IMP_Mailbox::formFrom($this->vars->mbox)->delete(array(
 146:             'subfolders' => !empty($this->vars->subfolders),
 147:             'subfolders_only' => !empty($this->vars->container)
 148:         )));
 149:     }
 150: 
 151:     /**
 152:      * AJAX action: Rename a mailbox.
 153:      *
 154:      * Variables used:
 155:      *   - new_name: (string) New mailbox name (child node) (UTF-8).
 156:      *   - new_parent: (string) New parent name (UTF-8; base64url encoded).
 157:      *                 If not present, uses old parent.
 158:      *   - old_name: (string) Full name of old mailbox (base64url encoded).
 159:      *
 160:      * @return boolean  True on success, false on failure.
 161:      */
 162:     public function renameMailbox()
 163:     {
 164:         if (!$this->vars->old_name || !$this->vars->new_name) {
 165:             return false;
 166:         }
 167: 
 168:         $old_name = IMP_Mailbox::formFrom($this->vars->old_name);
 169:         if (isset($this->vars->new_parent)) {
 170:             $parent = strlen($this->vars->new_parent)
 171:                 ? IMP_Mailbox::formFrom($this->vars->new_parent)
 172:                 : IMP_Mailbox::get(IMP_Ftree::BASE_ELT);
 173:         } else {
 174:             $parent = IMP_Mailbox::get($old_name->parent);
 175:         }
 176: 
 177:         if ($parent) {
 178:             $new_name = $parent->createMailboxName($this->vars->new_name);
 179: 
 180:             if (($old_name != $new_name) && $old_name->rename($new_name)) {
 181:                 $this->_base->queue->setMailboxOpt('switch', $new_name->form_to);
 182:                 return true;
 183:             }
 184:         }
 185: 
 186:         return false;
 187:     }
 188: 
 189:     /**
 190:      * AJAX action: Check access rights for a mailbox, and provide number of
 191:      * messages to be emptied.
 192:      *
 193:      * Variables used:
 194:      *   - mbox: (string) The name of the mailbox to check (base64url
 195:      *           encoded).
 196:      *
 197:      * @return object  Object with the following properties:
 198:      *   - result: (integer) The number of messages to be deleted.
 199:      */
 200:     public function emptyMailboxPrepare()
 201:     {
 202:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
 203:         $res = new stdClass;
 204:         $res->result = 0;
 205: 
 206:         if (!$mbox->access_empty) {
 207:             $GLOBALS['notification']->push(sprintf(_("The mailbox \"%s\" may not be emptied."), $mbox->display), 'horde.error');
 208:         } else {
 209:             $poll_info = $mbox->poll_info;
 210:             if (!($res->result = $poll_info->msgs)) {
 211:                 $GLOBALS['notification']->push(sprintf(_("The mailbox \"%s\" is already empty."), $mbox->display), 'horde.message');
 212:             }
 213:         }
 214: 
 215:         return $res;
 216:     }
 217: 
 218:     /**
 219:      * AJAX action: Empty a mailbox.
 220:      *
 221:      * Variables used:
 222:      *   - mbox: (string) The full mailbox name to empty (base64url encoded).
 223:      *
 224:      * @return boolean  True on success, false on failure.
 225:      */
 226:     public function emptyMailbox()
 227:     {
 228:         if (!$this->vars->mbox) {
 229:             return false;
 230:         }
 231: 
 232:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
 233: 
 234:         $GLOBALS['injector']->getInstance('IMP_Message')->emptyMailbox(array($mbox));
 235: 
 236:         $this->_base->queue->poll($mbox);
 237: 
 238:         $vp = new IMP_Ajax_Application_Viewport($mbox);
 239:         $vp->data_reset = 1;
 240:         $vp->rowlist_reset = 1;
 241:         $this->_base->addTask('viewport', $vp);
 242: 
 243:         return true;
 244:     }
 245: 
 246:     /**
 247:      * AJAX action: Flag all messages in a mailbox.
 248:      *
 249:      * Variables used:
 250:      *   - add: (integer) Add the flags?
 251:      *   - flags: (string) The IMAP flags to add/remove (JSON serialized
 252:      *            array).
 253:      *   - mbox: (string) The full mailbox name (base64url encoded).
 254:      *
 255:      * @return boolean  True on success, false on failure.
 256:      */
 257:     public function flagAll()
 258:     {
 259:         $flags = json_decode($this->vars->flags);
 260:         if (!$this->vars->mbox || empty($flags)) {
 261:             return false;
 262:         }
 263: 
 264:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
 265: 
 266:         if (!$GLOBALS['injector']->getInstance('IMP_Message')->flagAllInMailbox($flags, array($mbox), $this->vars->add)) {
 267:             return false;
 268:         }
 269: 
 270:         $this->_base->queue->poll($mbox);
 271: 
 272:         return true;
 273:     }
 274: 
 275:     /**
 276:      * AJAX action: List mailboxes.
 277:      *
 278:      * Variables used:
 279:      *   - all: (integer) 1 to show all mailboxes.
 280:      *   - base: (string) The base mailbox.
 281:      *   - expall: (boolean) 1 to expand all (requires 'all').
 282:      *   - initial: (string) 1 to indicate the initial request for mailbox
 283:      *              list.
 284:      *   - mboxes: (string) The list of mailboxes to process (JSON encoded
 285:      *             array; mailboxes are base64url encoded).
 286:      *   - reload: (integer) 1 to force reload of mailboxes.
 287:      *   - unsub: (integer) 1 to show unsubscribed mailboxes.
 288:      *
 289:      * @return boolean  True.
 290:      */
 291:     public function listMailboxes()
 292:     {
 293:         global $injector, $prefs, $session;
 294: 
 295:         $ftree = $injector->getInstance('IMP_Ftree');
 296:         $iterator = new AppendIterator();
 297: 
 298:         /* This might be a long running operation. */
 299:         if ($this->vars->initial) {
 300:             $session->close();
 301:             $ftree->eltdiff->clear();
 302: 
 303:             /* @todo: Correctly handle unsubscribed mailboxes in ftree. */
 304:             if ($ftree->unsubscribed_loaded && !$this->vars->reload) {
 305:                 $ftree->init();
 306:             }
 307:         }
 308: 
 309:         if ($this->vars->reload) {
 310:             $ftree->init();
 311:         }
 312: 
 313:         $filter = new IMP_Ftree_IteratorFilter($ftree);
 314:         if ($this->vars->unsub) {
 315:             $ftree->loadUnsubscribed();
 316:             $filter->remove($filter::UNSUB);
 317:         }
 318: 
 319:         if (isset($this->vars->base)) {
 320:             $this->_base->queue->setMailboxOpt('base', $this->vars->base);
 321:         }
 322: 
 323:         if ($this->vars->all) {
 324:             $this->_base->queue->setMailboxOpt('all', 1);
 325:             $iterator->append($filter);
 326:             if ($this->vars->expall) {
 327:                 $this->vars->action = 'expand';
 328:                 $this->_base->callAction('toggleMailboxes');
 329:             }
 330:         } elseif ($this->vars->initial || $this->vars->reload) {
 331:             $special = new ArrayIterator();
 332:             $special->append($ftree['INBOX']);
 333: 
 334:             /* Add special mailboxes explicitly to the initial folder list,
 335:              * since they are ALWAYS displayed, may appear outside of the
 336:              * folder slice requested, and need to be sorted logically. */
 337:             $s_elts = array();
 338:             foreach (IMP_Mailbox::getSpecialMailboxesSort() as $val) {
 339:                 if (isset($ftree[$val])) {
 340:                     $special->append($val);
 341:                     $s_elts[] = $ftree[$val];
 342:                 }
 343:             }
 344:             $iterator->append($special);
 345: 
 346:             /* Go through and find any parent elements that contain only
 347:              * special mailbox children - this need to be suppressed in
 348:              * display. */
 349:             $filter2 = clone $filter;
 350:             $filter2->add(array($filter2::CONTAINERS, $filter2::SPECIALMBOXES));
 351:             $no_children = array();
 352: 
 353:             foreach (array_unique($s_elts) as $val) {
 354:                 while (($val = $val->parent) && !$val->base_elt) {
 355:                     $filter2->iterator = new IMP_Ftree_Iterator($val);
 356:                     foreach ($filter2 as $val) {
 357:                         /* If we found at least one viewable mailbox, this
 358:                          * element needs its children to be displayed. */
 359:                         break 2;
 360:                     }
 361:                     $no_children[] = strval($val);
 362:                 }
 363:             }
 364: 
 365:             if (!empty($no_children)) {
 366:                 $this->_base->queue->ftreeCallback = function($id, $ob) use ($no_children) {
 367:                     if (in_array($id, $no_children)) {
 368:                         unset($ob->ch);
 369:                     }
 370:                 };
 371:             }
 372: 
 373:             /* Add regular mailboxes. */
 374:             $no_mbox = false;
 375: 
 376:             switch ($prefs->getValue('nav_expanded')) {
 377:             case IMP_Ftree_Prefs_Expanded::NO:
 378:                 $filter->add($filter::CHILDREN);
 379:                 break;
 380: 
 381:             case IMP_Ftree_Prefs_Expanded::YES:
 382:                 $this->_base->queue->setMailboxOpt('expand', 1);
 383:                 $no_mbox = true;
 384:                 break;
 385: 
 386:             case IMP_Ftree_Prefs_Expanded::LAST:
 387:                 $filter->add($filter::EXPANDED);
 388:                 $this->_base->queue->setMailboxOpt('expand', 1);
 389:                 break;
 390:             }
 391: 
 392:             $filter->mboxes = array('INBOX');
 393:             $iterator->append($filter);
 394: 
 395:             if (!$no_mbox) {
 396:                 $mboxes = IMP_Mailbox::formFrom(json_decode($this->vars->mboxes));
 397:                 foreach ($mboxes as $val) {
 398:                     if (!$val->inbox) {
 399:                         $ancestors = new IMP_Ftree_IteratorFilter(
 400:                             new IMP_Ftree_Iterator_Ancestors($val->tree_elt)
 401:                         );
 402:                         if ($this->vars->unsub) {
 403:                             $ancestors->remove($ancestors::UNSUB);
 404:                         }
 405:                         $iterator->append($ancestors);
 406:                     }
 407:                 }
 408:             }
 409:         } else {
 410:             $filter->add($filter::EXPANDED);
 411:             $this->_base->queue->setMailboxOpt('expand', 1);
 412: 
 413:             foreach (array_filter(IMP_Mailbox::formFrom(json_decode($this->vars->mboxes))) as $val) {
 414:                 $filter->iterator = new IMP_Ftree_Iterator($val->tree_elt);
 415:                 $iterator->append($filter);
 416:                 $ftree->expand($val);
 417:             }
 418:         }
 419: 
 420:         array_map(
 421:             array($ftree->eltdiff, 'add'),
 422:             array_unique(iterator_to_array($iterator, false))
 423:         );
 424: 
 425:         if ($this->vars->initial) {
 426:             $session->start();
 427: 
 428:             /* We need at least 1 changed mailbox. If not, something went
 429:              * wrong and we should reinitialize the folder list. */
 430:             if (!$ftree->eltdiff->changed_elts) {
 431:                 $this->vars->reload = true;
 432:                 $this->listMailboxes();
 433:                 $this->vars->reload = false;
 434:             }
 435:         }
 436: 
 437:         return true;
 438:     }
 439: 
 440:     /**
 441:      * AJAX action: Initialize dynamic view.
 442:      *
 443:      * @see IMP_Ajax_Application_Handler_Common#viewPort()
 444:      * @see listMailboxes()
 445:      *
 446:      * @return boolean  True.
 447:      */
 448:     public function dynamicInit()
 449:     {
 450:         $this->_base->callAction('viewPort');
 451: 
 452:         $this->vars->initial = 1;
 453:         $this->vars->mboxes = json_encode(array($this->vars->mailbox));
 454:         $this->listMailboxes();
 455: 
 456:         $this->_base->queue->flagConfig(Horde_Registry::VIEW_DYNAMIC);
 457: 
 458:         return true;
 459:     }
 460: 
 461:     /**
 462:      * AJAX action: Modify list of polled mailboxes.
 463:      *
 464:      * Variables used:
 465:      *   - add: (integer) 1 to add to the poll list, 0 to remove.
 466:      *   - mbox: (string) The full mailbox name to modify (base64url encoded).
 467:      *
 468:      * @return mixed  False on failure, or an object with the following
 469:      *                entries:
 470:      *   - add: (integer) 1 if added to the poll list, 0 if removed.
 471:      *   - mbox: (string) The full mailbox name modified.
 472:      */
 473:     public function modifyPoll()
 474:     {
 475:         global $injector;
 476: 
 477:         if (!$this->vars->mbox) {
 478:             return false;
 479:         }
 480: 
 481:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
 482: 
 483:         $result = new stdClass;
 484:         $result->add = intval($this->vars->add);
 485:         $result->mbox = $this->vars->mbox;
 486: 
 487:         if ($this->vars->add) {
 488:             $injector->getInstance('IMP_Ftree')->poll->addPollList($mbox);
 489:             $this->_base->queue->poll($mbox);
 490:             $GLOBALS['notification']->push(sprintf(_("\"%s\" mailbox now polled for new mail."), $mbox->display), 'horde.success');
 491:         } else {
 492:             $injector->getInstance('IMP_Ftree')->poll->removePollList($mbox);
 493:             $GLOBALS['notification']->push(sprintf(_("\"%s\" mailbox no longer polled for new mail."), $mbox->display), 'horde.success');
 494:         }
 495: 
 496:         return $result;
 497:     }
 498: 
 499:     /**
 500:      * AJAX action: [un]Subscribe to a mailbox.
 501:      *
 502:      * Variables used:
 503:      *   - mbox: (string) The full mailbox name to [un]subscribe to (base64url
 504:      *           encoded).
 505:      *   - sub: (integer) 1 to subscribe, empty to unsubscribe.
 506:      *   - subfolders: (boolean) [Un]subscribe to all subfolders?
 507:      *
 508:      * @return boolean  True on success, false on failure.
 509:      */
 510:     public function subscribe()
 511:     {
 512:         return IMP_Mailbox::formFrom($this->vars->mbox)->subscribe($this->vars->sub, array(
 513:             'subfolders' => !empty($this->vars->subfolders)
 514:         ));
 515:     }
 516: 
 517:     /**
 518:      * AJAX action: Import a mailbox.
 519:      *
 520:      * Variables used:
 521:      *   - import_mbox: (string) The mailbox to import into (base64url
 522:      *                  encoded).
 523:      *
 524:      * @return object  Returns response object to display JSON HTML-encoded:
 525:      *   - action: (string) The action name (importMailbox).
 526:      *   - mbox: (string) The mailbox the messages were imported to (base64url
 527:      *           encoded).
 528:      */
 529:     public function importMailbox()
 530:     {
 531:         global $injector, $notification;
 532: 
 533:         $mbox = IMP_Mailbox::formFrom($this->vars->import_mbox);
 534: 
 535:         try {
 536:             $notification->push($injector->getInstance('IMP_Mbox_Import')->import($mbox, 'import_file'), 'horde.success');
 537:             $this->_base->queue->poll($mbox);
 538:         } catch (Horde_Exception $e) {
 539:             $notification->push($e);
 540:         }
 541: 
 542:         $result = new stdClass;
 543:         $result->action = 'importMailbox';
 544:         $result->mbox = $this->vars->import_mbox;
 545: 
 546:         return new Horde_Core_Ajax_Response_HordeCore_JsonHtml($result);
 547:     }
 548: 
 549:     /**
 550:      * AJAX action: Flag messages.
 551:      *
 552:      * See the list of variables needed for IMP_Ajax_Application#changed() and
 553:      * IMP_Ajax_Application#checkUidvalidity(). Mailbox/indices form
 554:      * parameters needed. Additional variables used:
 555:      *   - add: (integer) Set the flag?
 556:      *   - flags: (string) The flags to set (JSON serialized array).
 557:      *
 558:      * @return boolean  True on success, false on failure.
 559:      */
 560:     public function flagMessages()
 561:     {
 562:         global $injector;
 563: 
 564:         if (!$this->vars->flags || !count($this->_base->indices)) {
 565:             return false;
 566:         }
 567: 
 568:         $change = $this->_base->changed(true);
 569: 
 570:         if (is_null($change)) {
 571:             return false;
 572:         }
 573: 
 574:         $flags = json_decode($this->vars->flags);
 575: 
 576:         /* Check for non-system flags. If we find any, and the server supports
 577:          * CONDSTORE, we should make sure that these flags are only updated if
 578:          * nobody else has altered the flags. */
 579:         $system_flags = array(
 580:             Horde_Imap_Client::FLAG_ANSWERED,
 581:             Horde_Imap_Client::FLAG_DELETED,
 582:             Horde_Imap_Client::FLAG_DRAFT,
 583:             Horde_Imap_Client::FLAG_FLAGGED,
 584:             Horde_Imap_Client::FLAG_RECENT,
 585:             Horde_Imap_Client::FLAG_SEEN
 586:         );
 587: 
 588:         $unchangedsince = null;
 589:         if (!$this->_base->indices->mailbox->search &&
 590:             $this->vars->viewport->cacheid &&
 591:             array_diff($flags, $system_flags)) {
 592:             $imp_imap = $this->_base->indices->mailbox->imp_imap;
 593:             $parsed = $imp_imap->parseCacheId($this->vars->viewport->cacheid);
 594: 
 595:             try {
 596:                 $unchangedsince[strval($this->_base->indices->mailbox)] = $imp_imap->sync($this->_base->indices->mailbox, $parsed['token'], array(
 597:                     'criteria' => Horde_Imap_Client::SYNC_UIDVALIDITY
 598:                 ))->highestmodseq;
 599:             } catch (Horde_Imap_Client_Exception_Sync $e) {}
 600:         }
 601: 
 602:         $res = $injector->getInstance('IMP_Message')->flag(array(
 603:             ($this->vars->add ? 'add' : 'remove') => $flags
 604:         ), $this->_base->indices, array(
 605:             'unchangedsince' => $unchangedsince
 606:         ));
 607: 
 608:         if (!$res) {
 609:             $this->_base->checkUidvalidity();
 610:             return false;
 611:         }
 612: 
 613:         if (in_array(Horde_Imap_Client::FLAG_SEEN, $flags)) {
 614:             $this->_base->queue->poll(array_keys($this->_base->indices->indices()));
 615:         }
 616: 
 617:         $this->_base->addTask('viewport', $change ? $this->_base->viewPortData(true) : new IMP_Ajax_Application_Viewport($this->_base->indices->mailbox));
 618: 
 619:         return true;
 620:     }
 621: 
 622:     /**
 623:      * AJAX action: Add contact.
 624:      *
 625:      * Variables used:
 626:      *   - addr: (string) [JSON array] Address list.
 627:      *
 628:      * @return boolean  True on success, false on failure.
 629:      */
 630:     public function addContact()
 631:     {
 632:         global $injector, $notification;
 633: 
 634:         $addr_ob = $injector->getInstance('IMP_Dynamic_AddressList')->parseAddressList($this->vars->addr);
 635: 
 636:         // TODO: Currently supports only a single, non-group contact.
 637:         $ob = $addr_ob[0];
 638:         if (!$ob) {
 639:             return false;
 640:         } elseif ($ob instanceof Horde_Mail_Rfc822_Group) {
 641:             $notification->push(_("Adding group lists not currently supported."), 'horde.warning');
 642:             return false;
 643:         }
 644: 
 645:         try {
 646:             $injector->getInstance('IMP_Contacts')->addAddress($ob->bare_address, $ob->personal);
 647:             $notification->push(sprintf(_("%s was successfully added to your address book."), $ob->label), 'horde.success');
 648:             return true;
 649:         } catch (Horde_Exception $e) {
 650:             $notification->push($e);
 651:             return false;
 652:         }
 653:     }
 654: 
 655:     /**
 656:      * AJAX action: Blacklist/whitelist addresses from messages.
 657:      *
 658:      * See the list of variables needed for IMP_Ajax_Application#changed(),
 659:      * IMP_Ajax_Application#deleteMsgs(), and
 660:      * IMP_Ajax_Application#checkUidvalidity(). Mailbox/indices form
 661:      * parameters needed. Additional variables used:
 662:      *   - blacklist: (integer) 1 to blacklist, 0 to whitelist.
 663:      *
 664:      * @return boolean  True on success.
 665:      */
 666:     public function blacklist()
 667:     {
 668:         if (!count($this->_base->indices)) {
 669:             return false;
 670:         }
 671: 
 672:         if ($this->vars->blacklist) {
 673:             $change = $this->_base->changed(false);
 674:             if (!is_null($change)) {
 675:                 try {
 676:                     if ($GLOBALS['injector']->getInstance('IMP_Filter')->blacklistMessage($this->_base->indices, false)) {
 677:                         $this->_base->deleteMsgs($this->_base->indices, $change);
 678:                         return true;
 679:                     }
 680:                 } catch (Horde_Exception $e) {
 681:                     $this->_base->checkUidvalidity();
 682:                 }
 683:             }
 684:         } else {
 685:             try {
 686:                 $GLOBALS['injector']->getInstance('IMP_Filter')->whitelistMessage($this->_base->indices, false);
 687:                 return true;
 688:             } catch (Horde_Exception $e) {
 689:                 $this->_base->checkUidvalidity();
 690:             }
 691:         }
 692: 
 693:         return false;
 694:     }
 695: 
 696:     /**
 697:      * AJAX action: Return the MIME tree representation of the message.
 698:      *
 699:      * See the list of variables needed for IMP_Ajax_Application#changed() and
 700:      * IMP_Ajax_Application#checkUidvalidity(). Mailbox/indices form
 701:      * parameters needed. Additional variables used:
 702:      *   - preview: (integer) If set, return preview data. Otherwise, return
 703:      *              full data.
 704:      *
 705:      * @return mixed  On error will return null.
 706:      *                Otherwise an object with the following entries:
 707:      *   - tree: (string) The MIME tree representation of the message.
 708:      *           If viewing preview, on error this object will contain error
 709:      *           and errortype properties.
 710:      */
 711:     public function messageMimeTree()
 712:     {
 713:         $result = new stdClass;
 714: 
 715:         try {
 716:             $imp_contents = $GLOBALS['injector']->getInstance('IMP_Factory_Contents')->create($this->_base->indices);
 717:             $result->tree = $imp_contents->getTree()->getTree(true);
 718:         } catch (IMP_Exception $e) {
 719:             if (!$this->vars->preview) {
 720:                 throw $e;
 721:             }
 722: 
 723:             $result->preview->error = $e->getMessage();
 724:             $result->preview->errortype = 'horde.error';
 725:             $result->preview->buid = $this->vars->buid;
 726:             $result->preview->view = $this->vars->view;
 727:         }
 728: 
 729:         return $result;
 730:     }
 731: 
 732:     /**
 733:      * AJAX action: Return a list of address objects used to build an address
 734:      * header for a message.
 735:      *
 736:      * See the list of variables needed for IMP_Ajax_Application#changed() and
 737:      * IMP_Ajax_Application#checkUidvalidity(). Mailbox/indices form
 738:      * parameters needed. Additional variables used:
 739:      *   - header: (integer) If set, return preview data. Otherwise, return
 740:      *              full data.
 741:      *
 742:      * @return object  An object with the following entries:
 743:      *   - hdr_data: (object) Contains header names as keys and lists of
 744:      *               address objects as values.
 745:      * @throws IMP_Exception
 746:      */
 747:     public function addressHeader()
 748:     {
 749:         $show_msg = new IMP_Ajax_Application_ShowMessage($this->_base->indices);
 750: 
 751:         $hdr = $this->vars->header;
 752: 
 753:         $result = new stdClass;
 754:         $result->hdr_data->$hdr = (object)$show_msg->getAddressHeader($this->vars->header, null);
 755: 
 756:         return $result;
 757:     }
 758: 
 759:     /**
 760:      * AJAX action: Delete an attachment from compose data.
 761:      *
 762:      * Variables used:
 763:      *   - atc_indices: (string) [JSON array] Attachment IDs to delete.
 764:      *   - imp_compose: (string) The IMP_Compose cache identifier.
 765:      *   - quiet: (boolean) If true, don't output notifications.
 766:      *
 767:      * @return array  The list of attchment IDs that were deleted.
 768:      */
 769:     public function deleteAttach()
 770:     {
 771:         global $injector, $notification;
 772: 
 773:         $result = array();
 774: 
 775:         if (isset($this->vars->atc_indices)) {
 776:             $imp_compose = $injector->getInstance('IMP_Factory_Compose')->create($this->vars->imp_compose);
 777:             foreach (json_decode($this->vars->atc_indices) as $val) {
 778:                 if (isset($imp_compose[$val])) {
 779:                     if (empty($this->vars->quiet)) {
 780:                         $notification->push(sprintf(_("Deleted attachment \"%s\"."), Horde_Mime::decode($imp_compose[$val]->getPart()->getName(true))), 'horde.success');
 781:                     }
 782:                     unset($imp_compose[$val]);
 783:                     $result[] = $val;
 784:                     $this->_base->queue->compose($imp_compose);
 785:                 }
 786:             }
 787:         }
 788: 
 789:         if (empty($result) && empty($this->vars->quiet)) {
 790:             $notification->push(_("At least one attachment could not be deleted."), 'horde.error');
 791:         }
 792: 
 793:         return $result;
 794:     }
 795: 
 796:     /**
 797:      * AJAX action: Purge deleted messages.
 798:      *
 799:      * See the list of variables needed for IMP_Ajax_Application#changed() and
 800:      * IMP_Ajax_Application#deleteMsgs().
 801:      *
 802:      * @return boolean  True on success.
 803:      */
 804:     public function purgeDeleted()
 805:     {
 806:         global $injector;
 807: 
 808:         $change = $this->_base->changed(true);
 809:         if (is_null($change)) {
 810:             return false;
 811:         }
 812: 
 813:         if (!$change) {
 814:             $change = ($this->_base->indices->mailbox->getSort()->sortby == Horde_Imap_Client::SORT_THREAD);
 815:         }
 816: 
 817:         $expunged = $injector->getInstance('IMP_Message')->expungeMailbox(array(strval($this->_base->indices->mailbox) => 1), array('list' => true));
 818: 
 819:         if (!($expunge_count = count($expunged))) {
 820:             return false;
 821:         }
 822: 
 823:         $GLOBALS['notification']->push(sprintf(ngettext("%d message was purged from \"%s\".", "%d messages were purged from \"%s\".", $expunge_count), $expunge_count, $this->_base->indices->mailbox->display), 'horde.success');
 824: 
 825:         $indices = new IMP_Indices_Mailbox();
 826:         $indices->buids = $this->_base->indices->mailbox->toBuids($expunged);
 827:         $indices->mailbox = $this->_base->indices->mailbox;
 828:         $indices->indices = $expunged;
 829: 
 830:         $this->_base->deleteMsgs($indices, $change, true);
 831:         $this->_base->queue->poll($this->_base->indices->mailbox);
 832: 
 833:         return true;
 834:     }
 835: 
 836:     /**
 837:      * AJAX action: Send a Message Disposition Notification (MDN).
 838:      *
 839:      * Mailbox/indices form parameters needed.
 840:      *
 841:      * @return mixed  False on failure, or an object with these properties:
 842:      *   - buid: (integer) BUID of message.
 843:      *   - mbox: (string) Mailbox of message (base64url encoded).
 844:      */
 845:     public function sendMDN()
 846:     {
 847:         global $injector, $notification;
 848: 
 849:         if (count($this->_base->indices) != 1) {
 850:             return false;
 851:         }
 852: 
 853:         try {
 854:             $contents = $injector->getInstance('IMP_Factory_Contents')->create($this->_base->indices);
 855:         } catch (IMP_Imap_Exception $e) {
 856:             $e->notify(_("The Message Disposition Notification was not sent. This is what the server said") . ': ' . $e->getMessage());
 857:             return false;
 858:         }
 859: 
 860:         list($mbox, $uid) = $this->_base->indices->getSingle();
 861:         $injector->getInstance('IMP_Message_Ui')->MDNCheck(
 862:             new IMP_Indices($mbox, $uid),
 863:             $contents->getHeaderAndMarkAsSeen(),
 864:             true
 865:         );
 866: 
 867:         $notification->push(_("The Message Disposition Notification was sent successfully."), 'horde.success');
 868: 
 869:         $result = new stdClass;
 870:         $result->buid = $this->_base->vars->buid;
 871:         $result->mbox = $mbox->form_to;
 872: 
 873:         return $result;
 874:     }
 875: 
 876:     /**
 877:      * AJAX action: strip attachment.
 878:      *
 879:      * See the list of variables needed for IMP_Ajax_Application#changed() and
 880:      * IMP_Ajax_Application#checkUidvalidity(). Mailbox/indices form
 881:      * parameters needed.
 882:      *
 883:      * @return mixed  False on failure, or an object with these properties:
 884:      *   - newbuid: (integer) BUID of new message.
 885:      *   - newmbox: (string) Mailbox of new message (base64url encoded).
 886:      */
 887:     public function stripAttachment()
 888:     {
 889:         global $injector, $notification;
 890: 
 891:         if (count($this->_base->indices) != 1) {
 892:             return false;
 893:         }
 894: 
 895:         $change = $this->_base->changed(true);
 896:         if (is_null($change)) {
 897:             return false;
 898:         }
 899: 
 900:         try {
 901:             $this->_base->indices = new IMP_Indices_Mailbox(
 902:                 $this->_base->indices->mailbox,
 903:                 $injector->getInstance('IMP_Message')->stripPart($this->_base->indices, $this->vars->id)
 904:             );
 905:         } catch (IMP_Exception $e) {
 906:             $notification->push($e);
 907:             return false;
 908:         }
 909: 
 910:         $notification->push(_("Attachment successfully stripped."), 'horde.success');
 911: 
 912:         $result = new stdClass;
 913:         list($result->newmbox, $result->newbuid) = $this->_base->indices->getSingle();
 914:         $result->newmbox = $result->newmbox->form_to;
 915: 
 916:         $this->_base->queue->message($this->_base->indices, true);
 917:         $this->_base->addTask('viewport', $this->_base->viewPortData(true));
 918: 
 919:         return $result;
 920:     }
 921: 
 922:     /**
 923:      * AJAX action: Convert HTML to text (compose data).
 924:      *
 925:      * Variables used:
 926:      *   - data: (string) [JSON array] List of data to convert. Keys are UIDs
 927:      *           used to idetify the return values. Values are arrays with
 928:      *           these keys:
 929:      *     - changed: (integer) Has the text changed from the original?
 930:      *     - text: (string) The text to convert.
 931:      *   - imp_compose: (string) The IMP_Compose cache identifier.
 932:      *
 933:      * @return object  An object with the following entries:
 934:      *   - text: (array) Array with keys as UIDs and values as the converted
 935:      *           text string.
 936:      */
 937:     public function html2Text()
 938:     {
 939:         return $this->_convertText('text');
 940:     }
 941: 
 942:     /**
 943:      * AJAX action: Convert text to HTML (compose data).
 944:      *
 945:      * Variables used:
 946:      *   - data: (string) [JSON array] List of data to convert. Keys are UIDs
 947:      *           used to idetify the return values. Values are arrays with
 948:      *           these keys:
 949:      *     - changed: (integer) Has the text changed from the original?
 950:      *     - text: (string) The text to convert.
 951:      *   - imp_compose: (string) The IMP_Compose cache identifier.
 952:      *
 953:      * @return object  An object with the following entries:
 954:      *   - text: (array) Array with keys as UIDs and values as the converted
 955:      *           text string.
 956:      */
 957:     public function text2Html()
 958:     {
 959:         return $this->_convertText('html');
 960:     }
 961: 
 962:     /**
 963:      * Helper for html2Text() and text2Html().
 964:      *
 965:      * @internal
 966:      */
 967:     protected function _convertText($mode)
 968:     {
 969:         global $injector;
 970: 
 971:         $compose = null;
 972: 
 973:         $result = new stdClass;
 974:         $result->text = array();
 975: 
 976:         foreach (json_decode($this->vars->data, true) as $key => $val) {
 977:             $tmp = null;
 978: 
 979:             if (empty($val['changed'])) {
 980:                 if (!$compose) {
 981:                     $compose = $this->_base->initCompose();
 982:                 }
 983: 
 984:                 switch ($compose->compose->replyType()) {
 985:                 case IMP_Compose::FORWARD_BODY:
 986:                 case IMP_Compose::FORWARD_BOTH:
 987:                     $data = $compose->compose->forwardMessageText($compose->contents, array(
 988:                         'format' => $mode
 989:                     ));
 990:                     $tmp = $data['body'];
 991:                     break;
 992: 
 993:                 case IMP_Compose::REPLY_ALL:
 994:                 case IMP_Compose::REPLY_LIST:
 995:                 case IMP_Compose::REPLY_SENDER:
 996:                     $data = $compose->compose->replyMessageText($compose->contents, array(
 997:                         'format' => $mode
 998:                     ));
 999:                     $tmp = $data['body'];
1000:                     break;
1001:                 }
1002:             }
1003: 
1004:             $result->text[$key] = is_null($tmp)
1005:                 ? $injector->getInstance('IMP_Compose_Ui')->convertComposeText($val['text'], $mode)
1006:                 : $tmp;
1007:         }
1008: 
1009:         return $result;
1010:     }
1011: 
1012:     /**
1013:      * AJAX action: Add an attachment to a compose message (from the ckeditor
1014:      * plugin).
1015:      *
1016:      * Variables used:
1017:      *   - CKEditorFuncNum: (integer) CKEditor function identifier to call
1018:      *                      when returning URL data
1019:      *   - composeCache: (string) The IMP_Compose cache identifier.
1020:      *
1021:      * @return Horde_Core_Ajax_Response_Raw  text/html return containing
1022:      *                                       javascript code to update the
1023:      *                                       URL parameter in CKEditor.
1024:      */
1025:     public function addAttachmentCkeditor()
1026:     {
1027:         global $injector;
1028: 
1029:         $data = $url = null;
1030: 
1031:         if (isset($this->vars->composeCache)) {
1032:             $imp_compose = $injector->getInstance('IMP_Factory_Compose')->create($this->vars->composeCache);
1033: 
1034:             if ($imp_compose->canUploadAttachment()) {
1035:                 try {
1036:                     $atc_ob = $imp_compose->addAttachmentFromUpload('upload');
1037:                     if ($atc_ob[0] instanceof IMP_Compose_Exception) {
1038:                         throw $atc_ob[0];
1039:                     }
1040: 
1041:                     $atc_ob[0]->related = true;
1042: 
1043:                     $data = array(
1044:                         IMP_Compose::RELATED_ATTR => 'src;' . $atc_ob[0]->id
1045:                     );
1046:                     $url = strval($atc_ob[0]->viewUrl());
1047:                 } catch (IMP_Compose_Exception $e) {
1048:                     $data = $e->getMessage();
1049:                 }
1050:             } else {
1051:                 $data = _("Uploading attachments has been disabled on this server.");
1052:             }
1053:         } else {
1054:             $data = _("Your attachment was not uploaded. Most likely, the file exceeded the maximum size allowed by the server configuration.");
1055:         }
1056: 
1057:         return new Horde_Core_Ajax_Response_Raw(
1058:             '<html>' .
1059:                 Horde::wrapInlineScript(array(
1060:                     'window.parent.CKEDITOR.tools.callFunction(' . $this->vars->CKEditorFuncNum . ',' . json_encode($url) . ',' . json_encode($data) . ')'
1061:                 )) .
1062:             '</html>',
1063:             'text/html'
1064:         );
1065:     }
1066: 
1067:     /**
1068:      * AJAX action: Is the given mailbox fixed? Called dynamically to delay
1069:      * retrieval of ACLs of all visible mailboxes at initialization.
1070:      *
1071:      * Variables used:
1072:      *   - mbox: (integer) The mailbox name.
1073:      *
1074:      * @return object  An object with the following entires:
1075:      *   - fixed: (boolean) True if the mailbox is fixed.
1076:      */
1077:     public function isFixedMbox()
1078:     {
1079:         $result = new stdClass;
1080:         $result->fixed = !(IMP_Mailbox::formFrom($this->vars->mbox)->access_deletembox);
1081:         return $result;
1082: 
1083:     }
1084: 
1085:     /**
1086:      * AJAX action: Create an IMAP flag.
1087:      *
1088:      * Variables used:
1089:      *   - flagcolor: (string) Background color for flag label.
1090:      *   - flagname: (string) Flag name.
1091:      *
1092:      * @return object  An object with the following properties:
1093:      *   - success: (boolean) True if successful.
1094:      */
1095:     public function createFlag()
1096:     {
1097:         global $injector, $notification;
1098: 
1099:         $ret = new stdClass;
1100:         $ret->success = true;
1101: 
1102:         $imp_flags = $injector->getInstance('IMP_Flags');
1103: 
1104:         try {
1105:             $imapflag = $imp_flags->addFlag($this->vars->flagname);
1106:         } catch (IMP_Exception $e) {
1107:             $notification->push($e, 'horde.error');
1108:             $ret->success = false;
1109:             return $ret;
1110:         }
1111: 
1112:         if (!empty($this->vars->flagcolor)) {
1113:             $imp_flags->updateFlag($this->vars->flagname, 'bgcolor', $this->vars->flagcolor);
1114:         }
1115: 
1116:         $this->vars->add = true;
1117:         $this->vars->flags = json_encode(array($imapflag));
1118:         $this->flagMessages();
1119: 
1120:         $this->_base->queue->flagConfig(Horde_Registry::VIEW_DYNAMIC);
1121: 
1122:         $name = 'imp:viewport';
1123:         if ($this->_base->tasks->$name) {
1124:             $this->_base->tasks->$name->addFlagMetadata();
1125:         }
1126: 
1127:         return $ret;
1128:     }
1129: 
1130:     /**
1131:      * AJAX action: Generate the sent-mail select list.
1132:      *
1133:      * Variables used: NONE
1134:      *
1135:      * @return object  An object with the following properties:
1136:      *   - flist: (array) TODO
1137:      */
1138:     public function sentMailList()
1139:     {
1140:         global $injector;
1141: 
1142:         /* Check to make sure the sent-mail mailboxes are created; they need
1143:          * to exist to show up in drop-down list. */
1144:         $identity = $injector->getInstance('IMP_Identity');
1145:         foreach ($identity->getAllSentmail() as $mbox) {
1146:             $mbox->create();
1147:         }
1148: 
1149:         $flist = array();
1150:         $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree'));
1151:         $iterator->add($iterator::NONIMAP);
1152: 
1153:         foreach ($iterator as $val) {
1154:             $mbox_ob = $val->mbox_ob;
1155:             $tmp = array(
1156:                 'f' => $mbox_ob->display,
1157:                 'l' => Horde_String::abbreviate(str_repeat(' ', 2 * $val->level) . $mbox_ob->basename, 30),
1158:                 'v' => $val->container ? '' : $mbox_ob->form_to
1159:             );
1160:             if ($tmp['f'] == $tmp['v']) {
1161:                 unset($tmp['f']);
1162:             }
1163:             $flist[] = $tmp;
1164:         }
1165: 
1166:         $ret = new stdClass;
1167:         $ret->flist = $flist;
1168: 
1169:         return $ret;
1170:     }
1171: 
1172:     /**
1173:      * AJAX action: Redirect to the filter edit page and pre-populate with
1174:      * an e-mail address.
1175:      *
1176:      * Requires EITHER 'addr' -or- mailbox/indices from form params.
1177:      *
1178:      * Variables used:
1179:      *   - addr: (string) The e-mail address to use.
1180:      *
1181:      * @return Horde_Core_Ajax_Response_HordeCore_Reload  Object with URL to
1182:      *                                                    redirect to.
1183:      */
1184:     public function newFilter()
1185:     {
1186:         global $injector, $notification, $registry;
1187: 
1188:         if (isset($this->vars->addr)) {
1189:             $addr_ob = $injector->getInstance('IMP_Dynamic_AddressList')->parseAddressList($this->vars->addr);
1190:         } else {
1191:             $query = new Horde_Imap_Client_Fetch_Query();
1192:             $query->envelope();
1193: 
1194:             $imp_imap = $this->_base->indices->mailbox->imp_imap;
1195:             list($mbox, $uid) = $this->_base->indices->getSingle();
1196:             $ret = $imp_imap->fetch($mbox, $query, array(
1197:                 'ids' => $imp_imap->getIdsOb($uid)
1198:             ));
1199: 
1200:             $addr_ob = $ret[$uid]->getEnvelope()->from;
1201:         }
1202: 
1203:         // TODO: Currently supports only a single, non-group contact.
1204:         $ob = $addr_ob[0];
1205:         if (!$ob) {
1206:             return false;
1207:         } elseif ($ob instanceof Horde_Mail_Rfc822_Group) {
1208:             $notification->push(_("Editing group lists not currently supported."), 'horde.warning');
1209:             return false;
1210:         }
1211: 
1212:         try {
1213:             return new Horde_Core_Ajax_Response_HordeCore_Reload(
1214:                 $registry->link('mail/newEmailFilter', array(
1215:                     'email' => $ob->bare_address
1216:                 ))
1217:             );
1218:         } catch (Horde_Exception $e) {
1219:             return false;
1220:         }
1221:     }
1222: 
1223:     /**
1224:      * AJAX action: Return the contacts images for a given e-mail address.
1225:      *
1226:      * Variables used:
1227:      *   - addr: (string) The e-mail address.
1228:      *
1229:      * @return object  An object with the following properties:
1230:      *   - avatar: (string) The URL of the avatar image.
1231:      *   - flag: (string) The URL of the sender's country flag image.
1232:      *   - flagname: (string) The name of the country of the sender.
1233:      */
1234:     public function getContactsImage()
1235:     {
1236:         $contacts_img = new IMP_Contacts_Image($this->vars->addr);
1237:         $out = new stdClass;
1238: 
1239:         try {
1240:             $res = $contacts_img->getImage($contacts_img::AVATAR);
1241:             $out->avatar = strval($res['url']);
1242:         } catch (IMP_Exception $e) {}
1243: 
1244:         try {
1245:             $res = $contacts_img->getImage($contacts_img::FLAG);
1246:             $out->flag = strval($res['url']);
1247:             $out->flagname = $res['desc'];
1248:         } catch (IMP_Exception $e) {}
1249: 
1250:         return $out;
1251:     }
1252: 
1253:     /**
1254:      * AJAX action: Determine the size of a mailbox.
1255:      *
1256:      * Variables used:
1257:      *   - mbox: (string) The name of the mailbox to check (base64url
1258:      *           encoded).
1259:      *
1260:      * @return object  An object with the following properties:
1261:      *   - size: (string) Formatted size string.
1262:      */
1263:     public function mailboxSize()
1264:     {
1265:         $mbox = IMP_Mailbox::formFrom($this->vars->mbox);
1266: 
1267:         $ret = new stdClass;
1268:         $ret->size = $mbox->size;
1269: 
1270:         return $ret;
1271:     }
1272: 
1273:     /**
1274:      * AJAX Action: Do an autocomplete search.
1275:      *
1276:      * Variables used:
1277:      *   - search: (string) Search string.
1278:      *   - type: (string) Autocomplete search type.
1279:      *
1280:      * @return object  An object with a single property: 'results'.
1281:      *                 The format of 'results' depends on the search type.
1282:      *   - type = 'email'
1283:      *     Results is an array with the following keys for each result:
1284:      *     - g: (array) List of addresses in the group (in same 'results'
1285:      *          format as type = 'email').
1286:      *     - l: (string) Full label.
1287:      *     - s: (string) Short display string.
1288:      *     - v: (string) Value.
1289:      */
1290:     public function autocompleteSearch()
1291:     {
1292:         $out = new stdClass;
1293:         $out->results = array();
1294: 
1295:         switch ($this->vars->type) {
1296:         case 'email':
1297:             $addr = $GLOBALS['injector']->getInstance('IMP_Contacts')->searchEmail(
1298:                 $this->vars->search,
1299:                 array('levenshtein' => true)
1300:             );
1301: 
1302:             $out->results = $this->_autocompleteSearchEmail($addr);
1303:             break;
1304:         }
1305: 
1306:         return $out;
1307:     }
1308: 
1309:     /**
1310:      * Creates the output list for the 'email' autocomplete search.
1311:      *
1312:      * @param Horde_Mail_Rfc822_List $alist  Address list.
1313:      *
1314:      * @return array  See autocompleteSearch().
1315:      */
1316:     protected function _autocompleteSearchEmail(Horde_Mail_Rfc822_List $alist)
1317:     {
1318:         $out = array();
1319: 
1320:         foreach ($alist as $val) {
1321:             $tmp = array('v' => strval($val));
1322:             $l = $val->writeAddress(array('noquote' => true));
1323:             $s = $val->label;
1324: 
1325:             if ($l !== $tmp['v']) {
1326:                 $tmp['l'] = $l;
1327:             }
1328: 
1329:             if ($val instanceof Horde_Mail_Rfc822_Group) {
1330:                 $tmp['g'] = $this->_autocompleteSearchEmail($val->addresses);
1331:                 $tmp['s'] = sprintf(
1332:                     _("%s [%d addresses]"),
1333:                     $s,
1334:                     count($val)
1335:                 );
1336:             } elseif ($s !== $tmp['v']) {
1337:                 $tmp['s'] = $s;
1338:             }
1339: 
1340:             $out[] = $tmp;
1341:         }
1342: 
1343:         return $out;
1344:     }
1345: 
1346: }
1347: 
API documentation generated by ApiGen