1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150:
151: class IMP_Mailbox
152: {
153:
154: const MBOX_DRAFTS = 'drafts_folder';
155: const MBOX_SENT = 'sent_mail_folder';
156: const MBOX_SPAM = 'spam_folder';
157: const MBOX_TEMPLATES = 'composetemplates_mbox';
158: const MBOX_TRASH = 'trash_folder';
159:
160: const MBOX_USERSPECIAL = 'user_special';
161:
162:
163: const SPECIAL_COMPOSETEMPLATES = 'composetemplates';
164: const SPECIAL_DRAFTS = 'drafts';
165: const SPECIAL_SENT = 'sent';
166: const SPECIAL_SPAM = 'spam';
167: const SPECIAL_TRASH = 'trash';
168: const SPECIAL_USER = 'userspecial';
169:
170: 171: 172: 173: 174:
175: protected $_mbox;
176:
177: 178: 179: 180: 181: 182: 183:
184: public static function get($mbox)
185: {
186: if (is_array($mbox)) {
187: return array_filter(array_map(array(__CLASS__, 'get'), $mbox));
188: }
189:
190: if ($mbox instanceof IMP_Mailbox) {
191: return $mbox;
192: }
193:
194: try {
195: return $GLOBALS['injector']
196: ->getInstance('IMP_Factory_Mailbox')
197: ->create(strval($mbox));
198: } catch (IMP_Exception $e) {
199: return null;
200: }
201: }
202:
203: 204: 205: 206: 207: 208: 209:
210: public static function getImapMboxOb($mbox)
211: {
212: if (is_array($mbox)) {
213: return array_filter(array_map(array(__CLASS__, 'getImapMboxOb'), $mbox));
214: }
215:
216: if ($mbox instanceof Horde_Imap_Client_Mailbox) {
217: return $mbox;
218: }
219:
220:
221: $mbox_ob = new self($mbox);
222: return Horde_Imap_Client_Mailbox::get($mbox_ob->imap_mbox);
223: }
224:
225: 226: 227: 228: 229: 230: 231:
232: public static function getPref($pref)
233: {
234: return self::get(self::prefFrom($GLOBALS['prefs']->getValue($pref)));
235: }
236:
237: 238: 239: 240: 241: 242: 243:
244: public function __construct($mbox)
245: {
246: if (strlen($mbox) === 0) {
247: throw new IMP_Exception('Mailbox name must not be empty.');
248: }
249:
250: $this->_mbox = $mbox;
251: }
252:
253: 254:
255: public function __toString()
256: {
257: return strval(
258: ($this->_mbox == IMP_Ftree::BASE_ELT) ? '' : $this->_mbox
259: );
260: }
261:
262: 263:
264: public function __get($key)
265: {
266: global $injector;
267:
268: switch ($key) {
269: case 'abbrev_label':
270: $label = $this->label;
271: return ($this->nonimap || ($pos = strrpos($label, $this->namespace_delimiter)) === false)
272: ? $label
273: : substr($label, $pos + 1);
274:
275: case 'access_creatembox':
276: return (!($acl = $this->acl) ||
277: ($acl[Horde_Imap_Client::ACL_CREATEMBOX]));
278:
279: case 'access_deletembox':
280: return ($this->access_deletembox_acl);
281:
282: case 'access_deletembox_acl':
283: return (!($acl = $this->acl) ||
284: ($acl[Horde_Imap_Client::ACL_DELETEMBOX]));
285:
286: case 'access_deletemsgs':
287: return (!($acl = $this->acl) ||
288: ($acl[Horde_Imap_Client::ACL_DELETEMSGS]));
289:
290: case 'access_empty':
291: if ($this->access_deletemsgs && $this->access_expunge) {
292: $special = $this->getSpecialMailboxes();
293: return empty($special[self::SPECIAL_TRASH]) ||
294: !$special[self::SPECIAL_TRASH]->vtrash ||
295: ($special[self::SPECIAL_TRASH] == $this);
296: }
297: return false;
298:
299: case 'access_expunge':
300: return (!($acl = $this->acl) ||
301: ($acl[Horde_Imap_Client::ACL_EXPUNGE]));
302:
303: case 'access_filters':
304: return !$this->search && $this->is_imap;
305:
306: case 'access_flags':
307: return $this->is_imap;
308:
309: case 'access_search':
310: return $this->is_imap;
311:
312: case 'access_sort':
313: 314: 315:
316: return $this->is_imap;
317:
318: case 'access_sortthread':
319: 320: 321: 322: 323:
324: return $this->is_imap;
325:
326: case 'acl':
327: $cache = $injector->getInstance('IMP_Mailbox_SessionCache');
328: if (($acl = $cache->getAcl($this->_mbox)) !== false) {
329: return $acl;
330: }
331:
332: if ($this->nonimap) {
333: $acl = null;
334: } else {
335: $acl = $injector->getInstance('IMP_Imap_Acl')->getACL($this, true);
336: $hooks = $injector->getInstance('Horde_Core_Hooks');
337:
338: if ($hooks->hookExists('mbox_acl', 'imp')) {
339: $hooks->callHook('mbox_acl', 'imp', array($this, $acl));
340: }
341: }
342:
343: $cache->setAcl($this->_mbox, $acl);
344:
345: return $acl;
346:
347: case 'basename':
348: if ($this->nonimap) {
349: return $this->label;
350: }
351:
352: $mbox = $this->remote_mbox
353: ? $this->label
354: : $this->_mbox;
355:
356: return (($pos = strrpos($mbox, $this->namespace_delimiter)) === false)
357: ? strval($mbox)
358: : substr($mbox, $pos + 1);
359:
360: case 'cacheid':
361: case 'cacheid_date':
362: return $this->_getCacheID($key == 'cacheid_date');
363:
364: case 'children':
365: return (($elt = $this->tree_elt) && $elt->children);
366:
367: case 'container':
368: return (($elt = $this->tree_elt) && $elt->container);
369:
370: case 'display':
371: return $this->nonimap
372: ? $this->label
373: : $this->_getDisplay();
374:
375: case 'display_html':
376: return htmlspecialchars($this->display);
377:
378: case 'display_notranslate':
379: return $this->nonimap
380: ? $this->label
381: : $this->_getDisplay(true);
382:
383: case 'drafts':
384: $special = $this->getSpecialMailboxes();
385: return ($this->_mbox == $special[self::SPECIAL_DRAFTS]);
386:
387: case 'editquery':
388: return $injector->getInstance('IMP_Search')->isQuery($this->_mbox, true);
389:
390: case 'editvfolder':
391: return $injector->getInstance('IMP_Search')->isVFolder($this->_mbox, true);
392:
393: case 'exists':
394: return $injector->getInstance('IMP_Mailbox_SessionCache')->exists($this);
395:
396: case 'form_to':
397: return $this->formTo($this->_mbox);
398:
399: case 'icon':
400: return $this->_getIcon();
401:
402: case 'imp_imap':
403: return $injector->getInstance('IMP_Factory_Imap')->create(strval($this));
404:
405: case 'imap_mbox':
406: return strval(
407: $injector->getInstance('IMP_Remote')->getMailboxById($this->_mbox) ?: $this->_mbox
408: );
409:
410: case 'imap_mbox_ob':
411: return self::getImapMboxOb($this->_mbox);
412:
413: case 'inbox':
414: return (strcasecmp($this->_mbox, 'INBOX') === 0);
415:
416: case 'innocent_show':
417: $p = $this->imp_imap->config->innocent_params;
418: return (!empty($p) &&
419: ((isset($p['display']) && empty($p['display'])) || $this->spam));
420:
421: case 'invisible':
422: return (($elt = $this->tree_elt) && $elt->invisible);
423:
424: case 'is_imap':
425: return $this->imp_imap->isImap();
426:
427: case 'is_open':
428: return (($elt = $this->tree_elt) && $elt->open);
429:
430: case 'label':
431: $cache = $injector->getInstance('IMP_Mailbox_SessionCache');
432: if (($label = $cache->getLabel($this->_mbox)) !== false) {
433: return $label;
434: }
435:
436: 437: 438: 439: 440:
441: $imp_search = $injector->getInstance('IMP_Search');
442: $label = ($ob = $imp_search[$this->_mbox])
443: ? $ob->label
444: : $this->_getDisplay();
445:
446: $hooks = $injector->getInstance('Horde_Core_Hooks');
447: if ($hooks->hookExists('mbox_label' ,'imp')) {
448: $label = $hooks->callHook(
449: 'mbox_label',
450: 'imp',
451: array($this->_mbox, $label)
452: );
453: }
454:
455: $cache->setLabel($this->_mbox, $label);
456:
457: return $label;
458:
459: case 'level':
460: return ($elt = $this->tree_elt) ? $elt->level : 0;
461:
462: case 'list_ob':
463: return $injector->getInstance('IMP_Factory_MailboxList')->create($this);
464:
465: case 'namespace':
466: return (($elt = $this->tree_elt) && $elt->namespace);
467:
468: case 'namespace_append':
469: $imp_imap = $this->imp_imap;
470: $def_ns = $imp_imap->getNamespace($imp_imap::NS_DEFAULT);
471: if (is_null($def_ns)) {
472: return $this;
473: }
474: $empty_ns = $imp_imap->getNamespace('');
475:
476: 477: 478: 479:
480: if (!is_null($empty_ns) &&
481: ($def_ns->name == $empty_ns->name)) {
482: return $this;
483: }
484:
485: $ns_info = $this->namespace_info;
486:
487: if (is_null($ns_info) || !is_null($empty_ns)) {
488: return self::get($def_ns->name . $this->_mbox);
489: }
490:
491: return $this;
492:
493: case 'namespace_delimiter':
494: $ns_info = $this->namespace_info;
495: return is_null($ns_info)
496: ? ''
497: : $ns_info->delimiter;
498:
499: case 'namespace_info':
500: return $this->imp_imap->getNamespace(strlen($this) ? $this->_mbox : IMP_Imap::NS_DEFAULT);
501:
502: case 'nonimap':
503: return ($this->search ||
504: (($elt = $this->tree_elt) && $elt->nonimap));
505:
506: case 'parent':
507: return ($elt = $this->tree_elt) ? $elt->parent->mbox_ob : null;
508:
509: case 'parent_imap':
510: return (is_null($p = $this->parent) || !strlen($p))
511: ? null
512: : $p;
513:
514: case 'permflags':
515: if ($this->access_flags) {
516: $imp_imap = $this->imp_imap;
517: try {
518: 519:
520: $imp_imap->openMailbox($this, Horde_Imap_Client::OPEN_READWRITE);
521: $status = $imp_imap->status($this->_mbox, Horde_Imap_Client::STATUS_FLAGS | Horde_Imap_Client::STATUS_PERMFLAGS);
522: return new IMP_Imap_PermanentFlags($status['permflags'], $status['flags']);
523: } catch (Exception $e) {}
524: }
525:
526: return new IMP_Imap_PermanentFlags();
527:
528: case 'poll_info':
529: $info = new stdClass;
530: $info->msgs = 0;
531: $info->recent = 0;
532: $info->unseen = 0;
533:
534: try {
535: if ($msgs_info = $this->imp_imap->status($this->_mbox, Horde_Imap_Client::STATUS_RECENT_TOTAL | Horde_Imap_Client::STATUS_UNSEEN | Horde_Imap_Client::STATUS_MESSAGES)) {
536: if (!empty($msgs_info['recent_total'])) {
537: $info->recent = intval($msgs_info['recent_total']);
538: }
539: $info->msgs = intval($msgs_info['messages']);
540: $info->unseen = intval($msgs_info['unseen']);
541: }
542: } catch (IMP_Imap_Exception $e) {}
543:
544: return $info;
545:
546: case 'polled':
547: return (!$this->search &&
548: (($elt = $this->tree_elt) && $elt->polled));
549:
550: case 'pref_from':
551: return $this->prefFrom($this->_mbox);
552:
553: case 'pref_to':
554: return $this->prefTo($this->_mbox);
555:
556: case 'query':
557: return $injector->getInstance('IMP_Search')->isQuery($this->_mbox);
558:
559: case 'readonly':
560: return (($acl = $this->acl) &&
561: !$acl[Horde_Imap_Client::ACL_DELETEMBOX] &&
562: !$acl[Horde_Imap_Client::ACL_DELETEMSGS] &&
563: !$acl[Horde_Imap_Client::ACL_EXPUNGE] &&
564: !$acl[Horde_Imap_Client::ACL_INSERT] &&
565: !$acl[Horde_Imap_Client::ACL_SEEN] &&
566: !$acl[Horde_Imap_Client::ACL_WRITE]);
567:
568: case 'remote':
569: return $injector->getInstance('IMP_Remote')->isRemoteMbox($this->_mbox);
570:
571: case 'remote_account':
572: $remote = $injector->getInstance('IMP_Remote');
573: $account = ($this->remote_container)
574: ? $remote[$this->_mbox]
575: : $remote->getRemoteById($this->_mbox);
576: return $account ?: null;
577:
578: case 'remote_container':
579: return (($elt = $this->tree_elt) && $elt->remote);
580:
581: case 'remote_mbox':
582: return (($elt = $this->tree_elt) && $elt->remote_mbox);
583:
584: case 'search':
585: return $injector->getInstance('IMP_Search')->isSearchMbox($this->_mbox);
586:
587: case 'size':
588: return $injector->getInstance('IMP_Mbox_Size')->getSize($this);
589:
590: case 'sortob':
591: return $this->imp_imap->access(IMP_Imap::ACCESS_SORT)
592: ? $injector->getInstance('IMP_Prefs_Sort')
593: : $injector->getInstance('IMP_Prefs_Sort_None');
594:
595: case 'spam':
596: $special = $this->getSpecialMailboxes();
597: return ($this->_mbox == $special[self::SPECIAL_SPAM]);
598:
599: case 'spam_show':
600: $p = $this->imp_imap->config->spam_params;
601: return (!empty($p) && (!empty($p['display']) || !$this->spam));
602:
603: case 'special':
604: $special = $this->getSpecialMailboxes();
605:
606: switch ($this->_mbox) {
607: case $special[self::SPECIAL_COMPOSETEMPLATES]:
608: case $special[self::SPECIAL_DRAFTS]:
609: case $special[self::SPECIAL_SPAM]:
610: case $special[self::SPECIAL_TRASH]:
611: return true;
612: }
613:
614: return in_array($this->_mbox, array_merge(
615: $special[self::SPECIAL_SENT],
616: $special[self::SPECIAL_USER]
617: ));
618:
619: case 'special_outgoing':
620: $special = $this->getSpecialMailboxes();
621:
622: return in_array($this->_mbox, array_merge(
623: array(
624: $special[self::SPECIAL_COMPOSETEMPLATES],
625: $special[self::SPECIAL_DRAFTS]
626: ),
627: $special[self::SPECIAL_SENT]
628: ));
629:
630: case 'specialvfolder':
631: return !$this->editvfolder;
632:
633: case 'sub':
634: return (($elt = $this->tree_elt) && $elt->subscribed);
635:
636: case 'subfolders':
637: return $this->get(array_merge(array($this->_mbox), $this->subfolders_only));
638:
639: case 'subfolders_only':
640: return $this->get($this->imp_imap->listMailboxes($this->imap_mbox_ob->list_escape . $this->namespace_delimiter . '*', null, array('flat' => true)));
641:
642: case 'systemquery':
643: return $injector->getInstance('IMP_Search')->isSystemQuery($this->_mbox);
644:
645: case 'templates':
646: $special = $this->getSpecialMailboxes();
647: return ($this->_mbox == $special[self::SPECIAL_COMPOSETEMPLATES]);
648:
649: case 'trash':
650: $special = $this->getSpecialMailboxes();
651: return ($this->_mbox == $special[self::SPECIAL_TRASH]);
652:
653: case 'tree_elt':
654: $ftree = $injector->getInstance('IMP_Ftree');
655: return $ftree[$this->_mbox];
656:
657: case 'uidvalid':
658: $cache = $injector->getInstance('IMP_Mailbox_SessionCache');
659: $uidvalid = $cache->getUidvalidity($this->_mbox);
660: if ($uidvalid === 0) {
661: return;
662: }
663:
664:
665: if (!$this->is_imap || $this->nonimap) {
666: $cache->setUidvalidity($this->_mbox, 0);
667: return false;
668: }
669:
670: $status = $this->imp_imap->status($this->_mbox, Horde_Imap_Client::STATUS_UIDVALIDITY);
671:
672: if (($first = ($uidvalid === false)) ||
673: ($status['uidvalidity'] != $uidvalid)) {
674: $uidvalid = $status['uidvalidity'];
675: $cache->setUidvalidity($this->_mbox, $uidvalid);
676:
677: if (!$first) {
678: throw new IMP_Exception(_("Mailbox structure on server has changed."));
679: }
680: }
681:
682: return $uidvalid;
683:
684: case 'utf7imap':
685: return Horde_String::convertCharset($this->_mbox, 'UTF-8', 'UTF7-IMAP');
686:
687: case 'value':
688: return $this->_mbox;
689:
690: case 'vfolder':
691: return $injector->getInstance('IMP_Search')->isVFolder($this->_mbox);
692:
693: case 'vfolder_container':
694: return ($this->_mbox == IMP_Ftree_Account_Vfolder::VFOLDER_KEY);
695:
696: case 'vinbox':
697: return $injector->getInstance('IMP_Search')->isVinbox($this->_mbox);
698:
699: case 'vtrash':
700: return $injector->getInstance('IMP_Search')->isVTrash($this->_mbox);
701: }
702:
703: return false;
704: }
705:
706: 707:
708: public function __set($key, $value)
709: {
710: global $injector;
711:
712: switch ($key) {
713: case 'display':
714: $injector->getInstance('IMP_Mailbox_SessionCache')->setDisplay($this->_mbox, $value);
715: break;
716: }
717: }
718:
719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730:
731: public function create(array $opts = array())
732: {
733: global $injector, $notification, $prefs;
734:
735: if ($this->exists) {
736: return true;
737: }
738:
739: $imp_imap = $this->imp_imap;
740:
741:
742: if (!$imp_imap->access(IMP_Imap::ACCESS_CREATEMBOX)) {
743: Horde::permissionDeniedError(
744: 'imp',
745: 'create_mboxes',
746: _("You are not allowed to create mailboxes.")
747: );
748: return false;
749: }
750: if (!$imp_imap->access(IMP_Imap::ACCESS_CREATEMBOX_MAX)) {
751: Horde::permissionDeniedError(
752: 'imp',
753: 'max_create_mboxes',
754: sprintf(_("You are not allowed to create more than %d mailboxes."), $imp_imap->max_create_mboxes)
755: );
756: return false;
757: }
758:
759:
760: $special_use = isset($opts['special_use'])
761: ? $opts['special_use']
762: : array();
763:
764:
765: try {
766: $imp_imap->createMailbox($this->_mbox, array('special_use' => $special_use));
767: } catch (IMP_Imap_Exception $e) {
768: if ($e->getCode() == $e::USEATTR) {
769: unset($opts['special_use']);
770: return $this->create($opts);
771: }
772:
773: $e->notify(sprintf(_("The mailbox \"%s\" was not created. This is what the server said"), $this->display) . ': ' . $e->getMessage());
774: return false;
775: }
776:
777: $notification->push(sprintf(_("The mailbox \"%s\" was successfully created."), $this->display), 'horde.success');
778:
779:
780: if ((!isset($opts['subscribe']) && $prefs->getValue('subscribe')) ||
781: !empty($opts['subscribe'])) {
782: try {
783: $imp_imap->subscribeMailbox($this->_mbox, true);
784: } catch (IMP_Imap_Exception $e) {}
785: }
786:
787:
788: $injector->getInstance('IMP_Ftree')->insert($this->_mbox);
789:
790: return true;
791: }
792:
793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804:
805: public function delete(array $opts = array())
806: {
807: global $injector, $notification;
808:
809: if ($this->vfolder) {
810: if ($this->editvfolder) {
811: $imp_search = $injector->getInstance('IMP_Search');
812: $label = $imp_search[$this->_mbox]->label;
813: unset($imp_search[$this->_mbox]);
814: $notification->push(sprintf(_("Deleted Virtual Folder \"%s\"."), $label), 'horde.success');
815: return true;
816: }
817:
818: $notification->push(sprintf(_("Could not delete Virtual Folder \"%s\"."), $this->label), 'horde.error');
819: return false;
820: }
821:
822: $deleted = array();
823: $imp_imap = $this->imp_imap;
824: if (empty($opts['subfolders'])) {
825: $to_delete = array($this);
826: } else {
827: $to_delete = empty($opts['subfolders_only'])
828: ? $this->subfolders
829: : $this->subfolders_only;
830: }
831:
832: foreach ($to_delete as $val) {
833: if (!$val->access_deletembox_acl) {
834: $notification->push(sprintf(_("The mailbox \"%s\" may not be deleted."), $val->display), 'horde.error');
835: continue;
836: }
837:
838: try {
839: $imp_imap->deleteMailbox($val->value);
840: $notification->push(sprintf(_("The mailbox \"%s\" was successfully deleted."), $val->display), 'horde.success');
841: $deleted[] = $val;
842: } catch (IMP_Imap_Exception $e) {
843: $e->notify(sprintf(_("The mailbox \"%s\" was not deleted. This is what the server said"), $val->display) . ': ' . $e->getMessage());
844: }
845: }
846:
847: if (!empty($deleted)) {
848: $injector->getInstance('IMP_Ftree')->delete($deleted);
849: $this->_onDelete($deleted);
850: }
851:
852: return (count($deleted) == count($to_delete));
853: }
854:
855: 856: 857: 858: 859: 860: 861: 862:
863: public function rename($new_name)
864: {
865: global $injector, $notification;
866:
867:
868: if (!strlen($new_name)) {
869: return false;
870: }
871:
872: if (!$this->access_deletembox_acl) {
873: $notification->push(sprintf(_("The mailbox \"%s\" may not be renamed."), $this->display), 'horde.error');
874: return false;
875: }
876:
877: $new_mbox = $this->get($new_name);
878: $old_list = $this->subfolders;
879:
880: try {
881: $this->imp_imap->renameMailbox($this->_mbox, $new_mbox);
882: } catch (IMP_Imap_Exception $e) {
883: $e->notify(sprintf(_("Renaming \"%s\" to \"%s\" failed. This is what the server said"), $this->display, $new_mbox->display) . ': ' . $e->getMessage());
884: return false;
885: }
886:
887: $notification->push(sprintf(_("The mailbox \"%s\" was successfully renamed to \"%s\"."), $this->display, $new_mbox->display), 'horde.success');
888:
889: $injector->getInstance('IMP_Ftree')->rename($this->_mbox, $new_mbox);
890: $this->_onDelete($old_list);
891:
892: return true;
893: }
894:
895: 896: 897: 898: 899: 900: 901: 902: 903:
904: public function subscribe($sub, array $opts = array())
905: {
906: global $injector, $notification, $prefs;
907:
908:
909: if (!$prefs->getValue('subscribe') ||
910: $this->nonimap ||
911: $this->container) {
912: return false;
913: }
914:
915: if (!$sub && $this->inbox) {
916: $notification->push(sprintf(_("You cannot unsubscribe from \"%s\"."), $this->display), 'horde.error');
917: return false;
918: }
919:
920: $imp_imap = $this->imp_imap;
921:
922: try {
923: $imp_imap->subscribeMailbox($this->_mbox, $sub);
924: } catch (IMP_Imap_Exception $e) {
925: if ($sub) {
926: $e->notify(sprintf(_("You were not subscribed to \"%s\". Here is what the server said"), $this->display) . ': ' . $e->getMessage());
927: } else {
928: $e->notify(sprintf(_("You were not unsubscribed from \"%s\". Here is what the server said"), $this->display) . ': ' . $e->getMessage());
929: }
930: return false;
931: }
932:
933: $imap_tree = $injector->getInstance('IMP_Ftree');
934: if ($sub) {
935: $imap_tree->subscribe($this->_mbox);
936: } else {
937: $imap_tree->unsubscribe($this->_mbox);
938: }
939:
940: if (empty($opts['subfolders'])) {
941: $notify = $sub
942: ? sprintf(_("You were successfully subscribed to \"%s\"."), $this->display)
943: : sprintf(_("You were successfully unsubscribed from \"%s\"."), $this->display);
944: } else {
945: $action = false;
946:
947: foreach ($this->subfolders_only as $val) {
948: try {
949: $imp_imap->subscribeMailbox($val, $sub);
950: if ($sub) {
951: $imap_tree->subscribe($val);
952: } else {
953: $imap_tree->unsubscribe($val);
954: }
955:
956: $action = true;
957: } catch (IMP_Imap_Exception $e) {
958:
959: }
960: }
961:
962: if ($action) {
963: $notify = $sub
964: ? sprintf(_("You were successfully subscribed to \"%s\" and all subfolders."), $this->display)
965: : sprintf(_("You were successfully unsubscribed from \"%s\" and all subfolders."), $this->display);
966: }
967: }
968:
969: $notification->push($notify, 'horde.success');
970:
971: return true;
972: }
973:
974: 975: 976:
977: public function filter()
978: {
979: if (!$this->search) {
980: $GLOBALS['injector']->getInstance('IMP_Filter')->filter($this);
981: }
982: }
983:
984: 985: 986: 987: 988: 989:
990: public function filterOnDisplay()
991: {
992: if ($this->inbox &&
993: $GLOBALS['prefs']->getValue('filter_on_display')) {
994: $this->filter();
995: return true;
996: }
997:
998: return false;
999: }
1000:
1001: 1002: 1003: 1004: 1005:
1006: public function getSearchOb()
1007: {
1008: $imp_search = $GLOBALS['injector']->getInstance('IMP_Search');
1009: return $imp_search[$this->_mbox];
1010: }
1011:
1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019:
1020: public function getIndicesOb($in)
1021: {
1022: return new IMP_Indices($this, $in);
1023: }
1024:
1025: 1026: 1027: 1028: 1029: 1030: 1031:
1032: public function getSort($convert = false)
1033: {
1034: global $prefs;
1035:
1036: $mbox = $this->search
1037: ? $this
1038: : self::get($this->pref_from);
1039:
1040: $ob = $this->sortob[strval($mbox)];
1041: $ob->convertSortby();
1042:
1043: if ($convert && ($ob->sortby == IMP::IMAP_SORT_DATE)) {
1044: $ob->sortby = $prefs->getValue('sortdate');
1045: }
1046:
1047: return $ob;
1048: }
1049:
1050: 1051: 1052: 1053: 1054: 1055: 1056:
1057: public function setSort($by = null, $dir = null, $delete = false)
1058: {
1059: $mbox = $this->search
1060: ? $this
1061: : self::get($this->pref_from);
1062:
1063: if ($delete) {
1064: unset($this->sortob[strval($mbox)]);
1065: } else {
1066: $change = array();
1067: if (!is_null($by)) {
1068: $change['by'] = $by;
1069: }
1070: if (!is_null($dir)) {
1071: $change['dir'] = $dir;
1072: }
1073: $this->sortob[strval($mbox)] = $change;
1074: }
1075: }
1076:
1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085:
1086: public function hideDeletedMsgs($deleted = false)
1087: {
1088: global $prefs;
1089:
1090: if (!$this->access_flags) {
1091: return true;
1092: }
1093:
1094: if ($prefs->getValue('use_trash')) {
1095: 1096:
1097: return $this->get($prefs->getValue(self::MBOX_TRASH))->vtrash
1098: ? !$this->vtrash
1099: : ($prefs->getValue('delhide_trash') ? true : $deleted);
1100: }
1101:
1102: return $prefs->getValue('delhide');
1103: }
1104:
1105: 1106: 1107: 1108: 1109:
1110: public function setHideDeletedMsgs($value)
1111: {
1112: $GLOBALS['prefs']->setValue('delhide', $value);
1113: $GLOBALS['injector']->getInstance('IMP_Factory_MailboxList')->expireAll();
1114: }
1115:
1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126:
1127: public function runSearchQuery(Horde_Imap_Client_Search_Query $query,
1128: $sortby = null, $sortdir = null)
1129: {
1130: try {
1131: $results = $this->imp_imap->search($this, $query, array(
1132: 'sort' => is_null($sortby) ? null : array($sortby)
1133: ));
1134: if ($sortdir) {
1135: $results['match']->reverse();
1136: }
1137: return $this->getIndicesOb($results['match']);
1138: } catch (IMP_Imap_Exception $e) {
1139: return new IMP_Indices();
1140: }
1141: }
1142:
1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152:
1153: public function url($page, $buid = null, $encode = true)
1154: {
1155: if ($page instanceof Horde_Url) {
1156: return $page->add($this->urlParams($buid))->setRaw(!$encode);
1157: }
1158:
1159: switch ($GLOBALS['registry']->getView()) {
1160: case Horde_Registry::VIEW_BASIC:
1161: switch ($page) {
1162: case 'message':
1163: return IMP_Basic_Message::url(array(
1164: 'buid' => $buid,
1165: 'mailbox' => $this->_mbox
1166: ))->setRaw(!$encode);
1167:
1168: case 'mailbox':
1169: return IMP_Basic_Mailbox::url(array(
1170: 'mailbox' => $this->_mbox
1171: ))->setRaw(!$encode);
1172: }
1173: break;
1174:
1175: case Horde_Registry::VIEW_DYNAMIC:
1176: $anchor = is_null($buid)
1177: ? ('mbox:' . $this->form_to)
1178: : ('msg:' . $this->form_to . ';' . $buid);
1179: return Horde::url('index.php')->setAnchor($anchor);
1180:
1181: case Horde_Registry::VIEW_MINIMAL:
1182: switch ($page) {
1183: case 'message':
1184: return IMP_Minimal_Message::url(array(
1185: 'buid' => $buid,
1186: 'mailbox' => $this->_mbox
1187: ))->setRaw(!$encode);
1188:
1189: case 'mailbox':
1190: return IMP_Minimal_Mailbox::url(array(
1191: 'mailbox' => $this->_mbox
1192: ))->setRaw(!$encode);
1193: }
1194: break;
1195:
1196: case Horde_Registry::VIEW_SMARTMOBILE:
1197: $url = Horde::url('smartmobile.php');
1198: $anchor = is_null($buid)
1199: ? ('mbox=' . $this->form_to)
1200: : ('msg=' . $this->form_to . ';' . $buid);
1201: $url->setAnchor('mailbox?' . $anchor);
1202: return $url;
1203: }
1204:
1205: return Horde::url($page . '.php')->add($this->urlParams($buid))->setRaw(!$encode);
1206: }
1207:
1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216:
1217: public function urlParams($buid = null)
1218: {
1219: $params = array('mailbox' => $this->form_to);
1220: if (!is_null($buid)) {
1221: $params['buid'] = $buid;
1222: }
1223: return $params;
1224: }
1225:
1226: 1227: 1228: 1229: 1230: 1231: 1232: 1233: 1234:
1235: public function equals($mbox)
1236: {
1237: return ($mbox == $this->_mbox);
1238: }
1239:
1240: 1241: 1242: 1243: 1244: 1245: 1246:
1247: public function fromBuids($buids)
1248: {
1249: if (is_array($buids)) {
1250: $buids = new IMP_Indices($this->_mbox, $buids);
1251: }
1252: $buid_list = $buids->getSingle(true);
1253:
1254: $out = new IMP_Indices();
1255:
1256: if ($buid_list[1]) {
1257: $list_ob = $this->list_ob;
1258: foreach ($buid_list[1] as $buid) {
1259: if ($resolve = $list_ob->resolveBuid($buid)) {
1260: $out->add($resolve['m'], $resolve['u']);
1261: }
1262: }
1263: }
1264:
1265: return $out;
1266: }
1267:
1268: 1269: 1270: 1271: 1272: 1273: 1274:
1275: public function toBuids(IMP_Indices $uids)
1276: {
1277: $list_ob = $this->list_ob;
1278: $out = new IMP_Indices();
1279:
1280: foreach ($uids as $val) {
1281: foreach ($val->uids as $val2) {
1282: $out->add($this->_mbox, $list_ob->getBuid($val->mbox, $val2));
1283: }
1284: }
1285:
1286: return $out;
1287: }
1288:
1289: 1290: 1291: 1292: 1293: 1294: 1295:
1296: public function createMailboxName($new)
1297: {
1298: if ($this->remote_container) {
1299: $new = $this->remote_account->mailbox($new);
1300: } else {
1301: $ns_info = $this->namespace_info;
1302: $new = strlen($this)
1303: ? ($this->_mbox . $ns_info->delimiter . $new)
1304: : $ns_info->name . $new;
1305: }
1306:
1307: return self::get($new);
1308: }
1309:
1310:
1311:
1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320:
1321: public static function formFrom($mbox)
1322: {
1323: return is_array($mbox)
1324: ? array_filter(array_map(array(__CLASS__, 'formFrom'), $mbox))
1325:
1326: : self::get(base64_decode(strtr($mbox, '-_', '+/')));
1327: }
1328:
1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337:
1338: public static function formTo($mbox)
1339: {
1340: return is_array($mbox)
1341: ? array_filter(array_map(array(__CLASS__, 'formTo'), $mbox))
1342:
1343: : strtr(rtrim(base64_encode($mbox), '='), '+/', '-_');
1344: }
1345:
1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353:
1354: public static function getSpecialMailboxes()
1355: {
1356: global $injector;
1357:
1358: return $injector->getInstance('IMP_Mailbox_SessionCache')->getSpecialMailboxes();
1359: }
1360:
1361: 1362: 1363: 1364: 1365: 1366:
1367: public static function getSpecialMailboxesSort()
1368: {
1369: $out = array();
1370:
1371: foreach (array_filter(self::getSpecialMailboxes()) as $val) {
1372: if (is_array($val)) {
1373: $out = array_merge($out, $val);
1374: } else {
1375: $out[] = $val;
1376: }
1377: }
1378:
1379: $tmp = array();
1380: foreach ($out as $val) {
1381: $tmp[strval($val)] = $val->abbrev_label;
1382: }
1383: asort($tmp, SORT_LOCALE_STRING);
1384:
1385: return self::get(array_keys($tmp));
1386: }
1387:
1388: 1389: 1390: 1391: 1392: 1393: 1394:
1395: public static function prefFrom($mbox)
1396: {
1397: $imp_imap = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
1398: if ($imp_imap->isImap()) {
1399: $empty_ns = $imp_imap->getNamespace('');
1400:
1401: if (!is_null($empty_ns) &&
1402: (strpos($mbox, $empty_ns->delimiter) === 0)) {
1403:
1404: return substr($mbox, strlen($empty_ns->delimiter));
1405: } elseif ($imp_imap->getNamespace($mbox, true) === null) {
1406:
1407: $def_ns = $imp_imap->getNamespace($imp_imap::NS_DEFAULT);
1408: return $def_ns->name . $mbox;
1409: }
1410: }
1411:
1412: return $mbox;
1413: }
1414:
1415: 1416: 1417: 1418: 1419: 1420: 1421:
1422: public static function prefTo($mbox)
1423: {
1424: global $injector;
1425:
1426: $cache = $injector->getInstance('IMP_Mailbox_SessionCache');
1427: $mbox_str = strval($mbox);
1428:
1429: if (($pref_to = $cache->getPrefTo($mbox_str)) !== false) {
1430: return $pref_to;
1431: }
1432:
1433: if (($ns = self::get($mbox)->namespace_info) !== null) {
1434: $imp_imap = $injector->getInstance('IMP_Factory_Imap')->create();
1435: $def_ns = $imp_imap->getNamespace($imp_imap::NS_DEFAULT);
1436:
1437: if ($ns->name == $def_ns->name) {
1438:
1439: $ret = substr($mbox_str, strlen($def_ns->name));
1440: } else {
1441: $empty_ns = $imp_imap->getNamespace('');
1442: if ($ns->name == $empty_ns->name) {
1443:
1444: $ret = $empty_ns->delimiter . $mbox_str;
1445: }
1446: }
1447: }
1448:
1449: $cache->setPrefTo($mbox_str, $ret);
1450:
1451: return $ret;
1452: }
1453:
1454:
1455:
1456: 1457: 1458: 1459: 1460: 1461: 1462: 1463: 1464: 1465: 1466: 1467: 1468: 1469: 1470:
1471: protected function _getCacheID($date = false)
1472: {
1473: $date = $date
1474: ? 'D' . date('z')
1475: : '';
1476:
1477: if ($this->search) {
1478: return '1' . ($date ? '|' . $date : '');
1479: }
1480:
1481: $sortpref = $this->getSort(true);
1482: $addl = array($sortpref->sortby, $sortpref->sortdir);
1483: if ($date) {
1484: $addl[] = $date;
1485: }
1486:
1487: try {
1488: return $this->imp_imap->getCacheId($this->_mbox, $addl);
1489: } catch (IMP_Imap_Exception $e) {
1490:
1491: return strval(new Horde_Support_Randomid());
1492: }
1493: }
1494:
1495: 1496: 1497: 1498: 1499: 1500: 1501: 1502: 1503: 1504:
1505: protected function _getDisplay($notranslate = false)
1506: {
1507: global $injector;
1508:
1509: $cache = $injector->getInstance('IMP_Mailbox_SessionCache');
1510: if (!$notranslate &&
1511: (($display = $cache->getDisplay($this->_mbox)) !== false)) {
1512: return $display;
1513: }
1514:
1515:
1516: if (($elt = $this->tree_elt) && $elt->nonimap && $elt->container) {
1517: if ($elt->remote) {
1518: return _("Remote Accounts");
1519: } elseif ($elt->vfolder) {
1520: return _("Virtual Folders");
1521: } elseif ($elt->namespace_other) {
1522: return _("Other Users");
1523: } elseif ($elt->namespace_shared) {
1524: return _("Shared");
1525: }
1526: }
1527:
1528:
1529: if ($this->remote) {
1530: return $injector->getInstance('IMP_Remote')->label($this->_mbox);
1531: }
1532:
1533: $ns_info = $this->namespace_info;
1534: $out = $this->_mbox;
1535:
1536: if (!is_null($ns_info)) {
1537:
1538: if (strlen($ns_info->translation) && $this->namespace) {
1539: $cache->setDisplay($this->_mbox, $ns_info->translation);
1540: return $ns_info->translation;
1541: }
1542:
1543:
1544: if ($ns_info->type === $ns_info::NS_PERSONAL) {
1545: $out = $ns_info->stripNamespace($this->_mbox);
1546: }
1547: }
1548:
1549: if ($notranslate) {
1550: return $out;
1551: }
1552:
1553: 1554:
1555: foreach ($this->getSpecialMailboxes() as $key => $val) {
1556: switch ($key) {
1557: case self::SPECIAL_COMPOSETEMPLATES:
1558: if (strval($val) == $this->_mbox) {
1559: $out = _("Templates");
1560: }
1561: break;
1562:
1563: case self::SPECIAL_DRAFTS:
1564: if (strval($val) == $this->_mbox) {
1565: $out = _("Drafts");
1566: }
1567: break;
1568:
1569: case self::SPECIAL_SENT:
1570: if (in_array($this->_mbox, $val)) {
1571: $out = _("Sent");
1572:
1573: 1574:
1575: $identity = $injector->getInstance('IMP_Identity');
1576: $sm_all = $identity->getAllSentmail(false);
1577: if (count($sm_all) > 1) {
1578: $sm = array_keys($sm_all, $this->_mbox);
1579: if (count($sm) === 1) {
1580: $out .= ' (' . $identity->getValue('id', reset($sm)) . ')';
1581: }
1582: }
1583: }
1584: break;
1585:
1586: case self::SPECIAL_SPAM:
1587: if (strval($val) == $this->_mbox) {
1588: $out = _("Spam");
1589: }
1590: break;
1591:
1592: case self::SPECIAL_TRASH:
1593: if (strval($val) == $this->_mbox) {
1594: $out = _("Trash");
1595: }
1596: break;
1597: }
1598: }
1599:
1600: if ($this->inbox) {
1601: $out = _("Inbox");
1602: } elseif (($this->_mbox == $out) &&
1603: !is_null($ns_info) &&
1604: (strpos($out, 'INBOX' . $ns_info->delimiter) === 0)) {
1605: $out = substr_replace($out, _("Inbox"), 0, 5);
1606: }
1607:
1608: $cache->setDisplay($this->_mbox, $out);
1609:
1610: return $out;
1611: }
1612:
1613: 1614: 1615: 1616: 1617: 1618: 1619: 1620: 1621: 1622:
1623: protected function _getIcon()
1624: {
1625: global $injector;
1626:
1627: $info = new stdClass;
1628: $info->iconopen = null;
1629: $info->user_icon = false;
1630:
1631: if ($this->container) {
1632:
1633: if ($this->is_open) {
1634: $info->alt = _("Opened Folder");
1635: $info->class = 'folderopenImg';
1636: $info->icon = 'folders/open.png';
1637: } else {
1638: $info->alt = _("Folder");
1639: $info->class = 'folderImg';
1640: $info->icon = 'folders/folder.png';
1641: $info->iconopen = Horde_Themes::img('folders/open.png');
1642: }
1643: } elseif ($this->remote_container) {
1644: $info->alt = _("Remote Account");
1645: $info->class = 'remoteImg';
1646: $info->icon = 'shared.png';
1647: } else {
1648: $special = $this->getSpecialMailboxes();
1649:
1650: switch ($this->_mbox) {
1651: case 'INBOX':
1652: $info->alt = _("Inbox");
1653: $info->class = 'inboxImg';
1654: $info->icon = 'folders/inbox.png';
1655: break;
1656:
1657: case $special[self::SPECIAL_COMPOSETEMPLATES]:
1658: $info->alt = ("Templates");
1659: $info->class = 'composetemplatesImg';
1660: $info->icon = 'folders/drafts.png';
1661: break;
1662:
1663: case $special[self::SPECIAL_DRAFTS]:
1664: $info->alt = _("Drafts");
1665: $info->class = 'draftsImg';
1666: $info->icon = 'folders/drafts.png';
1667: break;
1668:
1669: case $special[self::SPECIAL_SPAM]:
1670: $info->alt = _("Spam");
1671: $info->class = 'spamImg';
1672: $info->icon = 'folders/spam.png';
1673: break;
1674:
1675: case $special[self::SPECIAL_TRASH]:
1676: $info->alt = _("Trash");
1677: $info->class = 'trashImg';
1678: $info->icon = 'folders/trash.png';
1679: break;
1680:
1681: default:
1682: if (in_array($this->_mbox, $special[self::SPECIAL_SENT])) {
1683: $info->alt = _("Sent");
1684: $info->class = 'sentImg';
1685: $info->icon = 'folders/sent.png';
1686: } else {
1687: $info->alt = in_array($this->_mbox, $special[self::SPECIAL_USER])
1688: ? $this->display
1689: : _("Mailbox");
1690: if ($this->is_open) {
1691: $info->class = 'folderopenImg';
1692: $info->icon = 'folders/open.png';
1693: } else {
1694: $info->class = 'folderImg';
1695: $info->icon = 'folders/folder.png';
1696: }
1697: }
1698: break;
1699: }
1700:
1701:
1702: if ($this->vfolder) {
1703: $imp_search = $injector->getInstance('IMP_Search');
1704: if ($imp_search->isVTrash($this->_mbox)) {
1705: $info->alt = $imp_search[$this->_mbox]->label;
1706: $info->class = 'trashImg';
1707: $info->icon = 'folders/trash.png';
1708: } elseif ($imp_search->isVinbox($this->_mbox)) {
1709: $info->alt = $imp_search[$this->_mbox]->label;
1710: $info->class = 'inboxImg';
1711: $info->icon = 'folders/inbox.png';
1712: }
1713: }
1714: }
1715:
1716:
1717: $mi = $injector->getInstance('IMP_Mailbox_SessionCache')->getIcons($this->_mbox);
1718: if (!empty($mi)) {
1719: if (isset($mi['alt'])) {
1720: $info->alt = $mi['alt'];
1721: }
1722: $info->icon = strval($mi['icon']);
1723: $info->user_icon = true;
1724: } elseif ($info->icon) {
1725: $info->icon = Horde_Themes::img($info->icon);
1726: }
1727:
1728: return $info;
1729: }
1730:
1731: 1732: 1733: 1734: 1735:
1736: protected function _onDelete($deleted)
1737: {
1738:
1739: foreach ($this->get($deleted) as $val) {
1740: $val->setSort(null, null, true);
1741: }
1742: }
1743:
1744: }
1745: