1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17: 18: 19: 20: 21: 22:
23: class IMP_Contents_View
24: {
25: const VIEW_TOKEN_PARAM = 'view_token';
26:
27: 28: 29:
30: protected $_contents;
31:
32: 33: 34:
35: public function __construct(IMP_Indices $indices)
36: {
37: try {
38: $this->_contents = $GLOBALS['injector']->getInstance('IMP_Factory_Contents')->create($indices);
39: } catch (Exception $e) {
40: exit;
41: }
42: }
43:
44: 45:
46: public function downloadAll()
47: {
48: global $page_output, $session;
49:
50: $headers = $this->_contents->getHeader();
51: $zipfile = trim(preg_replace('/[^\pL\pN-+_. ]/u', '_', $headers->getValue('subject')), ' _');
52: if (empty($zipfile)) {
53: $zipfile = _("attachments.zip");
54: } else {
55: $zipfile .= '.zip';
56: }
57:
58: $page_output->disableCompression();
59: $session->close();
60:
61: $tosave = array();
62: foreach ($this->_contents->downloadAllList() as $val) {
63: $mime = $this->_getRawDownloadPart($val);
64: if (!($name = $mime->getName(true))) {
65: $name = sprintf(_("part %s"), $val);
66: }
67: $tosave[] = array(
68: 'data' => $mime->getContents(array('stream' => true)),
69: 'name' => $name
70: );
71: }
72:
73: if (empty($tosave)) {
74: return array();
75: }
76:
77: return array(
78: 'data' => Horde_Compress::factory('Zip')->compress($tosave, array(
79: 'stream' => true
80: )),
81: 'name' => $zipfile,
82: 'type' => 'application/zip'
83: );
84: }
85:
86: 87:
88: public function downloadAttach($id, $zip = false)
89: {
90: global $page_output, $session;
91:
92: $session->close();
93:
94: $mime = $this->_getRawDownloadPart($id);
95: $name = $this->_contents->getPartName($mime);
96:
97:
98: if ($zip) {
99: $data = Horde_Compress::factory('Zip')->compress(array(
100: array(
101: 'data' => $mime->getContents(),
102: 'name' => $name
103: )
104: ), array(
105: 'stream' => true
106: ));
107: $name .= '.zip';
108: $type = 'application/zip';
109:
110: $page_output->disableCompression();
111: } else {
112: $data = $mime->getContents(array('stream' => true));
113: $type = $mime->getType(true);
114: }
115:
116: return array(
117: 'data' => $data,
118: 'name' => $name,
119: 'type' => $type
120: );
121: }
122:
123: 124:
125: public function downloadRender($id, $mode, $ctype = null)
126: {
127: global $session;
128:
129: $session->close();
130:
131: $render = $this->_contents->renderMIMEPart(
132: $id,
133: $mode,
134: array(
135: 'type' => $ctype
136: )
137: );
138: return reset($render);
139: }
140:
141: 142: 143:
144: public function viewAttach($id, $mode, $autodetect = false, $ctype = null)
145: {
146: global $session;
147:
148: $session->close();
149:
150: $render = $this->_contents->renderMIMEPart(
151: $id,
152: $mode,
153: array(
154: 'autodetect' => $autodetect,
155: 'type' => $ctype
156: )
157: );
158:
159: if (!empty($render)) {
160: return reset($render);
161: } elseif ($autodetect) {
162: $e = new IMP_Exception(_("Could not auto-determine data type."));
163: $e->logged = true;
164: throw $e;
165: }
166:
167: return array();
168: }
169:
170: 171:
172: public function viewSource()
173: {
174: global $session;
175:
176: $session->close();
177:
178: $charset = $this->_contents->getMIMEMessage()->getCharset();
179:
180: return array(
181: 'data' => $this->_contents->fullMessageText(array(
182: 'stream' => true
183: )),
184: 'name' => _("Message Source"),
185: 'type' => 'text/plain; charset=' . (is_null($charset) ? 'UTF-8' : $charset)
186: );
187: }
188:
189: 190:
191: public function saveMessage()
192: {
193: global $session;
194:
195: $session->close();
196:
197: $name = ($subject = $this->_contents->getHeader()->getValue('subject'))
198: ? trim(preg_replace('/[^\pL\pN-+_. ]/u', '_', $subject), ' _')
199: : 'saved_message';
200:
201: return array(
202: 'data' => $this->_contents->fullMessageText(array(
203: 'stream' => true
204: )),
205: 'name' => $name . '.eml',
206: 'type' => 'message/rfc822'
207: );
208: }
209:
210: 211:
212: public function printAttach($id)
213: {
214: global $injector, $page_output, $prefs, $registry;
215:
216: if (is_null($id) ||
217: !($render = $this->_contents->renderMIMEPart($id, IMP_Contents::RENDER_FULL))) {
218: return array();
219: }
220:
221: $part = reset($render);
222:
223:
224: if ((stripos($part['type'], 'text/html')) !== 0 ||
225: !strlen($part['data'])) {
226: return $part;
227: }
228:
229: $imp_ui_mbox = new IMP_Mailbox_Ui();
230: $basic_headers = $injector->getInstance('IMP_Message_Ui')->basicHeaders();
231: unset($basic_headers['bcc'], $basic_headers['reply-to']);
232: $headerob = $this->_contents->getHeader();
233:
234: $headers = array();
235: foreach ($basic_headers as $key => $val) {
236: if ($hdr_val = $headerob->getValue($key)) {
237:
238: if ($key == 'date') {
239: $date_ob = new IMP_Message_Date($hdr_val);
240: $hdr_val = $date_ob->format($date_ob::DATE_FORCE);
241: }
242:
243: $headers[] = array(
244: 'header' => $val,
245: 'value' => $hdr_val
246: );
247: }
248: }
249:
250: if ($prefs->getValue('add_printedby')) {
251: $user_identity = $injector->getInstance('IMP_Identity');
252: $headers[] = array(
253: 'header' => _("Printed By"),
254: 'value' => $user_identity->getFullname() ?: $registry->getAuth()
255: );
256: }
257:
258: $view = new Horde_View(array(
259: 'templatePath' => IMP_TEMPLATES . '/print'
260: ));
261: $view->addHelper('Text');
262:
263: $view->headers = $headers;
264:
265: $ctype = new Horde_Mime_ContentParam($part['type']);
266:
267: $header_dom = new Horde_Domhtml(
268: Horde_String::convertCharset($view->render('headers'), 'UTF-8', $ctype->params['charset']),
269: $ctype->params['charset']
270: );
271: $elt = $header_dom->dom->getElementById('headerblock');
272: $elt->removeAttribute('id');
273:
274: if ($elt->hasAttribute('class')) {
275: $selectors = array('body');
276: foreach (explode(' ', $elt->getAttribute('class')) as $val) {
277: if (strlen($val = trim($val))) {
278: $selectors[] = '.' . $val;
279: }
280: }
281:
282:
283: $cache_list = array();
284: $cache_ob = $injector->getInstance('Horde_Cache');
285:
286: $css_list = $page_output->css->getStylesheets();
287: foreach ($css_list as $val) {
288: $cache_list[] = $val['fs'];
289: $cache_list[] = filemtime($val['fs']);
290: }
291: $cache_id = 'imp_printcss_' . hash(
292: (PHP_MINOR_VERSION >= 4) ? 'fnv132' : 'sha1',
293: implode('|', $cache_list)
294: );
295:
296: if (($style = $cache_ob->get($cache_id, 0)) === false) {
297: try {
298: $css_parser = new Horde_Css_Parser(
299: $page_output->css->loadCssFiles(
300: $page_output->css->getStylesheets()
301: )
302: );
303:
304: $style = '';
305:
306: foreach ($css_parser->doc->getContents() as $val) {
307: if (($val instanceof Sabberworm\CSS\RuleSet\DeclarationBlock) &&
308: array_intersect($selectors, array_map('strval', $val->getSelectors()))) {
309: $style .= implode('', array_map('strval', $val->getRules()));
310: }
311: }
312:
313: $cache_ob->set($cache_id, $style, 86400);
314: } catch (Exception $e) {
315:
316: }
317: }
318:
319: if (strlen($style)) {
320: $elt->setAttribute('style', ($elt->hasAttribute('style') ? rtrim($elt->getAttribute('style'), ' ;') . ';' : '') . $style);
321: }
322: }
323:
324: $elt->removeAttribute('class');
325:
326:
327: $newdiv = new DOMDocument();
328: $div = $newdiv->createElement('div');
329: $div->appendChild($newdiv->importNode($elt, true));
330:
331: $pstring = Horde_Mime::decodeParam('content-type', $part['type']);
332:
333: $doc = new Horde_Domhtml($part['data'], $pstring['params']['charset']);
334:
335: $bodyelt = $doc->dom->getElementsByTagName('body')->item(0);
336: $bodyelt->insertBefore($doc->dom->importNode($div, true), $bodyelt->firstChild);
337:
338:
339: $headelt = $doc->getHead();
340: foreach ($headelt->getElementsByTagName('title') as $node) {
341: $headelt->removeChild($node);
342: }
343: $headelt->appendChild($doc->dom->createElement('title', htmlspecialchars($imp_ui_mbox->getSubject($headerob->getValue('subject')))));
344:
345: return array(
346: 'data' => $doc->returnHtml(),
347: 'name' => $part['name'],
348: 'type' => $part['type']
349: );
350: }
351:
352: 353: 354: 355: 356: 357: 358:
359: public function checkToken(Horde_Variables $vars)
360: {
361: $GLOBALS['session']->checkToken($vars->get(self::VIEW_TOKEN_PARAM));
362: }
363:
364:
365:
366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377:
378: public static function downloadUrl($filename, array $params = array())
379: {
380: global $registry;
381:
382: return $registry->downloadUrl($filename, self::addToken($params));
383: }
384:
385: 386: 387: 388: 389: 390: 391:
392: public static function addToken(array $params = array())
393: {
394: global $session;
395:
396: $params[self::VIEW_TOKEN_PARAM] = $session->getToken();
397:
398: return $params;
399: }
400:
401:
402:
403: 404: 405: 406: 407: 408: 409:
410: protected function _getRawDownloadPart($id)
411: {
412: $mime = $this->_contents->getMIMEPart($id);
413:
414: if ($this->_contents->canDisplay($id, IMP_Contents::RENDER_RAW)) {
415: $render = $this->_contents->renderMIMEPart($id, IMP_Contents::RENDER_RAW);
416: $part = reset($render);
417: $mime->setContents($part['data'], array(
418: 'encoding' => 'binary'
419: ));
420: }
421:
422: return $mime;
423: }
424:
425: }
426: