예제 #1
0
 public function testIsChild()
 {
     $this->assertTrue(Horde_Mime::isChild('1', '1.0'));
     $this->assertTrue(Horde_Mime::isChild('1', '1.1'));
     $this->assertTrue(Horde_Mime::isChild('1', '1.1.0'));
     $this->assertFalse(Horde_Mime::isChild('1', '1'));
     $this->assertFalse(Horde_Mime::isChild('1', '2.1'));
     $this->assertFalse(Horde_Mime::isChild('1', '10.0'));
 }
예제 #2
0
파일: Contents.php 프로젝트: DSNS-LAB/Dmail
 /**
  * Generate inline message display.
  *
  * @param array $options  Options:
  *   - display_mask: (integer) The mask of display view type to render
  *                   inline (DEFAULT: RENDER_INLINE_AUTO).
  *   - mask: (integer) The mask needed for a getSummary() call.
  *   - no_inline_all: (boolean) If true, only display first inline part.
  *                    Subsequent inline parts will be treated as
  *                    attachments.
  *   - part_info_display: (array) The list of summary fields to display.
  *   - show_parts: (string) The value of the 'parts_display' pref.
  *
  * @return array  An array with the following keys:
  *   - atc_parts: (array) The list of attachment MIME IDs.
  *   - display_ids: (array) The list of display MIME IDs.
  *   - js_onload: (array) A list of javascript code to run onload.
  *   - msgtext: (string) The rendered HTML code.
  *   - one_part: (boolean) If true, the message only consists of one part.
  */
 public function getInlineOutput(array $options = array())
 {
     global $prefs, $registry;
     $atc_parts = $display_ids = $msgtext = $js_onload = $wrap_ids = array();
     $parts_list = $this->getContentTypeMap();
     $text_out = '';
     $view = $registry->getView();
     $contents_mask = isset($options['mask']) ? $options['mask'] : 0;
     $display_mask = isset($options['display_mask']) ? $options['display_mask'] : self::RENDER_INLINE_AUTO;
     $no_inline_all = !empty($options['no_inline_all']);
     $part_info_display = isset($options['part_info_display']) ? $options['part_info_display'] : array();
     $show_parts = isset($options['show_parts']) ? $options['show_parts'] : $prefs->getValue('parts_display');
     foreach ($parts_list as $mime_id => $mime_type) {
         if (isset($display_ids[$mime_id]) || isset($atc_parts[$mime_id])) {
             continue;
         }
         if (!($render_mode = $this->canDisplay($mime_id, $display_mask))) {
             if ($this->isAttachment($mime_type)) {
                 if ($show_parts == 'atc') {
                     $atc_parts[$mime_id] = 1;
                 }
                 if ($contents_mask) {
                     $msgtext[$mime_id] = array('text' => $this->_formatSummary($mime_id, $contents_mask, $part_info_display, true));
                 }
             }
             continue;
         }
         $render_part = $this->renderMIMEPart($mime_id, $render_mode);
         if ($show_parts == 'atc' && $this->isAttachment($mime_type) && (empty($render_part) || !($render_mode & self::RENDER_INLINE))) {
             $atc_parts[$mime_id] = 1;
         }
         if (empty($render_part)) {
             if ($contents_mask && $this->isAttachment($mime_type)) {
                 $msgtext[$mime_id] = array('text' => $this->_formatSummary($mime_id, $contents_mask, $part_info_display, true));
             }
             continue;
         }
         reset($render_part);
         while (list($id, $info) = each($render_part)) {
             $display_ids[$id] = 1;
             if (empty($info)) {
                 continue;
             }
             if ($no_inline_all === 1) {
                 $atc_parts[$id] = 1;
                 continue;
             }
             $part_text = $contents_mask && empty($info['nosummary']) ? $this->_formatSummary($id, $contents_mask, $part_info_display, !empty($info['attach'])) : '';
             if (empty($info['attach'])) {
                 if (isset($info['status'])) {
                     if (!is_array($info['status'])) {
                         $info['status'] = array($info['status']);
                     }
                     foreach ($info['status'] as $val) {
                         if (in_array($view, $val->views)) {
                             $part_text .= strval($val);
                         }
                     }
                 }
                 $part_text .= '<div class="mimePartData">' . $info['data'] . '</div>';
             } elseif ($show_parts == 'atc') {
                 $atc_parts[$id] = 1;
             }
             $msgtext[$id] = array('text' => $part_text, 'wrap' => empty($info['wrap']) ? null : $info['wrap']);
             if (isset($info['js'])) {
                 $js_onload = array_merge($js_onload, $info['js']);
             }
             if ($no_inline_all) {
                 $no_inline_all = 1;
             }
         }
     }
     if (!empty($msgtext)) {
         uksort($msgtext, 'strnatcmp');
     }
     reset($msgtext);
     while (list($id, $part) = each($msgtext)) {
         while (!empty($wrap_ids) && !Horde_Mime::isChild(end($wrap_ids), $id)) {
             array_pop($wrap_ids);
             $text_out .= '</div>';
         }
         if (!empty($part['wrap'])) {
             $text_out .= '<div class="' . $part['wrap'] . '">';
             $wrap_ids[] = $id;
         }
         $text_out .= '<div class="mimePartBase">' . $part['text'] . '</div>';
     }
     $text_out .= str_repeat('</div>', count($wrap_ids));
     if (!strlen($text_out)) {
         $text_out = strval(new IMP_Mime_Status(_("There are no parts that can be shown inline.")));
     }
     $atc_parts = $show_parts == 'all' ? array_keys($parts_list) : array_keys($atc_parts);
     return array('atc_parts' => $atc_parts, 'display_ids' => array_keys($display_ids), 'js_onload' => $js_onload, 'msgtext' => $text_out, 'one_part' => count($parts_list) == 1);
 }
