Overview

Packages

  • IMP
  • None

Classes

  • IMP
  • IMP_Ajax_Application
  • IMP_Ajax_Imple_ContactAutoCompleter
  • IMP_Ajax_Imple_PassphraseDialog
  • IMP_Ajax_Queue
  • IMP_Api
  • IMP_Auth
  • IMP_Block_Newmail
  • IMP_Block_Summary
  • IMP_Compose
  • IMP_Compose_Exception
  • IMP_Compose_Stationery
  • IMP_Contents
  • IMP_Crypt_Pgp
  • IMP_Crypt_Smime
  • IMP_Dimp
  • IMP_Exception
  • IMP_Factory_AuthImap
  • IMP_Factory_Compose
  • IMP_Factory_Contents
  • IMP_Factory_Flags
  • IMP_Factory_Identity
  • IMP_Factory_Imap
  • IMP_Factory_Imaptree
  • IMP_Factory_Mail
  • IMP_Factory_Mailbox
  • IMP_Factory_MailboxList
  • IMP_Factory_MimeViewer
  • IMP_Factory_Pgp
  • IMP_Factory_Quota
  • IMP_Factory_Search
  • IMP_Factory_Sentmail
  • IMP_Factory_Smime
  • 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_Imap
  • IMP_Imap_Acl
  • IMP_Imap_Exception
  • IMP_Imap_PermanentFlags
  • IMP_Imap_Thread
  • IMP_Imap_Tree
  • IMP_Indices
  • IMP_Indices_Form
  • 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_Track
  • IMP_Maillog
  • IMP_Menu_Dimp
  • IMP_Message
  • IMP_Mime_Status
  • 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_Notification_Event_Status
  • IMP_Notification_Handler_Decorator_ImapAlerts
  • IMP_Notification_Handler_Decorator_NewmailNotify
  • IMP_Notification_Listener_AjaxStatus
  • Imp_Prefs_Identity
  • IMP_Prefs_Ui
  • IMP_Quota
  • IMP_Quota_Base
  • IMP_Quota_Command
  • IMP_Quota_Hook
  • IMP_Quota_Imap
  • IMP_Quota_Maildir
  • IMP_Quota_Mdaemon
  • IMP_Quota_Mercury32
  • IMP_Quota_Null
  • IMP_Quota_Sql
  • IMP_Search
  • IMP_Search_Element
  • IMP_Search_Element_Attachment
  • IMP_Search_Element_Autogenerated
  • IMP_Search_Element_Bulk
  • IMP_Search_Element_Contacts
  • IMP_Search_Element_Date
  • 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_Query
  • IMP_Search_Vfolder
  • IMP_Search_Vfolder_Builtin
  • IMP_Search_Vfolder_Vinbox
  • IMP_Search_Vfolder_Vtrash
  • IMP_Sentmail
  • IMP_Sentmail_Base
  • IMP_Sentmail_Null
  • IMP_Sentmail_Sql
  • IMP_Spam
  • IMP_Test
  • IMP_Tree_Flist
  • IMP_Tree_Jquerymobile
  • IMP_Tree_Simplehtml
  • IMP_Ui_Compose
  • IMP_Ui_Editor
  • IMP_Ui_Folder
  • IMP_Ui_Headers
  • IMP_Ui_Imageview
  • IMP_Ui_Mailbox
  • IMP_Ui_Message
  • IMP_Ui_Mimp
  • IMP_Ui_Search
  • IMP_Views_Compose
  • IMP_Views_ListMessages
  • IMP_Views_ShowMessage
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * The IMP_Ui_Compose:: class is designed to provide a place to store common
  4:  * code shared among IMP's various UI views for the compose page.
  5:  *
  6:  * Copyright 2006-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * See the enclosed file COPYING for license information (GPL). If you
  9:  * did not receive this file, see http://www.horde.org/licenses/gpl.
 10:  *
 11:  * @author   Michael Slusarz <slusarz@horde.org>
 12:  * @category Horde
 13:  * @license  http://www.horde.org/licenses/gpl GPL
 14:  * @package  IMP
 15:  */
 16: class IMP_Ui_Compose
 17: {
 18:     /**
 19:      * Was the HTML signature replaced in the Html2text callback?
 20:      *
 21:      * @var boolean
 22:      */
 23:     protected $_replaced;
 24: 
 25:     /**
 26:      * Expand addresses in a string. Only the last address in the string will
 27:      * be expanded.
 28:      *
 29:      * @param string $input             The input string.
 30:      * @param IMP_Compose $imp_compose  An IMP_Compose object.
 31:      *
 32:      * @return mixed  If a string, this value should be used as the new
 33:      *                input string.  If an array, the first value is the
 34:      *                input string without the search string; the second
 35:      *                value is the search string; and the third value is
 36:      *                the list of matching addresses.
 37:      */
 38:     public function expandAddresses($input, $imp_compose)
 39:     {
 40:         $addr_list = $this->getAddressList($input, array('addr_list' => true));
 41:         if (empty($addr_list)) {
 42:             return '';
 43:         }
 44: 
 45:         $search = array_pop($addr_list);
 46: 
 47:         /* Don't search if the search string looks like an e-mail address. */
 48:         if ((strpos($search, '<') !== false) ||
 49:             (strpos($search, '@') !== false)) {
 50:             array_push($addr_list, $search);
 51:             return implode(', ', $addr_list);
 52:         }
 53: 
 54:         $res = $imp_compose->expandAddresses($search, array('levenshtein' => true));
 55: 
 56:         if (count($res) == 1) {
 57:             array_push($addr_list, reset($res));
 58:             return implode(', ', $addr_list);
 59:         } elseif (!count($res)) {
 60:             $GLOBALS['notification']->push(sprintf(_("Search for \"%s\" failed: no address found."), $search), 'horde.warning');
 61:             array_push($addr_list, $search);
 62:             return implode(', ', $addr_list);
 63:         }
 64: 
 65:         $GLOBALS['notification']->push(_("Ambiguous address found."), 'horde.warning');
 66: 
 67:         return array(
 68:             implode(', ', $addr_list),
 69:             $search,
 70:             $res
 71:         );
 72:     }
 73: 
 74:     /**
 75:      * Attach the auto-completer to the current compose form.
 76:      *
 77:      * @param array $fields  The list of DOM IDs to attach the autocompleter
 78:      *                       to.
 79:      */
 80:     public function attachAutoCompleter($fields)
 81:     {
 82:         /* Attach autocompleters to the compose form elements. */
 83:         foreach ($fields as $val) {
 84:             $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create(array('imp', 'ContactAutoCompleter'), array('triggerId' => $val));
 85:         }
 86:     }
 87: 
 88:     /**
 89:      * Attach the spellchecker to the current compose form.
 90:      */
 91:     public function attachSpellChecker()
 92:     {
 93:         $menu_view = $GLOBALS['prefs']->getValue('menu_view');
 94:         $spell_img = '<span class="iconImg spellcheckImg"></span>';
 95: 
 96:         if (IMP::getViewMode() == 'imp') {
 97:             $br = '<br />';
 98:             $id = 'IMP';
 99:         } else {
100:             $br = '';
101:             $id = 'DIMP';
102:         }
103: 
104:         $args = array(
105:             'id' => $id . '.SpellChecker',
106:             'targetId' => 'composeMessage',
107:             'triggerId' => 'spellcheck',
108:             'states' => array(
109:                 'CheckSpelling' => $spell_img . (($menu_view == 'text' || $menu_view == 'both') ? $br . _("Check Spelling") : ''),
110:                 'Checking' => $spell_img . $br . _("Checking..."),
111:                 'ResumeEdit' => $spell_img . $br . _("Resume Editing"),
112:                 'Error' => $spell_img . $br . _("Spell Check Failed")
113:             )
114:         );
115: 
116:         $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create('SpellChecker', $args);
117:     }
118: 
119:     /**
120:      * Given an address input, parses the input to obtain the list of
121:      * addresses to use on the compose page.
122:      *
123:      * @param string $addr  The value of the header string.
124:      * @param array $opts   Additional options:
125:      *   - addr_list: (boolean) Return the list of address components?
126:      *                DEFAULT: false
127:      *
128:      * @return mixed  List of addresses, or a string of addresses if
129:      *                'addr_list' is true.
130:      */
131:     public function getAddressList($addr, $opts = array())
132:     {
133:         $addr = rtrim(trim($addr), ',');
134:         $addr_list = array();
135: 
136:         if (!empty($addr)) {
137:             // Although we allow ';' to delimit addresses in the UI, need to
138:             // convert to RFC-compliant ',' delimiter for processing.
139:             foreach (Horde_Mime_Address::explode($addr, ',;') as $val) {
140:                 $addr_list[] = IMP_Compose::formatAddr(trim($val));
141:             }
142:         }
143: 
144:         return empty($opts['addr_list'])
145:             ? implode(', ', $addr_list)
146:             : $addr_list;
147:     }
148: 
149:     /**
150:      * Create the IMP_Contents objects needed to create a message.
151:      *
152:      * @param Horde_Variables $vars  The variables object.
153:      *
154:      * @return IMP_Contents  The IMP_Contents object.
155:      * @throws IMP_Exception
156:      */
157:     public function getContents($vars = null)
158:     {
159:         $ob = null;
160: 
161:         $indices = $this->getIndices($vars);
162: 
163:         if (!is_null($indices)) {
164:             try {
165:                 $ob = $GLOBALS['injector']->getInstance('IMP_Factory_Contents')->create($indices);
166:             } catch (Horde_Exception $e) {}
167:         }
168: 
169:         if (is_null($ob)) {
170:             if (!is_null($vars)) {
171:                 $vars->uid = null;
172:                 $vars->type = 'new';
173:             }
174: 
175:             throw new IMP_Exception(_("Could not retrieve message data from the mail server."));
176:         }
177: 
178:         return $ob;
179:     }
180: 
181:     /**
182:      * Return the Indices object for the messages affected by this compose
183:      * action.
184:      *
185:      * @param Horde_Variables $vars  The variables object.
186:      *
187:      * @return IMP_Contents  The IMP_Contents object.
188:      */
189:     public function getIndices($vars = null)
190:     {
191:         if (!is_null($vars) && isset($vars->msglist)) {
192:             return new IMP_Indices($vars->msglist);
193:         }
194: 
195:         return (is_null($vars) || !isset($vars->uids))
196:             ? IMP::$thismailbox->getIndicesOb(IMP::$uid)
197:             : new IMP_Indices_Form($vars->uids);
198:     }
199: 
200:     /**
201:      * Generate mailbox return URL.
202:      *
203:      * @param string $url  The URL to use instead of the default.
204:      *
205:      * @return string  The mailbox return URL.
206:      */
207:     public function mailboxReturnUrl($url = null)
208:     {
209:         if (!$url) {
210:             $url = Horde::url('mailbox.php');
211:         }
212: 
213:         foreach (array('start', 'page', 'mailbox', 'thismailbox') as $key) {
214:             if (($param = Horde_Util::getFormData($key))) {
215:                 $url->add($key, $param);
216:             }
217:         }
218: 
219:         return $url;
220:     }
221: 
222:     /**
223:      * Generate a compose message popup success window (compose.php).
224:      */
225:     public function popupSuccess()
226:     {
227:         $menu = new Horde_Menu(Horde_Menu::MASK_NONE);
228:         $menu->add(Horde::url('compose.php'), _("New Message"), 'compose.png');
229:         $menu->add(new Horde_Url(''), _("Close this window"), 'close.png', null, null, 'window.close();');
230:         require IMP_TEMPLATES . '/common-header.inc';
231:         $success_template = $GLOBALS['injector']->createInstance('Horde_Template');
232:         $success_template->set('menu', $menu->render());
233:         echo $success_template->fetch(IMP_TEMPLATES . '/imp/compose/success.html');
234:         IMP::status();
235:         require $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc';
236:     }
237: 
238:     /**
239:      * Outputs the script necessary to generate the passphrase dialog box.
240:      *
241:      * @param string $type     Either 'pgp', 'pgp_symm', or 'smime'.
242:      * @param string $cacheid  Compose cache ID (only needed for 'pgp_symm').
243:      */
244:     public function passphraseDialog($type, $cacheid = null)
245:     {
246:         $params = array('onload' => true);
247: 
248:         switch ($type) {
249:         case 'pgp':
250:             $type = 'pgpPersonal';
251:             break;
252: 
253:         case 'pgp_symm':
254:             $params = array('symmetricid' => 'imp_compose_' . $cacheid);
255:             $type = 'pgpSymmetric';
256:             break;
257: 
258:         case 'smime':
259:             $type = 'smimePersonal';
260:             break;
261:         }
262: 
263:         $GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')->create(array('imp', 'PassphraseDialog'), array(
264:             'onload' => true,
265:             'params' => $params,
266:             'type' => $type
267:         ));
268:     }
269: 
270:     /**
271:      * @return array  See Horde::addInlineJsVars().
272:      */
273:     public function identityJs()
274:     {
275:         $identities = array();
276:         $identity = $GLOBALS['injector']->getInstance('IMP_Identity');
277: 
278:         $html_sigs = $identity->getAllSignatures('html');
279: 
280:         foreach ($identity->getAllSignatures() as $ident => $sig) {
281:             $smf = $identity->getValue('sent_mail_folder', $ident);
282: 
283:             $identities[] = array(
284:                 // Plain text signature
285:                 'sig' => $sig,
286:                 // HTML signature
287:                 'sig_html' => $html_sigs[$ident],
288:                 // Signature location
289:                 'sig_loc' => (bool)$identity->getValue('sig_first', $ident),
290:                 // Sent mail folder name
291:                 'smf_name' => $smf ? $smf->form_to : '',
292:                 // Save in sent mail folder by default?
293:                 'smf_save' => (bool)$identity->saveSentmail($ident),
294:                 // Sent mail display name
295:                 'smf_display' => $smf ? $smf->display_html : '',
296:                 // Bcc addresses to add
297:                 'bcc' => Horde_Mime_Address::addrArray2String($identity->getBccAddresses($ident), array('charset' => 'UTF-8'))
298:             );
299:         }
300: 
301:         return Horde::addInlineJsVars(array(
302:             'ImpComposeBase.identities' => $identities
303:         ), array('ret_vars' => true));
304:     }
305: 
306:     /**
307:      * Convert compose data to/from text/HTML.
308:      *
309:      * @param string $data       The message text.
310:      * @param string $to         Either 'text' or 'html'.
311:      * @param integer $identity  The current identity.
312:      *
313:      * @return string  The converted text
314:      */
315:     public function convertComposeText($data, $to, $identity)
316:     {
317:         $imp_identity = $GLOBALS['injector']->getInstance('IMP_Identity');
318:         $this->_replaced = false;
319: 
320:         $html_sig = $imp_identity->getSignature('html', $identity);
321:         $txt_sig = $imp_identity->getSignature('text', $identity);
322: 
323:         /* Try to find the signature, replace it with a placeholder, convert
324:          * the message, and then re-add the signature in the new format. */
325:         switch ($to) {
326:         case 'html':
327:             if ($txt_sig) {
328:                 $data = preg_replace('/' . preg_replace('/(?<!^)\s+/', '\\s+', preg_quote($txt_sig, '/')) . '/', '###IMP_SIGNATURE###', $data, 1, $this->_replaced);
329:             }
330:             $data = IMP_Compose::text2html($data);
331:             $sig = $html_sig;
332:             break;
333: 
334:         case 'text':
335:             $callback = $html_sig
336:                 ? array($this, 'htmlSigCallback')
337:                 : null;
338: 
339:             $data = $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($data, 'Html2text', array(
340:                 'callback' => $callback,
341:                 'wrap' => false
342:             ));
343: 
344:             $sig = $txt_sig;
345:             break;
346:         }
347: 
348:         if ($this->_replaced) {
349:             return str_replace('###IMP_SIGNATURE###', $sig, $data);
350:         } elseif ($imp_identity->getValue('sig_first', $identity)) {
351:             return $sig . $data;
352:         }
353: 
354:         return $data . "\n" . $sig;
355:     }
356: 
357:     /**
358:      * Process DOM node (callback).
359:      *
360:      * @param DOMDocument $doc  Document node.
361:      * @param DOMNode $node     Node.
362:      *
363:      * @return mixed  The text to replace the node with. Returns null if
364:      *                regular node processing should continue.
365:      */
366:     public function htmlSigCallback($doc, $node)
367:     {
368:         if ($node instanceof DOMElement &&
369:             (strtolower($node->tagName) == 'div') &&
370:             ($node->getAttribute('class') == 'impComposeSignature')) {
371:             $this->_replaced = true;
372:             return '###IMP_SIGNATURE###';
373:         }
374: 
375:         return null;
376:     }
377: 
378: }
379: 
API documentation generated by ApiGen