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:  * IMP Base Class.
  4:  *
  5:  * Copyright 1999-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (GPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/gpl.
  9:  *
 10:  * @author   Chuck Hagenbuch <chuck@horde.org>
 11:  * @author   Jon Parise <jon@horde.org>
 12:  * @author   Michael Slusarz <slusarz@horde.org>
 13:  * @category Horde
 14:  * @license  http://www.horde.org/licenses/gpl GPL
 15:  * @package  IMP
 16:  */
 17: class IMP
 18: {
 19:     /* Encrypt constants. */
 20:     const ENCRYPT_NONE = 'encrypt_none';
 21: 
 22:     /* IMP Mailbox view constants. */
 23:     const MAILBOX_START_FIRSTUNSEEN = 1;
 24:     const MAILBOX_START_LASTUNSEEN = 2;
 25:     const MAILBOX_START_FIRSTPAGE = 3;
 26:     const MAILBOX_START_LASTPAGE = 4;
 27: 
 28:     /* Folder list actions. */
 29:     const NOTEPAD_EDIT = "notepad\0";
 30:     const TASKLIST_EDIT = "tasklist\0";
 31: 
 32:     /* Initial page constants. */
 33:     const INITIAL_FOLDERS = "initial\0folders";
 34: 
 35:     /* Sorting constants. */
 36:     const IMAP_SORT_DATE = 100;
 37: 
 38:     /**
 39:      * Storage place for an altered version of the current URL.
 40:      *
 41:      * @var string
 42:      */
 43:     static public $newUrl = null;
 44: 
 45:     /**
 46:      * The current active mailbox (may be search mailbox).
 47:      *
 48:      * @var IMP_Mailbox
 49:      */
 50:     static public $mailbox;
 51: 
 52:     /**
 53:      * The real IMAP mailbox of the current index.
 54:      *
 55:      * @var IMP_Mailbox
 56:      */
 57:     static public $thismailbox;
 58: 
 59:     /**
 60:      * The IMAP UID.
 61:      *
 62:      * @var integer
 63:      */
 64:     static public $uid = '';
 65: 
 66:     /**
 67:      * Returns the current view mode for IMP.
 68:      *
 69:      * @return string  Either 'dimp', 'imp', 'mimp', or 'mobile'.
 70:      */
 71:     static public function getViewMode()
 72:     {
 73:         return ($view = $GLOBALS['session']->get('imp', 'view'))
 74:             ? $view
 75:             : 'imp';
 76:     }
 77: 
 78:     /**
 79:      * Determines if we should display the ajax view based on a combination of
 80:      * user prefs and browser capabilities.
 81:      *
 82:      * @return boolean  A boolean indicating if we should show the ajax view.
 83:      */
 84:     static public function showAjaxView()
 85:     {
 86:         global $prefs, $session;
 87: 
 88:         $mode = $session->get('horde', 'mode');
 89:         return ($mode == 'dynamic' || ($prefs->getValue('dynamic_view') && $mode == 'auto')) && Horde::ajaxAvailable();
 90:     }
 91: 
 92:     /**
 93:      * Adds a contact to the user defined address book.
 94:      *
 95:      * @param string $newAddress  The contact's email address.
 96:      * @param string $newName     The contact's name.
 97:      *
 98:      * @return string  A link or message to show in the notification area.
 99:      * @throws Horde_Exception
100:      */
101:     static public function addAddress($newAddress, $newName)
102:     {
103:         global $registry, $prefs;
104: 
105:         if (empty($newName)) {
106:             $newName = $newAddress;
107:         }
108: 
109:         $result = $registry->call('contacts/import', array(array('name' => $newName, 'email' => $newAddress), 'array', $prefs->getValue('add_source')));
110: 
111:         $escapeName = @htmlspecialchars($newName, ENT_COMPAT, 'UTF-8');
112: 
113:         try {
114:             if ($contact_link = $registry->link('contacts/show', array('uid' => $result, 'source' => $prefs->getValue('add_source')))) {
115:                 return Horde::link(Horde::url($contact_link), sprintf(_("Go to address book entry of \"%s\""), $newName)) . $escapeName . '</a>';
116:             }
117:         } catch (Horde_Exception $e) {}
118: 
119:         return $escapeName;
120:     }
121: 
122:     /**
123:      * Generates a select form input from a folder list. The &lt;select&gt;
124:      * and &lt;/select&gt; tags are NOT included in the output.
125:      *
126:      * @param array $options  Optional parameters:
127:      *   - abbrev: (boolean) Abbreviate long mailbox names by replacing the
128:      *             middle of the name with '...'?
129:      *             DEFAULT: Yes
130:      *   - basename: (boolean)  Use raw basename instead of abbreviated label?
131:      *               DEFAULT: false
132:      *   - filter: (array) An array of mailboxes to ignore.
133:      *             DEFAULT: Display all
134:      *   - heading: (string) The label for an empty-value option at the top of
135:      *              the list.
136:      *              DEFAULT: ''
137:      *   - inc_notepads: (boolean) Include user's editable notepads in list?
138:      *                   DEFAULT: No
139:      *   - inc_tasklists: (boolean) Include user's editable tasklists in list?
140:      *                    DEFAULT: No
141:      *   - inc_vfolder: (boolean) Include user's virtual folders in list?
142:      *                  DEFAULT: No
143:      *   - new_folder: (boolean) Display an option to create a new folder?
144:      *                 DEFAULT: No
145:      *   - selected: (string) The mailbox to have selected by default.
146:      *               DEFAULT: None
147:      *
148:      * @return string  A string containing <option> elements for each mailbox
149:      *                 in the list.
150:      */
151:     static public function flistSelect(array $options = array())
152:     {
153:         $imaptree = $GLOBALS['injector']->getInstance('IMP_Imap_Tree');
154:         $imaptree->setIteratorFilter();
155:         $tree = $imaptree->createTree(strval(new Horde_Support_Randomid()), array(
156:             'basename' => !empty($options['basename']),
157:             'render_type' => 'IMP_Tree_Flist'
158:         ));
159:         if (!empty($options['selected'])) {
160:             $tree->addNodeParams(IMP_Mailbox::formTo($options['selected']), array('selected' => true));
161:         }
162:         $tree->setOption($options);
163: 
164:         return $tree->getTree();
165:     }
166: 
167:     /**
168:      * Checks for To:, Subject:, Cc:, and other compose window arguments and
169:      * pass back an associative array of those that are present.
170:      *
171:      * @return string  An associative array with compose arguments.
172:      */
173:     static public function getComposeArgs()
174:     {
175:         $args = array();
176:         $fields = array('to', 'cc', 'bcc', 'message', 'body', 'subject');
177: 
178:         foreach ($fields as $val) {
179:             if (($$val = Horde_Util::getFormData($val))) {
180:                 $args[$val] = $$val;
181:             }
182:         }
183: 
184:         return self::_decodeMailto($args);
185:     }
186: 
187:     /**
188:      * Checks for mailto: prefix in the To field.
189:      *
190:      * @param array $args  A list of compose arguments.
191:      *
192:      * @return array  The array with the To: argument stripped of mailto:.
193:      */
194:     static protected function _decodeMailto($args)
195:     {
196:         $fields = array('to', 'cc', 'bcc', 'message', 'body', 'subject');
197: 
198:         if (isset($args['to']) && (strpos($args['to'], 'mailto:') === 0)) {
199:             $mailto = @parse_url($args['to']);
200:             if (is_array($mailto)) {
201:                 $args['to'] = isset($mailto['path']) ? $mailto['path'] : '';
202:                 if (!empty($mailto['query'])) {
203:                     parse_str($mailto['query'], $vals);
204:                     foreach ($fields as $val) {
205:                         if (isset($vals[$val])) {
206:                             $args[$val] = $vals[$val];
207:                         }
208:                     }
209:                 }
210:             }
211:         }
212: 
213:         return $args;
214:     }
215: 
216:     /**
217:      * Returns the appropriate link to call the message composition script.
218:      *
219:      * @param mixed $args       List of arguments to pass to compose script.
220:      *                          If this is passed in as a string, it will be
221:      *                          parsed as a toaddress?subject=foo&cc=ccaddress
222:      *                          (mailto-style) string.
223:      * @param array $extra      Hash of extra, non-standard arguments to pass
224:      *                          to compose script.
225:      * @param string $simplejs  Use simple JS (instead of Horde.popup() JS
226:      *                          function)?
227:      *
228:      * @return Horde_Url  The link to the message composition script.
229:      */
230:     static public function composeLink($args = array(), $extra = array(),
231:                                        $simplejs = false)
232:     {
233:         if (is_string($args)) {
234:             $string = $args;
235:             $args = array();
236:             if (($pos = strpos($string, '?')) !== false) {
237:                 parse_str(substr($string, $pos + 1), $args);
238:                 $args['to'] = substr($string, 0, $pos);
239:             } else {
240:                 $args['to'] = $string;
241:             }
242:         }
243: 
244:         $args = array_merge(self::_decodeMailto($args), $extra);
245:         $callback = $raw = false;
246:         $uid = isset($args['uid'])
247:             ? $args['uid']
248:             : null;
249:         $view = self::getViewMode();
250: 
251:         if ($simplejs || ($view == 'dimp')) {
252:             $args['popup'] = 1;
253: 
254:             $url = ($view == 'dimp')
255:                 ? 'compose-dimp.php'
256:                 : 'compose.php';
257:             $raw = true;
258:             $callback = array(__CLASS__, 'composeLinkSimpleCallback');
259:         } elseif (($view != 'mimp') &&
260:                   $GLOBALS['prefs']->getValue('compose_popup') &&
261:                   $GLOBALS['browser']->hasFeature('javascript')) {
262:             $url = 'compose.php';
263:             $callback = array(__CLASS__, 'composeLinkJsCallback');
264:         } else {
265:             $url = ($view == 'mimp')
266:                 ? 'compose-mimp.php'
267:                 : 'compose.php';
268:         }
269: 
270:         if (isset($args['thismailbox'])) {
271:             $url = IMP_Mailbox::get($args['thismailbox'])->url($url, $uid);
272:         } elseif (isset($args['mailbox'])) {
273:             $url = IMP_Mailbox::get($args['mailbox'])->url($url, $uid);
274:         } else {
275:             $url = Horde::url($url);
276:         }
277: 
278:         unset($args['mailbox'], $args['thismailbox'], $args['uid']);
279: 
280:         $url->setRaw($raw)->add($args);
281:         if ($callback) {
282:             $url->toStringCallback = $callback;
283:         }
284: 
285:         return $url;
286:     }
287: 
288:     /**
289:      * Callback for Horde_Url when generating "simple" compose links. Simple
290:      * links don't require exterior javascript libraries.
291:      *
292:      * @param Horde_Url $url  URL object.
293:      *
294:      * @return string  URL string representation.
295:      */
296:     static public function composeLinkSimpleCallback($url)
297:     {
298:         return "javascript:void(window.open('" . strval($url) . "','','width=820,height=610,status=1,scrollbars=yes,resizable=yes'));";
299:     }
300: 
301:     /**
302:      * Callback for Horde_Url when generating javascript compose links.
303:      *
304:      * @param Horde_Url $url  URL object.
305:      *
306:      * @return string  URL string representation.
307:      */
308:     static public function composeLinkJsCallback($url)
309:     {
310:         return 'javascript:' . Horde::popupJs(strval($url), array('urlencode' => true));
311:     }
312: 
313:     /**
314:      * Filters a string, if requested.
315:      *
316:      * @param string $text  The text to filter.
317:      *
318:      * @return string  The filtered text (if requested).
319:      */
320:     static public function filterText($text)
321:     {
322:         if ($GLOBALS['prefs']->getValue('filtering') && strlen($text)) {
323:             return $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter($text, 'words', array(
324:                 'replacement' => $GLOBALS['conf']['msgsettings']['filtering']['replacement'],
325:                 'words_file' => $GLOBALS['conf']['msgsettings']['filtering']['words']
326:             ));
327:         }
328: 
329:         return $text;
330:     }
331: 
332:     /**
333:      * Returns whether the specified permission is granted.
334:      *
335:      * @param string $permission  The permission to check.
336:      * @param mixed $allowed      The allowed permissions.
337:      * @param array $opts         Additional options:
338:      *   - For 'max_recipients' and 'max_timelimit', 'value' is the number of
339:      *     recipients in the current message.
340:      *
341:      * @return boolean  Whether the specified permission is allowed.
342:      */
343:     public function hasPermission($permission, $opts = array())
344:     {
345:         $allowed = $GLOBALS['injector']->getInstance('Horde_Core_Perms')
346:             ->hasAppPermission($permission);
347: 
348:         switch ($permission) {
349:         case 'create_folders':
350:             // No-op
351:             break;
352: 
353:         case 'max_folders':
354:             return ($allowed >= count($GLOBALS['injector']->getInstance('IMP_Imap_Tree')));
355:             break;
356: 
357:         case 'max_recipients':
358:             if (isset($opts['value'])) {
359:                 return ($allowed >= $opts['value']);
360:             }
361:             break;
362: 
363:         case 'max_timelimit':
364:             if (isset($opts['value'])) {
365:                 $sentmail = $GLOBALS['injector']->getInstance('IMP_Sentmail');
366:                 if (!($sentmail instanceof IMP_Sentmail_Base)) {
367:                     Horde::logMessage('The permission for the maximum number of recipients per time period has been enabled, but no backend for the sent-mail logging has been configured for IMP.', 'ERR');
368:                     return true;
369:                 }
370: 
371:                 try {
372:                     $opts['value'] += $sentmail->numberOfRecipients($GLOBALS['conf']['sentmail']['params']['limit_period'], true);
373:                 } catch (IMP_Exception $e) {}
374: 
375:                 return ($allowed >= $opts['value']);
376:             }
377:             break;
378:         }
379: 
380:         return (bool)$allowed;
381:     }
382: 
383:     /**
384:      * Build IMP's menu.
385:      *
386:      * @return string  The menu output.
387:      */
388:     static public function menu()
389:     {
390:         $t = $GLOBALS['injector']->createInstance('Horde_Template');
391:         $t->set('form_url', Horde::url('mailbox.php'));
392:         $t->set('forminput', Horde_Util::formInput());
393:         $t->set('use_folders', $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create()->access(IMP_Imap::ACCESS_FOLDERS), true);
394:         if ($t->get('use_folders')) {
395:             Horde::addScriptFile('imp.js', 'imp');
396:             $menu_view = $GLOBALS['prefs']->getValue('menu_view');
397:             $ak = $GLOBALS['prefs']->getValue('widget_accesskey')
398:                 ? Horde::getAccessKey(_("Open Fo_lder"))
399:                 : '';
400: 
401:             $t->set('ak', $ak);
402:             $t->set('flist', self::flistSelect(array(
403:                 'inc_vfolder' => true,
404:                 'selected' => self::$mailbox
405:             )));
406:             $t->set('flink', sprintf('%s%s<br />%s</a>', Horde::link('#'), ($menu_view != 'text') ? '<span class="iconImg folderImg" title="' . htmlspecialchars(_("Open Folder")) . '"></span>' : '', ($menu_view != 'icon') ? Horde::highlightAccessKey(_("Open Fo_lder"), $ak) : ''));
407:         }
408:         $t->set('menu_string', Horde::menu(array('app' => 'imp', 'menu_ob' => true))->render());
409: 
410:         $menu = $t->fetch(IMP_TEMPLATES . '/imp/menu/menu.html');
411: 
412:         /* Need to buffer sidebar output here, because it may add things like
413:          * cookies which need to be sent before output begins. */
414:         Horde::startBuffer();
415:         require HORDE_BASE . '/services/sidebar.php';
416:         return $menu . Horde::endBuffer();
417:     }
418: 
419:     /**
420:      * Outputs IMP's status/notification bar.
421:      */
422:     static public function status()
423:     {
424:         $GLOBALS['notification']->notify(array('listeners' => array('status', 'audio')));
425:     }
426: 
427:     /**
428:      * Outputs IMP's quota information.
429:      */
430:     static public function quota()
431:     {
432:         $quotadata = self::quotaData(true);
433:         if (!empty($quotadata)) {
434:             $t = $GLOBALS['injector']->createInstance('Horde_Template');
435:             $t->set('class', $quotadata['class']);
436:             $t->set('message', $quotadata['message']);
437:             echo $t->fetch(IMP_TEMPLATES . '/quota/quota.html');
438:         }
439:     }
440: 
441:     /**
442:      * Returns data needed to output quota.
443:      *
444:      * @param boolean $long  Output long messages?
445:      *
446:      * @return array  Array with these keys: class, message, percent.
447:      */
448:     static public function quotaData($long = true)
449:     {
450:         if (!$GLOBALS['session']->get('imp', 'imap_quota')) {
451:             return false;
452:         }
453: 
454:         try {
455:             $quotaDriver = $GLOBALS['injector']->getInstance('IMP_Quota');
456:             $quota = $quotaDriver->getQuota();
457:         } catch (IMP_Exception $e) {
458:             Horde::logMessage($e, 'ERR');
459:             return false;
460:         }
461: 
462:         if (empty($quota)) {
463:             return false;
464:         }
465: 
466:         $strings = $quotaDriver->getMessages();
467:         list($calc, $unit) = $quotaDriver->getUnit();
468:         $ret = array('percent' => 0);
469: 
470:         if ($quota['limit'] != 0) {
471:             $quota['usage'] = $quota['usage'] / $calc;
472:             $quota['limit'] = $quota['limit'] / $calc;
473:             $ret['percent'] = ($quota['usage'] * 100) / $quota['limit'];
474:             if ($ret['percent'] >= 90) {
475:                 $ret['class'] = 'quotaalert';
476:             } elseif ($ret['percent'] >= 75) {
477:                 $ret['class'] = 'quotawarn';
478:             } else {
479:                 $ret['class'] = 'control';
480:             }
481: 
482:             $ret['message'] = $long
483:                 ? sprintf($strings['long'], $quota['usage'], $unit, $quota['limit'], $unit, $ret['percent'])
484:                 : sprintf($strings['short'], $ret['percent'], $quota['limit'], $unit);
485:             $ret['percent'] = sprintf("%.2f", $ret['percent']);
486:         } else {
487:             $ret['class'] = 'control';
488:             if ($quota['usage'] != 0) {
489:                 $quota['usage'] = $quota['usage'] / $calc;
490: 
491:                 $ret['message'] = $long
492:                     ? sprintf($strings['nolimit_long'], $quota['usage'], $unit)
493:                     : sprintf($strings['nolimit_short'], $quota['usage'], $unit);
494:             } else {
495:                 $ret['message'] = $long
496:                     ? sprintf(_("Quota status: NO LIMIT"))
497:                     : _("No limit");
498:             }
499:         }
500: 
501:         return $ret;
502:     }
503: 
504:     /**
505:      * Return a list of valid encrypt HTML option tags.
506:      *
507:      * @param string $default      The default encrypt option.
508:      * @param boolean $returnList  Whether to return a hash with options
509:      *                             instead of the options tag.
510:      *
511:      * @return mixed  The list of option tags. This is empty if no encryption
512:      *                is available.
513:      */
514:     static public function encryptList($default = null, $returnList = false)
515:     {
516:         if (is_null($default)) {
517:             $default = $GLOBALS['prefs']->getValue('default_encrypt');
518:         }
519: 
520:         $enc_opts = array();
521:         $output = '';
522: 
523:         if (!empty($GLOBALS['conf']['gnupg']['path']) &&
524:             $GLOBALS['prefs']->getValue('use_pgp')) {
525:             $enc_opts += $GLOBALS['injector']->getInstance('IMP_Crypt_Pgp')->encryptList();
526:         }
527: 
528:         if ($GLOBALS['prefs']->getValue('use_smime')) {
529:             $enc_opts += $GLOBALS['injector']->getInstance('IMP_Crypt_Smime')->encryptList();
530:         }
531: 
532:         if (!empty($enc_opts)) {
533:             $enc_opts = array_merge(
534:                 array(self::ENCRYPT_NONE => _("None")),
535:                 $enc_opts
536:             );
537:         }
538: 
539:         if ($returnList) {
540:             return $enc_opts;
541:         }
542: 
543:         foreach ($enc_opts as $key => $val) {
544:              $output .= '<option value="' . $key . '"' . (($default == $key) ? ' selected="selected"' : '') . '>' . $val . "</option>\n";
545:         }
546: 
547:         return $output;
548:     }
549: 
550:     /**
551:      * Sets mailbox/index information for current page load. This information
552:      * is accessible via IMP::$mailbox, IMP::$thismailbox, and IMP::$uid.
553:      *
554:      * @param boolean $mbox  Use this mailbox, instead of form data.
555:      */
556:     static public function setCurrentMailboxInfo($mbox = null)
557:     {
558:         if (is_null($mbox)) {
559:             $mbox = Horde_Util::getFormData('mailbox');
560:             self::$mailbox = is_null($mbox)
561:                 ? IMP_Mailbox::get('INBOX')
562:                 : IMP_Mailbox::formFrom($mbox);
563: 
564:             $mbox = Horde_Util::getFormData('thismailbox');
565:             self::$thismailbox = is_null($mbox)
566:                 ? self::$mailbox
567:                 : IMP_Mailbox::formFrom($mbox);
568: 
569:             self::$uid = Horde_Util::getFormData('uid');
570:         } else {
571:             self::$mailbox = self::$thismailbox = IMP_Mailbox::get($mbox);
572:             self::$uid = null;
573:         }
574:     }
575: 
576:     /**
577:      * Return a selfURL that has had index/mailbox/actionID information
578:      * removed/altered based on an action that has occurred on the present
579:      * page.
580:      *
581:      * @return Horde_Url  The self URL.
582:      */
583:     static public function selfUrl()
584:     {
585:         return self::$newUrl
586:             ? self::$newUrl->copy()
587:             : Horde::selfUrl(true);
588:     }
589: 
590:     /**
591:      * Determine the status of composing.
592:      *
593:      * @return boolean  Is compose allowed?
594:      * @throws Horde_Exception
595:      */
596:     static public function canCompose()
597:     {
598:         try {
599:             return !Horde::callHook('disable_compose', array(), 'imp');
600:         } catch (Horde_Exception_HookNotSet $e) {
601:             return true;
602:         }
603:     }
604: 
605:     /**
606:      * Determines parameters needed to do an address search
607:      *
608:      * @return array  An array with two keys: 'fields' and 'sources'.
609:      */
610:     static public function getAddressbookSearchParams()
611:     {
612:         $src = json_decode($GLOBALS['prefs']->getValue('search_sources'));
613:         if (empty($src)) {
614:             $src = array();
615:         }
616: 
617:         $fields = json_decode($GLOBALS['prefs']->getValue('search_fields'), true);
618:         if (empty($fields)) {
619:             $fields = array();
620:         }
621: 
622:         return array(
623:             'fields' => $fields,
624:             'sources' => $src
625:         );
626:     }
627: 
628:     /**
629:      * Base64url (RFC 4648 [5]) encode a string.
630:      *
631:      * @param string $in  Unencoded string.
632:      *
633:      * @return string  Encoded string.
634:      */
635:     static public function base64urlEncode($in)
636:     {
637:         return strtr(rtrim(base64_encode($in), '='), '+/', '-_');
638:     }
639: 
640:     /**
641:      * Base64url (RFC 4648 [5]) decode a string.
642:      *
643:      * @param string $in  Encoded string.
644:      *
645:      * @return string  Decoded string.
646:      */
647:     static public function base64urlDecode($in)
648:     {
649:         return base64_decode(strtr($in, '-_', '+/'));
650:     }
651: 
652:     /**
653:      * Workaround broken number_format() prior to PHP 5.4.0.
654:      *
655:      * @param integer $number    Number to format.
656:      * @param integer $decimals  Number of decimals to display.
657:      *
658:      * @return string  See number_format().
659:      */
660:     static public function numberFormat($number, $decimals)
661:     {
662:         $localeinfo = Horde_Nls::getLocaleInfo();
663: 
664:         return str_replace(
665:             array('X', 'Y'),
666:             array($localeinfo['decimal_point'], $localeinfo['thousands_sep']),
667:             number_format($number, $decimals, 'X', 'Y')
668:         );
669:     }
670: 
671: }
672: 
API documentation generated by ApiGen