예제 #3
0
파일: Compose.php 프로젝트: DSNS-LAB/Dmail
 /**
  * Regenerates body text for use in the compose screen from IMAP data.
  *
  * @param IMP_Contents $contents  An IMP_Contents object.
  * @param array $options          Additional options:
  * <ul>
  *  <li>html: (boolean) Return text/html part, if available.</li>
  *  <li>imp_msg: (integer) If non-empty, the message data was created by
  *               IMP. Either:
  *   <ul>
  *    <li>self::COMPOSE</li>
  *    <li>self::FORWARD</li>
  *    <li>self::REPLY</li>
  *   </ul>
  *  </li>
  *  <li>replylimit: (boolean) Enforce length limits?</li>
  *  <li>toflowed: (boolean) Do flowed conversion?</li>
  * </ul>
  *
  * @return mixed  Null if bodypart not found, or array with the following
  *                keys:
  *   - charset: (string) The guessed charset to use.
  *   - flowed: (Horde_Text_Flowed) A flowed object, if the text is flowed.
  *             Otherwise, null.
  *   - id: (string) The MIME ID of the bodypart.
  *   - mode: (string) Either 'text' or 'html'.
  *   - text: (string) The body text.
  */
 protected function _getMessageText($contents, array $options = array())
 {
     global $conf, $injector, $notification, $prefs, $session;
     $body_id = null;
     $mode = 'text';
     $options = array_merge(array('imp_msg' => self::COMPOSE), $options);
     if (!empty($options['html']) && $session->get('imp', 'rteavail') && ($body_id = $contents->findBody('html')) !== null) {
         $mime_message = $contents->getMIMEMessage();
         switch ($mime_message->getPrimaryType()) {
             case 'multipart':
                 if ($body_id != '1' && $mime_message->getSubType() == 'mixed' && !Horde_Mime::isChild('1', $body_id)) {
                     $body_id = null;
                 } else {
                     $mode = 'html';
                 }
                 break;
             default:
                 if (strval($body_id) != '1') {
                     $body_id = null;
                 } else {
                     $mode = 'html';
                 }
                 break;
         }
     }
     if (is_null($body_id)) {
         $body_id = $contents->findBody();
         if (is_null($body_id)) {
             return null;
         }
     }
     $part = $contents->getMIMEPart($body_id);
     $type = $part->getType();
     $part_charset = $part->getCharset();
     $msg = Horde_String::convertCharset($part->getContents(), $part_charset, 'UTF-8');
     /* Enforce reply limits. */
     if (!empty($options['replylimit']) && !empty($conf['compose']['reply_limit'])) {
         $limit = $conf['compose']['reply_limit'];
         if (Horde_String::length($msg) > $limit) {
             $msg = Horde_String::substr($msg, 0, $limit) . "\n" . _("[Truncated Text]");
         }
     }
     if ($mode == 'html') {
         $dom = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($msg, 'Xss', array('charset' => $this->charset, 'return_dom' => true, 'strip_style_attributes' => false));
         /* If we are replying to a related part, and this part refers
          * to local message parts, we need to move those parts into this
          * message (since the original message may disappear during the
          * compose process). */
         if ($related_part = $contents->findMimeType($body_id, 'multipart/related')) {
             $this->_setMetadata('related_contents', $contents);
             $related_ob = new Horde_Mime_Related($related_part);
             $related_ob->cidReplace($dom, array($this, '_getMessageTextCallback'), $part_charset);
             $this->_setMetadata('related_contents', null);
         }
         /* Convert any Data URLs to attachments. */
         $xpath = new DOMXPath($dom->dom);
         foreach ($xpath->query('//*[@src]') as $val) {
             $data_url = new Horde_Url_Data($val->getAttribute('src'));
             if (strlen($data_url->data)) {
                 $data_part = new Horde_Mime_Part();
                 $data_part->setContents($data_url->data);
                 $data_part->setType($data_url->type);
                 try {
                     $atc = $this->addAttachmentFromPart($data_part);
                     $val->setAttribute('src', $atc->viewUrl());
                     $this->addRelatedAttachment($atc, $val, 'src');
                 } catch (IMP_Compose_Exception $e) {
                     $notification->push($e, 'horde.warning');
                 }
             }
         }
         $msg = $dom->returnBody();
     } elseif ($type == 'text/html') {
         $msg = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($msg, 'Html2text');
         $type = 'text/plain';
     }
     /* Always remove leading/trailing whitespace. The data in the
      * message body is not intended to be the exact representation of the
      * original message (use forward as message/rfc822 part for that). */
     $msg = trim($msg);
     if ($type == 'text/plain') {
         if ($prefs->getValue('reply_strip_sig') && ($pos = strrpos($msg, "\n-- ")) !== false) {
             $msg = rtrim(substr($msg, 0, $pos));
         }
         /* Remove PGP armored text. */
         $pgp = $injector->getInstance('Horde_Crypt_Pgp_Parse')->parseToPart($msg);
         if (!is_null($pgp)) {
             $msg = '';
             $pgp->buildMimeIds();
             foreach ($pgp->contentTypeMap() as $key => $val) {
                 if (strpos($val, 'text/') === 0) {
                     $msg .= $pgp[$key]->getContents();
                 }
             }
         }
         if ($part->getContentTypeParameter('format') == 'flowed') {
             $flowed = new Horde_Text_Flowed($msg, 'UTF-8');
             if (Horde_String::lower($part->getContentTypeParameter('delsp')) == 'yes') {
                 $flowed->setDelSp(true);
             }
             $flowed->setMaxLength(0);
             $msg = $flowed->toFixed(false);
         } else {
             /* If the input is *not* in flowed format, make sure there is
              * no padding at the end of lines. */
             $msg = preg_replace("/\\s*\n/U", "\n", $msg);
         }
         if (isset($options['toflowed'])) {
             $flowed = new Horde_Text_Flowed($msg, 'UTF-8');
             $msg = $options['toflowed'] ? $flowed->toFlowed(true) : $flowed->toFlowed(false, array('nowrap' => true));
         }
     }
     if (strcasecmp($part->getCharset(), 'windows-1252') === 0) {
         $part_charset = 'ISO-8859-1';
     }
     return array('charset' => $part_charset, 'flowed' => isset($flowed) ? $flowed : null, 'id' => $body_id, 'mode' => $mode, 'text' => $msg);
 }
