1<?php
2/**
3 * Copyright 2004-2017 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 2004-2017 Horde LLC
10 * @license   http://www.horde.org/licenses/gpl GPL
11 * @package   IMP
12 */
13
14/**
15 * Message thread display.
16 * Usable in both basic and dynamic views.
17 *
18 * @author    Michael Slusarz <slusarz@horde.org>
19 * @category  Horde
20 * @copyright 2004-2017 Horde LLC
21 * @license   http://www.horde.org/licenses/gpl GPL
22 * @package   IMP
23 */
24class IMP_Basic_Thread extends IMP_Basic_Base
25{
26    /**
27     */
28    protected function _init()
29    {
30        global $injector, $notification, $page_output, $registry, $session;
31
32        $imp_mailbox = $this->indices->mailbox->list_ob;
33
34        switch ($mode = $this->vars->get('mode', 'thread')) {
35        case 'thread':
36            /* THREAD MODE: Make sure we have a valid index. */
37            list($m, $u) = $this->indices->getSingle();
38            $imp_indices = $imp_mailbox->getFullThread($u, $m);
39            break;
40
41        default:
42            /* MSGVIEW MODE: Make sure we have a valid list of messages. */
43            $imp_indices = $this->indices;
44            break;
45        }
46
47        if (!count($imp_indices)) {
48            $notification->push(_("Could not load message."), 'horde.error');
49            $this->indices->mailbox->url('mailbox')->redirect();
50        }
51
52        /* Run through action handlers. */
53        switch ($this->vars->actionID) {
54        case 'add_address':
55            try {
56                $contact_link = $injector->getInstance('IMP_Contacts')->addAddress($this->vars->address, $this->vars->name);
57                $notification->push(sprintf(_("Entry \"%s\" was successfully added to the address book"), $contact_link), 'horde.success', array('content.raw'));
58            } catch (Horde_Exception $e) {
59                $notification->push($e);
60            }
61            break;
62        }
63
64        $msgs = $tree = array();
65        $subject = '';
66        $page_label = $this->indices->mailbox->label;
67
68        $imp_ui = $injector->getInstance('IMP_Message_Ui');
69
70        $query = new Horde_Imap_Client_Fetch_Query();
71        $query->envelope();
72
73        /* Force images to show in HTML data. */
74        $injector->getInstance('IMP_Images')->alwaysShow = true;
75
76        $multiple = (count($imp_indices) > 1);
77
78        foreach ($imp_indices as $ob) {
79            $imp_imap = $ob->mbox->imp_imap;
80            $fetch_res = $imp_imap->fetch($ob->mbox, $query, array(
81                'ids' => $imp_imap->getIdsOb($ob->uids)
82            ));
83
84            foreach ($ob->uids as $idx) {
85                $envelope = $fetch_res[$idx]->getEnvelope();
86
87                /* Get the body of the message. */
88                $curr_msg = $curr_tree = array();
89                $contents = $injector->getInstance('IMP_Factory_Contents')->create($ob->mbox->getIndicesOb($idx));
90                $mime_id = $contents->findBody();
91                if ($contents->canDisplay($mime_id, IMP_Contents::RENDER_INLINE)) {
92                    $ret = $contents->renderMIMEPart($mime_id, IMP_Contents::RENDER_INLINE);
93                    $ret = reset($ret);
94                    $curr_msg['body'] = $ret['data'];
95
96                    if (!empty($ret['js'])) {
97                        $page_output->addInlineScript($ret['js'], true);
98                    }
99                } else {
100                    $curr_msg['body'] = '<em>' . _("There is no text that can be displayed inline.") . '</em>';
101                }
102                $curr_msg['idx'] = $idx;
103
104                /* Get headers for the message. */
105                $curr_msg['date'] = $imp_ui->getLocalTime($envelope->date);
106
107                if ($this->indices->mailbox->special_outgoing) {
108                    $curr_msg['addr_to'] = true;
109                    $curr_msg['addr'] = _("To:") . ' ' . $imp_ui->buildAddressLinks($envelope->to, Horde::selfUrlParams());
110                    $addr = _("To:") . ' ' . htmlspecialchars($envelope->to[0]->label, ENT_COMPAT, 'UTF-8');
111                } else {
112                    $from = $envelope->from;
113                    $curr_msg['addr_to'] = false;
114                    $curr_msg['addr'] = $imp_ui->buildAddressLinks($from, Horde::selfUrlParams());
115                    $addr = htmlspecialchars($from[0]->label, ENT_COMPAT, 'UTF-8');
116                }
117
118                $subject_header = htmlspecialchars($envelope->subject, ENT_COMPAT, 'UTF-8');
119
120                switch ($mode) {
121                case 'thread':
122                    if (empty($subject)) {
123                        $subject = preg_replace('/^re:\s*/i', '', $subject_header);
124                    }
125                    $curr_msg['link'] = $multiple
126                        ? Horde::widget(array('url' => '#display', 'title' => _("Thread List"), 'nocheck' => true))
127                        : '';
128                    $curr_tree['subject'] = $imp_mailbox->getThreadOb($imp_mailbox->getArrayIndex($fetch_res[$idx]->getUid(), $ob->mbox) + 1)->img;
129                    break;
130
131                default:
132                    $curr_msg['link'] = Horde::widget(array('url' => '#display', 'title' => _("Back to Multiple Message View Index"), 'nocheck' => true));
133                    $curr_tree['subject'] = '';
134                    break;
135                }
136
137                switch ($registry->getView()) {
138                case $registry::VIEW_BASIC:
139                    $curr_msg['link'] .= ' | ' . Horde::widget(array('url' => $this->indices->mailbox->url('message', $idx), 'title' => _("Go to Message"), 'nocheck' => true)) .
140                        ' | ' . Horde::widget(array('url' => $this->indices->mailbox->url('mailbox')->add(array('start' => $imp_mailbox->getArrayIndex($idx))), 'title' => sprintf(_("Bac_k to %s"), $page_label)));
141                    break;
142                }
143
144                $curr_tree['subject'] .= Horde::link('#i' . $idx) . Horde_String::truncate($subject_header, 60) . '</a> (' . $addr . ')';
145
146                $msgs[] = $curr_msg;
147                $tree[] = $curr_tree;
148            }
149        }
150
151        /* Flag messages as seen. */
152        $injector->getInstance('IMP_Message')->flag(array(
153            'add' => array(Horde_Imap_Client::FLAG_SEEN)
154        ), $imp_indices);
155
156        $view = new Horde_View(array(
157            'templatePath' => IMP_TEMPLATES . '/thread'
158        ));
159
160        if ($mode == 'thread') {
161            $view->subject = $subject;
162            $view->thread = true;
163
164            switch ($registry->getView()) {
165            case $registry::VIEW_BASIC:
166                $uid_list = $imp_indices[strval($this->indices->mailbox)];
167                $delete_link = $this->indices->mailbox->url('mailbox')->add(array(
168                    'actionID' => 'delete_messages',
169                    'indices' => strval($imp_indices),
170                    'token' => $session->getToken(),
171                    'start' => $imp_mailbox->getArrayIndex(end($uid_list))
172                ));
173                $view->delete = Horde::link($delete_link, _("Delete Thread"), null, null, null, null, null, array('id' => 'threaddelete'));
174                $page_output->addInlineScript(array(
175                    '$("threaddelete").observe("click", function(e) { if (!window.confirm(' . json_encode(_("Are you sure you want to delete all messages in this thread?")) . ')) { e.stop(); } })'
176                ), true);
177                break;
178            }
179        } else {
180            $view->subject = sprintf(_("%d Messages"), count($msgs));
181        }
182        $view->messages = $msgs;
183        $view->tree = $tree;
184
185        $page_output->addScriptFile('stripe.js', 'horde');
186        $page_output->addScriptFile('toggle_quotes.js', 'horde');
187        $page_output->noDnsPrefetch();
188
189        $this->output = $view->render('thread');
190
191        switch ($registry->getView()) {
192        case $registry::VIEW_DYNAMIC:
193            $page_output->topbar = $page_output->sidebar = false;
194            $this->header_params = array(
195                'html_id' => 'htmlAllowScroll'
196            );
197            break;
198        }
199
200        $this->title = ($mode == 'thread')
201            ? _("Thread View")
202            : _("Multiple Message View");
203    }
204
205    /**
206     */
207    public function status()
208    {
209        global $registry;
210
211        return ($registry->getView() == $registry::VIEW_DYNAMIC)
212            ? ''
213            : parent::status();
214    }
215
216    /**
217     */
218    static public function url(array $opts = array())
219    {
220        return Horde::url('basic.php')
221            ->add('page', 'thread')
222            ->unique()
223            ->setRaw(!empty($opts['full']));
224    }
225
226}
227