예제 #4
0
파일: Related.php 프로젝트: DSNS-LAB/Dmail
 /**
  * Render out the currently set contents.
  *
  * @param boolean $inline  Are we viewing inline?
  *
  * @return array  See self::render().
  */
 protected function _IMPrender($inline)
 {
     $related_id = $this->_mimepart->getMimeId();
     $used = array($related_id);
     if (!($id = $this->_init($inline))) {
         return array();
     }
     $render = $this->getConfigParam('imp_contents')->renderMIMEPart($id, $inline ? IMP_Contents::RENDER_INLINE : IMP_Contents::RENDER_FULL);
     if (!$inline) {
         foreach (array_keys($render) as $key) {
             if (!is_null($render[$key])) {
                 return array($related_id => $render[$key]);
             }
         }
         return null;
     }
     $data_id = null;
     $ret = array_fill_keys(array_keys($this->_mimepart->contentTypeMap()), null);
     foreach (array_keys($render) as $val) {
         $ret[$val] = $render[$val];
         if ($ret[$val]) {
             $data_id = $val;
         }
     }
     if (!is_null($data_id)) {
         $this->_mimepart->setMetadata('viewable_part', $data_id);
         /* We want the inline display to show multipart/related vs. the
          * viewable MIME part.  This is because a multipart/related part
          * is not downloadable and clicking on the MIME part may not
          * produce the desired result in the full display (i.e. HTML parts
          * with related images). */
         if ($data_id !== $related_id) {
             $ret[$related_id] = $ret[$data_id];
             $ret[$data_id] = null;
         }
     }
     /* Fix for broken messages that don't refer to a related CID part
      * within the base part. */
     if ($cids_used = $this->_mimepart->getMetadata('related_cids_used')) {
         $used = array_merge($used, $cids_used);
     }
     foreach (array_diff(array_keys($ret), $used) as $val) {
         if ($val !== $id && !Horde_Mime::isChild($id, $val)) {
             $summary = $this->getConfigParam('imp_contents')->getSummary($val, IMP_Contents::SUMMARY_SIZE | IMP_Contents::SUMMARY_ICON | IMP_Contents::SUMMARY_DESCRIP_LINK | IMP_Contents::SUMMARY_DOWNLOAD);
             $status = new IMP_Mime_Status(array(_("This part contains an attachment that can not be displayed within this part:"), implode('&nbsp;', array($summary['icon'], $summary['description'], $summary['size'], $summary['download']))));
             $status->action(IMP_Mime_Status::WARNING);
             if (isset($ret[$related_id]['status'])) {
                 if (!is_array($ret[$related_id]['status'])) {
                     $ret[$related_id]['status'] = array($ret[$related_id]['status']);
                 }
             } else {
                 $ret[$related_id]['status'] = array();
             }
             $ret[$related_id]['status'][] = $status;
         }
     }
     return $ret;
 }