저자: Chuck Hagenbuch (chuck@horde.org)
저자: Jan Schneider (jan@horde.org)
예제 #1
0
 public function testBug12787()
 {
     $js = "function foo(a) { return/\\//.test(a); }";
     $this->assertEquals('function foo(a){return/\\//.test(a);}', Horde_Text_Filter::filter($js, 'JavascriptMinify'));
     $js2 = 'var a = 0, b = c / 100 | 0;';
     $this->assertNotEquals($js2, Horde_Text_Filter::filter($js2, 'JavascriptMinify'));
 }
예제 #2
0
 public function testBug12253()
 {
     // ISO-8859-2 encoded data.
     $text = base64_decode('a/ZubmVu');
     $filter = Horde_Text_Filter::filter($text, 'text2html', array('charset' => 'iso-8859-2', 'parselevel' => Horde_Text_Filter_Text2html::MICRO_LINKURL));
     $this->assertGreaterThan(0, strlen($filter));
 }
예제 #3
0
 public function testBug12152()
 {
     $text = 'http://imslp.org/wiki/Symphony_No.5,_D.485_(Schubert,_Franz)';
     $old_ini = ini_get('pcre.backtrack_limit');
     ini_set('pcre.backtrack_limit', 1000);
     $this->assertEquals($text, Horde_Text_Filter::filter($text, 'linkurls'));
     ini_set('pcre.backtrack_limit', $old_ini);
 }
예제 #4
0
파일: XssTest.php 프로젝트: horde/horde
 public function testBug9567()
 {
     $text = quoted_printable_decode("pr=E9parer =E0 vendre d’ao=FBt");
     $this->assertEquals($text, Horde_Text_Filter::filter('<html><body>' . $text . '</body></html>', 'xss', array('charset' => 'iso-8859-1')));
     $this->assertEquals($text, Horde_Text_Filter::filter('<html><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></head><body>' . $text . '</body></html>', 'xss', array('charset' => 'iso-8859-1')));
     $text = Horde_String::convertCharset(quoted_printable_decode("pr=E9parer =E0 vendre d&#8217;ao=FBt&nbsp;;"), 'windows-1252', 'UTF-8');
     $expected = "préparer à vendre d’août ;";
     $this->assertEquals($expected, Horde_Text_Filter::filter('<html><body>' . $text . '</body></html>', 'xss', array('charset' => 'utf-8')));
 }
예제 #5
0
파일: TextFilter.php 프로젝트: horde/horde
 /**
  * Applies a set of patterns to a block of text.
  *
  * @param string $text    The text to filter.
  * @param mixed $filters  The list of filters (or a single filter).
  * @param mixed $params   The list of params to use with each filter.
  *
  * @return string  The transformed text.
  */
 public function filter($text, $filters = array(), $params = array())
 {
     if (!is_array($filters)) {
         $filters = array($filters);
         $params = array($params);
     }
     $filter_list = array();
     $params = array_values($params);
     foreach (array_values($filters) as $num => $filter) {
         list($driver, $driv_param) = $this->_getDriver($filter, isset($params[$num]) ? $params[$num] : array());
         $filter_list[$driver] = $driv_param;
     }
     return Horde_Text_Filter::filter($text, array_keys($filter_list), array_values($filter_list));
 }
예제 #6
0
    public function testCombination()
    {
        $html = <<<HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<p class="MsoNormal"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Danke f&uuml;r die rasche Erledigung!</span></p>
<p class="MsoNormal"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal foo"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>W&uuml;nsche ein sch&ouml;nes Weihnachtsfest und f&uuml;r 2015 alles Gute!<o:p>&nbsp;</o:p></span></p>
<p class="foo MsoNormal"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>&nbsp;</span></p>
</body></html>
HTML;
        $expected = <<<HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>Danke f&uuml;r die rasche Erledigung!</span><br>

<div class="foo"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>W&uuml;nsche ein sch&ouml;nes Weihnachtsfest und f&uuml;r 2015 alles Gute!</span></div>
<div class="foo"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>&nbsp;</span></div>
</body></html>

HTML;
        $filtered = Horde_Text_Filter::filter($html, 'Msoffice');
        $this->assertEquals($expected, $filtered);
    }
예제 #7
0
파일: Driver.php 프로젝트: DSNS-LAB/Dmail
 /**
  * Create an AS memo from this task
  *
  * @param array $memo  A memo array.
  * @param array $options
  *
  * @return Horde_ActiveSync_Message_Note
  */
 public function toASNote($memo, $options = array())
 {
     $message = new Horde_ActiveSync_Message_Note(array('protocolversion' => $options['protocolversion']));
     $message->subject = $memo['desc'];
     $bp = $options['bodyprefs'];
     $body = new Horde_ActiveSync_Message_AirSyncBaseBody();
     // When the note is encrypted, we won't have the passphrase so the
     // body will be a Mnemo_Exception.
     if ($memo['body'] instanceof Mnemo_Exception) {
         $memo['body'] = $memo['body']->getMessage();
     }
     if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) {
         $body->type = Horde_ActiveSync::BODYPREF_TYPE_HTML;
         $memo['body'] = Horde_Text_Filter::filter($memo['body'], 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
         if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']) && Horde_String::length($memo['body']) > $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']) {
             $body->data = Horde_String::substr($memo['body'], $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']);
             $body->truncated = 1;
         } else {
             $body->data = $memo['body'];
         }
     } else {
         $body->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN;
         if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) && Horde_String::length($memo['body']) > $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) {
             $body->data = Horde_String::substr($memo['body'], 0, $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']);
             $body->truncated = 1;
         } else {
             $body->data = $memo['body'];
         }
     }
     $body->estimateddatasize = Horde_String::length($memo['body']);
     $message->body = $body;
     if (!empty($memo['tags'])) {
         $message->categories = $memo['tags'];
     }
     $history = $GLOBALS['injector']->getInstance('Horde_History');
     $last = $history->getActionTimeStamp('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid'], 'modify');
     if (empty($last)) {
         $last = $history->getActionTimeStamp('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid'], 'add');
     }
     $message->lastmodified = new Horde_Date($last);
     return $message;
 }
예제 #8
0
 /**
  * @dataProvider markupExamples
  */
 public function testSimplemarkup($markup, $output, $html)
 {
     $this->assertEquals($output, Horde_Text_Filter::filter($markup, 'simplemarkup', array('html' => $html)));
 }
예제 #9
0
파일: VTodo.php 프로젝트: raz0rsdge/horde
 protected function _tovTodo()
 {
     $iCal = new Horde_Icalendar();
     $iCal->setAttribute('METHOD', $this->_method);
     $vtodo = Horde_Icalendar::newComponent('vtodo', $iCal);
     $vtodo->setAttribute('UID', $this->_guid);
     // For REQUESTS, we MUST have the ORGANIZER and an ATTENDEE.
     if ($this->_state == self::STATE_ASSIGNERS_COPY || $this->_ownership == self::OWNERSHIP_ASSIGNERS_COPY) {
         // When sending a REQUEST the lastUser to edit it should be the
         // ORGANIZER. I can't find any of the other properties that work
         // consistently.
         $vtodo->setAttribute('ORGANIZER', 'mailto: ' . $this->_lastUser);
         $list = new Horde_Mail_Rfc822_List($this->_owner);
         foreach ($list as $email) {
             $vtodo->setAttribute('ATTENDEE', $email, array('ROLE' => 'REQ-PARTICIPANT'));
         }
     }
     if ($this->_due) {
         $vtodo->setAttribute('DUE', $this->_due);
     }
     if ($this->_start) {
         $vtodo->setAttribute('DTSTART', $this->_start);
     }
     if ($this->_completed) {
         $vtodo->setAttribute('COMPLETED', $this->_completed);
     }
     if (isset($this->_percentComplete)) {
         $vtodo->setAttribute('PERCENT-COMPLETE', $this->_percentComplete);
     }
     // Summary is stored in the message data.
     $msg = $this->_options['parent']->getMsgInfo();
     if ($msg->subject) {
         $vtodo->setAttribute('SUMMARY', $msg->subject);
     }
     // Figure out the body.
     if ($this->_bodyPlain) {
         $vtodo->setAttribute('DESCRIPTION', $this->_bodyPlain);
     } elseif ($this->_bodyHtml) {
         $vtodo->setAttribute('DESCRIPTION', Horde_Text_Filter::filter($this->_bodyHtml, 'html2text'));
     }
     $iCal->addComponent($vtodo);
     return array('type' => 'text', 'subtype' => 'calendar', 'name' => $msg->subject ? $msg->subject . '.vtodo' : 'Untitled.vtodo', 'stream' => $iCal->exportvCalendar());
 }
예제 #10
0
파일: Mail.php 프로젝트: raz0rsdge/horde
 public static function html2text($msg)
 {
     return Horde_Text_Filter::filter($msg, 'Html2text', array('nestingLimit' => 1000));
 }
예제 #11
0
파일: Mail.php 프로젝트: jubinpatel/horde
 /**
  * Parse a MIME message and create a new ticket.
  *
  * @param string $text       This is the full text of the MIME message.
  * @param array $info        An array of information for the new ticket.
  *                           This should include:
  *                           - 'queue'    => queue id
  *                           - 'type'     => type id
  *                           - 'state'    => state id
  *                           - 'priority' => priority id
  *                           - 'ticket'   => ticket id (prevents creation
  *                                           of new tickets)
  * @param string $auth_user  This will be the Horde user that creates the
  *                           ticket. If null, we will try to deduce from
  *                           the message's From: header. We do NOT default
  *                           to $GLOBALS['registry']->getAuth().
  *
  * @return Whups_Ticket  Ticket.
  */
 public static function processMail($text, array $info, $auth_user = null)
 {
     global $conf;
     $message = Horde_Mime_Part::parseMessage($text);
     if (preg_match("/^(.*?)\r?\n\r?\n/s", $text, $matches)) {
         $hdrText = $matches[1];
     } else {
         $hdrText = $text;
     }
     $headers = Horde_Mime_Headers::parseHeaders($hdrText);
     // If this message was generated by Whups, don't process it.
     if ($headers->getValue('X-Whups-Generated')) {
         return true;
     }
     // Try to avoid bounces, auto-replies, and mailing list responses.
     $from = $headers->getValue('from');
     if (strpos($headers->getValue('Content-Type'), 'multipart/report') !== false || stripos($from, 'mailer-daemon@') !== false || stripos($from, 'postmaster@') !== false || !is_null($headers->getValue('X-Failed-Recipients')) || !is_null($headers->getValue('X-Autoreply-Domain')) || $headers->getValue('Auto-Submitted') == 'auto-replied' || $headers->getValue('Precedence') == 'auto_reply' || $headers->getValue('X-Precedence') == 'auto_reply' || $headers->getValue('X-Auto-Response-Suppress') == 'All' || $headers->getValue('X-List-Administrivia') == 'Yes') {
         return true;
     }
     // Use the message subject as the ticket summary.
     $info['summary'] = trim($headers->getValue('subject'));
     if (empty($info['summary'])) {
         $info['summary'] = _("[No Subject]");
     }
     // Format the message into a comment.
     $comment = _("Received message:") . "\n\n";
     if (!empty($GLOBALS['conf']['mail']['include_headers'])) {
         foreach ($headers->toArray(array('nowrap' => true)) as $name => $vals) {
             if (!in_array(strtolower($name), array('subject', 'from', 'to', 'cc', 'date'))) {
                 if (is_array($vals)) {
                     foreach ($vals as $val) {
                         $comment .= $name . ': ' . $val . "\n";
                     }
                 } else {
                     $comment .= $name . ': ' . $vals . "\n";
                 }
             }
         }
         $comment .= "\n";
     }
     // Look for the body part.
     $body_id = $message->findBody();
     if ($body_id) {
         $part = $message->getPart($body_id);
         $content = Horde_String::convertCharset($part->getContents(), $part->getCharset(), 'UTF-8');
         switch ($part->getType()) {
             case 'text/plain':
                 $comment .= $content;
                 break;
             case 'text/html':
                 $comment .= Horde_Text_Filter::filter($content, array('Html2text'), array(array('width' => 0)));
                 break;
             default:
                 $comment .= _("[ Could not render body of message. ]");
                 break;
         }
     } else {
         $comment .= _("[ Could not render body of message. ]");
     }
     $info['comment'] = $comment . "\n";
     // Try to determine the Horde user for creating the ticket.
     if (empty($auth_user)) {
         $tmp = new Horde_Mail_Rfc822_Address($from);
         $auth_user = self::_findAuthUser($tmp->bare_address);
     }
     $author = $auth_user;
     if (empty($auth_user) && !empty($info['default_auth'])) {
         $auth_user = $info['default_auth'];
         if (!empty($from)) {
             $info['user_email'] = $from;
         }
     }
     if (empty($auth_user) && !empty($conf['mail']['username'])) {
         $auth_user = $conf['mail']['username'];
         if (!empty($from)) {
             $info['user_email'] = $from;
         }
     }
     // Authenticate as the correct Horde user.
     if (!empty($auth_user) && $auth_user != $GLOBALS['registry']->getAuth()) {
         $GLOBALS['registry']->setAuth($auth_user, array());
     }
     // Attach message.
     $attachments = array();
     if (!empty($GLOBALS['conf']['mail']['attach_message'])) {
         $tmp_name = Horde::getTempFile('whups');
         $fp = @fopen($tmp_name, 'wb');
         if (!$fp) {
             throw new Whups_Exception(sprintf('Cannot open file %s for writing.', $tmp_name));
         }
         fwrite($fp, $text);
         fclose($fp);
         $attachments[] = array('name' => _("Original Message") . '.eml', 'tmp_name' => $tmp_name);
     }
     // Extract attachments.
     $dl_list = array_slice(array_keys($message->contentTypeMap()), 1);
     foreach ($dl_list as $key) {
         $part = $message->getPart($key);
         if ($key == $body_id && $part->getType() == 'text/plain' || $part->getType() == 'multipart/alternative' || $part->getType() == 'multipart/mixed') {
             continue;
         }
         $tmp_name = Horde::getTempFile('whups');
         $fp = @fopen($tmp_name, 'wb');
         if (!$fp) {
             throw new Whups_Exception(sprintf('Cannot open file %s for writing.', $tmp_name));
         }
         fwrite($fp, $part->getContents());
         fclose($fp);
         $part_name = $part->getName(true);
         if (!$part_name) {
             $ptype = $part->getPrimaryType();
             switch ($ptype) {
                 case 'multipart':
                 case 'application':
                     $part_name = sprintf(_("%s part"), ucfirst($part->getSubType()));
                     break;
                 default:
                     $part_name = sprintf(_("%s part"), ucfirst($ptype));
                     break;
             }
             if ($ext = Horde_Mime_Magic::mimeToExt($part->getType())) {
                 $part_name .= '.' . $ext;
             }
         }
         $attachments[] = array('name' => $part_name, 'tmp_name' => $tmp_name);
     }
     // See if we can match this message to an existing ticket.
     if ($ticket = self::_findTicket($info)) {
         $ticket->change('comment', $info['comment']);
         $ticket->change('comment-email', $from);
         if ($attachments) {
             $ticket->change('attachments', $attachments);
         }
         $ticket->commit($author);
     } elseif (!empty($info['ticket'])) {
         // Didn't match an existing ticket though a ticket number had been
         // specified.
         throw new Whups_Exception(sprintf(_("Could not find ticket \"%s\"."), $info['ticket']));
     } else {
         if (!empty($info['guess-queue'])) {
             // Try to guess the queue name for the new ticket from the
             // message subject.
             $queues = $GLOBALS['whups_driver']->getQueues();
             foreach ($queues as $queueId => $queueName) {
                 if (preg_match('/\\b' . preg_quote($queueName, '/') . '\\b/i', $info['summary'])) {
                     $info['queue'] = $queueId;
                     break;
                 }
             }
         }
         $info['attachments'] = $attachments;
         // Create a new ticket.
         $ticket = Whups_Ticket::newTicket($info, $author);
     }
 }
예제 #12
0
 public function testHtml2TextSpacing()
 {
     $html = '<span><span>Normal</span> <strong>Strong</strong> Normal</span> <em>Italics</em> Normal <u>Underline</u> Normal <strike>Strike</strike> Normal';
     $filter = Horde_Text_Filter::filter($html, 'Html2text');
     $this->assertEquals('Normal STRONG Normal /Italics/ Normal _Underline_ Normal Strike Normal', $filter);
 }
예제 #13
0
 /**
  * Returns the main text body of the message suitable for sending over
  * EAS response.
  *
  * @param array $options  An options array containgin:
  *  - bodyprefs: (array)  Bodypref settings
  *               DEFAULT: none (No bodyprefs used).
  *  - mimesupport: (integer)  Indicates if MIME is supported or not.
  *                  Possible values: 0 - Not supported 1 - Only S/MIME or
  *                  2 - All MIME.
  *                  DEFAULT: 0 (No MIME support)
  *  - protocolversion: (float)  The EAS protocol we are supporting.
  *                     DEFAULT 2.5
  *
  * @return array  An array of one or both of 'plain' and 'html' content.
  *
  * @throws Horde_ActiveSync_Exception, Horde_Exception_NotFound
  */
 public function getMessageBodyData(array $options = array())
 {
     $version = empty($options['protocolversion']) ? Horde_ActiveSync::VERSION_TWOFIVE : $options['protocolversion'];
     // Look for the parts we need. We try to detect and fetch only the parts
     // we need, while ensuring we have something to return. So, e.g., if we
     // don't have BODYPREF_TYPE_HTML, we only request plain text, but if we
     // can't find plain text but we have a html body, fetch that anyway.
     $text_id = $this->_message->findBody('plain');
     $html_id = $this->_message->findBody('html');
     // Deduce which part(s) we need to request.
     $want_html_text = $version >= Horde_ActiveSync::VERSION_TWELVE && (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_MIME]));
     $want_plain_text = $version == Horde_ActiveSync::VERSION_TWOFIVE || empty($options['bodyprefs']) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_RTF]) || !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_MIME]) || $want_html_text && empty($html_id);
     $want_html_as_plain = false;
     if (!empty($text_id) && $want_plain_text) {
         $text_body_part = $this->_message->getPart($text_id);
         $charset = $text_body_part->getCharset();
     } elseif ($want_plain_text && !empty($html_id) && empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_MIME])) {
         $want_html_text = true;
         $want_html_as_plain = true;
     }
     if (!empty($html_id) && $want_html_text) {
         $html_body_part = $this->_message->getPart($html_id);
         $html_charset = $html_body_part->getCharset();
     }
     // Sanity check the truncation stuff
     if (empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]) && !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]) && $want_plain_text && $want_html_text) {
         // We only have HTML truncation data, requested HTML body but only
         // have plaintext.
         $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN] = $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML];
     }
     $query = new Horde_Imap_Client_Fetch_Query();
     $query_opts = array('decode' => true, 'peek' => true);
     // Get body information
     if ($version >= Horde_ActiveSync::VERSION_TWELVE) {
         if (!empty($html_id)) {
             $query->bodyPartSize($html_id);
             $query->bodyPart($html_id, $query_opts);
         }
         if (!empty($text_id)) {
             $query->bodyPart($text_id, $query_opts);
             $query->bodyPartSize($text_id);
         }
     } else {
         // EAS 2.5 Plaintext body
         $query->bodyPart($text_id, $query_opts);
         $query->bodyPartSize($text_id);
     }
     try {
         $fetch_ret = $this->_imap->fetch($this->_mbox, $query, array('ids' => new Horde_Imap_Client_Ids(array($this->_uid))));
     } catch (Horde_Imap_Client_Exception $e) {
         throw new Horde_ActiveSync_Exception($e);
     }
     if (!($data = $fetch_ret->first())) {
         throw new Horde_Exception_NotFound(sprintf('Could not load message %s from server.', $this->_uid));
     }
     $return = array();
     if (!empty($text_id) && $want_plain_text) {
         $text = $data->getBodyPart($text_id);
         if (!$data->getBodyPartDecode($text_id)) {
             $text_body_part->setContents($text);
             $text = $text_body_part->getContents();
         }
         $text_size = !is_null($data->getBodyPartSize($text_id)) ? $data->getBodyPartSize($text_id) : Horde_String::length($text);
         if (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) {
             // EAS >= 12.0 truncation
             $text = Horde_String::substr($text, 0, $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'], $charset);
         }
         $truncated = $text_size > Horde_String::length($text);
         if ($version >= Horde_ActiveSync::VERSION_TWELVE && $truncated && !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['allornone'])) {
             $text = '';
         }
         $return['plain'] = array('charset' => $charset, 'body' => $text, 'truncated' => $truncated, 'size' => $text_size);
     }
     if (!empty($html_id) && $want_html_text) {
         $html = $data->getBodyPart($html_id);
         if (!$data->getBodyPartDecode($html_id)) {
             $html_body_part->setContents($html);
             $html = $html_body_part->getContents();
         }
         // Size of the original HTML part.
         $html_size = !is_null($data->getBodyPartSize($html_id)) ? $data->getBodyPartSize($html_id) : Horde_String::length($html);
         if (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize'])) {
             $html = Horde_String::substr($html, 0, $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize'], $html_charset);
         } elseif ($want_html_as_plain) {
             $html = Horde_Text_Filter::filter($html, 'Html2text', array('charset' => $html_charset));
             // Get the new size, since it probably changed.
             $html_size = Horde_String::length($html);
             if (!empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) {
                 // EAS >= 12.0 truncation
                 $html = Horde_String::substr($html, 0, $options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'], $html_charset);
             }
         }
         // Was the part truncated?
         $truncated = $html_size > Horde_String::length($html);
         if ($want_html_as_plain) {
             $return['plain'] = array('charset' => $html_charset, 'body' => $html, 'truncated' => $truncated, 'size' => $html_size);
         }
         if ($version >= Horde_ActiveSync::VERSION_TWELVE && !($truncated && !empty($options['bodyprefs'][Horde_ActiveSync::BODYPREF_TYPE_HTML]['allornone']))) {
             $return['html'] = array('charset' => $html_charset, 'body' => $html, 'estimated_size' => $html_size, 'truncated' => $truncated);
         }
     }
     return $return;
 }
예제 #14
0
파일: Mail.php 프로젝트: jubinpatel/horde
 public static function html2text($msg)
 {
     Horde_Text_Filter::filter($msg, 'Html2text');
 }
예제 #15
0
파일: Driver.php 프로젝트: horde/horde
 /**
  * Handle meeting responses.
  *
  * @param array $response  The response data. Contains:
  *   - requestid: The identifier of the meeting request. Used by the server
  *                to fetch the original meeting request details.
  *   - response:  The user's response to the request. One of the response
  *                code constants.
  *   - folderid:  The collection id that contains the meeting request.
  *   -
  *
  * @return string  The UID of any created calendar entries, otherwise false.
  * @throws Horde_ActiveSync_Exception, Horde_Exception_NotFound
  */
 public function meetingResponse(array $response)
 {
     global $injector;
     if (empty($response['folderid']) || empty($response['requestid']) || empty($response['response'])) {
         throw new Horde_ActiveSync_Exception('Invalid meeting response.');
     }
     // First thing we need is to obtain the meeting request.
     $imap_message = $this->_imap->getImapMessage($response['folderid'], $response['requestid']);
     if (empty($imap_message)) {
         throw new Horde_Exception_NotFound();
     }
     $imap_message = $imap_message[$response['requestid']];
     // Find the request
     if (!($part = $imap_message->hasiCalendar())) {
         $this->_logger->err('Unable to find the meeting request.');
         throw new Horde_Exception_NotFound();
     }
     // Parse the vCal
     $vCal = new Horde_Icalendar();
     $data = $part->getContents();
     if (!$vCal->parsevCalendar($data, 'VCALENDAR', $part->getCharset())) {
         throw new Horde_ActiveSync_Exception('Unknown error parsing vCal data.');
     }
     if (!($vEvent = $vCal->findComponent('vEvent'))) {
         throw new Horde_ActiveSync_Exception('Unknown error locating vEvent.');
     }
     // Update the vCal so the response will be reflected when imported.
     $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($this->_user);
     $cn = $ident->getValue('fullname');
     $email = $ident->getValue('from_addr');
     switch ($response['response']) {
         case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_ACCEPTED:
             $itip_response = 'ACCEPTED';
             break;
         case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_TENTATIVE:
             $itip_response = 'TENTATIVE';
             break;
         case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_DECLINED:
             $itip_response = 'DECLINED';
     }
     $vEvent->updateAttendee($email, $itip_response);
     // Create an event from the vEvent.
     // Note we don't use self::changeMessage since we don't want to treat
     // this as an incoming message addition from the PIM. Otherwise, the
     // message may not get synched back to the PIM.
     try {
         $uid = $this->_connector->calendar_import_vevent($vEvent);
     } catch (Horde_Exception $e) {
         $this->_logger->err($e->getMessage());
         throw new Horde_ActiveSync_Exception($e);
     }
     if (!empty($response['sendresponse'])) {
         if ($response['sendresponse'] !== true) {
             $comment = $response['sendresponse']->data;
             if ($response['sendresponse']->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
                 $comment = Horde_Text_Filter::filter($comment, 'Html2text', array('charset' => 'UTF-8', 'nestingLimit' => 1000));
             }
         } else {
             $comment = '';
         }
         // Start building the iTip response email.
         try {
             $organizer = parse_url($vEvent->getAttribute('ORGANIZER'));
             $organizer = $organizer['path'];
         } catch (Horde_Icalendar_Exception $e) {
             $this->_logger->err('Unable to find organizer.');
             throw new Horde_ActiveSync_Exception($e);
         }
         $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($event->creator);
         if (!$ident->getValue('from_addr')) {
             throw new Horde_ActiveSync_Exception(_("You do not have an email address configured in your Personal Information Preferences."));
         }
         $resource = new Horde_Itip_Resource_Identity($ident, $vEvent->getAttribute('ATTENDEE'), (string) $ident->getFromAddress());
         switch ($response['response']) {
             case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_ACCEPTED:
                 $type = new Horde_Itip_Response_Type_Accept($resource, $comment);
                 break;
             case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_DECLINED:
                 $type = new Horde_Itip_Response_Type_Decline($resource, $comment);
                 break;
             case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_TENTATIVE:
                 $type = new Horde_Itip_Response_Type_Tentative($resource, $comment);
                 break;
         }
         try {
             // Send the reply.
             Horde_Itip::factory($vEvent, $resource)->sendMultiPartResponse($type, new Horde_Core_Itip_Response_Options_Horde('UTF-8', array()), $injector->getInstance('Horde_Mail'));
             $this->_logger->info('Reply sent.');
         } catch (Horde_Itip_Exception $e) {
             $this->_logger->err(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error');
         }
     }
     // Delete the original request. EAS Specs require this. Most clients
     // will remove the email from the UI as soon as the response is sent.
     // Failure to remove it from the server will result in an inconsistent
     // sync state.
     try {
         $this->_imap->deleteMessages(array($response['requestid']), $response['folderid']);
     } catch (Horde_ActiveSync_Exception $e) {
         $this->_logger->err($e->getMessage());
     }
     return $uid;
 }
예제 #16
0
 /**
  * Executes any code necessary before applying the filter patterns.
  *
  * @param mixed $text  The text before the filtering. Either a string or
  *                     a Horde_Text_Flowed object (since 1.1.0).
  *
  * @return string  The modified text.
  */
 public function preProcess($text)
 {
     if ($text instanceof Horde_Text_Flowed) {
         $text->setMaxLength(0);
         $lines = $text->toFixedArray();
         $level = 0;
         $out = $txt = '';
         foreach ($lines as $key => $val) {
             $line = ltrim($val['text'], '>');
             if (!isset($lines[$key + 1])) {
                 $out .= $this->preProcess(ltrim($txt) . $line);
                 while (--$level > 0) {
                     $out .= '</blockquote>';
                 }
             } elseif ($val['level'] > $level) {
                 $out .= $this->preProcess(ltrim($txt));
                 do {
                     $out .= $this->_params['flowed'];
                 } while (++$level != $val['level']);
                 $txt = $line;
             } elseif ($val['level'] < $level) {
                 $out .= $this->preProcess(ltrim($txt));
                 do {
                     $out .= '</blockquote>';
                 } while (--$level != $val['level']);
                 $txt = $line;
             } else {
                 $txt .= "\n" . $line;
             }
         }
         return $out;
     }
     if (!strlen($text)) {
         return '';
     }
     /* Abort out on simple cases. */
     if ($this->_params['parselevel'] == self::PASSTHRU) {
         return $text;
     }
     if ($this->_params['parselevel'] == self::NOHTML_NOBREAK) {
         return @htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
     }
     if ($this->_params['parselevel'] < self::NOHTML) {
         $filters = array();
         if ($this->_params['linkurls']) {
             reset($this->_params['linkurls']);
             $this->_params['linkurls'][key($this->_params['linkurls'])]['encode'] = true;
             $filters = $this->_params['linkurls'];
         } else {
             $filters['linkurls'] = array('encode' => true);
         }
         if ($this->_params['parselevel'] < self::MICRO_LINKURL) {
             if ($this->_params['emails']) {
                 reset($this->_params['emails']);
                 $this->_params['emails'][key($this->_params['emails'])]['encode'] = true;
                 $filters += $this->_params['emails'];
             } else {
                 $filters['emails'] = array('encode' => true);
             }
         }
         $text = Horde_Text_Filter::filter($text, array_keys($filters), array_values($filters));
     }
     /* For level MICRO or NOHTML, start with htmlspecialchars(). */
     $text2 = @htmlspecialchars($text, ENT_COMPAT, $this->_params['charset']);
     /* Bad charset input in may result in an empty string. Or the charset
      * may not be supported. Convert to UTF-8 for htmlspecialchars() and
      * then convert back. If we STILL don't have any output, the input
      * charset is probably incorrect. Try the popular Western charsets as
      * a last resort. */
     if (!strlen($text2)) {
         $text2 = Horde_String::convertCharset(@htmlspecialchars(Horde_String::convertCharset($text, $this->_params['charset'], 'UTF-8'), ENT_COMPAT, 'UTF-8'), 'UTF-8', $this->_params['charset']);
         if (!strlen($text2)) {
             foreach (array('windows-1252', 'utf-8') as $val) {
                 $text2 = Horde_String::convertCharset(@htmlspecialchars($text, ENT_COMPAT, $val), $val, $this->_params['charset']);
                 if (strlen($text2)) {
                     break;
                 }
             }
         }
     }
     $text = $text2;
     /* Do in-lining of http://xxx.xxx to link, xxx@xxx.xxx to email. */
     if ($this->_params['parselevel'] < self::NOHTML) {
         $text = Horde_Text_Filter_Linkurls::decode($text);
         if ($this->_params['parselevel'] < self::MICRO_LINKURL) {
             $text = Horde_Text_Filter_Emails::decode($text);
         }
         if ($this->_params['space2html']) {
             $params = reset($this->_params['space2html']);
             $driver = key($this->_params['space2html']);
         } else {
             $driver = 'space2html';
             $params = array();
         }
         $text = Horde_Text_Filter::filter($text, $driver, $params);
     }
     /* Do the newline ---> <br /> substitution. Everybody gets this; if
      * you don't want even that, just use htmlspecialchars(). */
     return nl2br($text);
 }
예제 #17
0
파일: Base.php 프로젝트: horde/horde
 /**
  * Filter text.
  *
  * @param string $text    TODO
  * @param mixed  $driver  TODO
  * @param array  $params  TODO
  *
  * @return string  The filtered text.
  */
 protected function _textFilter($text, $driver, array $params = array())
 {
     return ($text_filter = $this->getConfigParam('text_filter')) ? call_user_func($text_filter, $text, $driver, $params) : Horde_Text_Filter::filter($text, $driver, $params);
 }
예제 #18
0
 /**
  * @dataProvider space2htmlProvider
  */
 public function testSpace2html($spaces, $results, $results_encode_all)
 {
     $this->assertEquals($results, Horde_Text_Filter::filter($spaces, 'space2html', array('encode_all' => false)));
     $this->assertEquals($results_encode_all, Horde_Text_Filter::filter($spaces, 'space2html', array('encode_all' => true)));
 }
예제 #19
0
 /**
  * @dataProvider environmentProvider
  */
 public function testEnvironment($input, $expected)
 {
     $this->assertEquals($expected, Horde_Text_Filter::filter($input, 'environment'));
 }
예제 #20
0
 public function testHtml2TextNestingLimit()
 {
     $html = '<span>Foo</span><div><div><div><div>Bar</div></div></div></div>';
     $filter = Horde_Text_Filter::filter($html, 'Html2text', array('nestingLimit' => 3));
     $this->assertEquals('Foo', $filter);
     $filter = Horde_Text_Filter::filter($html, 'Html2text', array('nestingLimit' => 4));
     $this->assertEquals('FooBar', $filter);
 }
예제 #21
0
파일: Api.php 프로젝트: DSNS-LAB/Dmail
 /**
  * Import a memo represented in the specified contentType.
  *
  * @param string $content      The content of the memo.
  * @param string $contentType  What format is the data in? Currently supports:
  *                             text/plain
  *                             text/x-vnote
  *                             activesync
  * @param string $notepad      (optional) The notepad to save the memo on.
  *
  * @return string  The new UID, or false on failure.
  * @throws Mnemo_Exception
  * @throws Horde_Exception_PermissionDenied
  */
 public function import($content, $contentType, $notepad = null)
 {
     global $prefs;
     /* Make sure we have a valid notepad and permissions to edit
      * it. */
     if (empty($notepad)) {
         $notepad = Mnemo::getDefaultNotepad(Horde_Perms::EDIT);
     }
     if (!array_key_exists($notepad, Mnemo::listNotepads(false, Horde_Perms::EDIT))) {
         throw new Horde_Exception_PermissionDenied();
     }
     /* Create a Mnemo_Driver instance. */
     $storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
     switch ($contentType) {
         case 'text/plain':
             $noteId = $storage->add($storage->getMemoDescription($content), $content);
             break;
         case 'text/x-vnote':
             if (!$content instanceof Horde_Icalendar_Vnote) {
                 $iCal = new Horde_Icalendar();
                 if (!$iCal->parsevCalendar($content)) {
                     throw new Mnemo_Exception(_("There was an error importing the iCalendar data."));
                 }
                 $components = $iCal->getComponents();
                 switch (count($components)) {
                     case 0:
                         throw new Mnemo_Exception(_("No iCalendar data was found."));
                     case 1:
                         $content = $components[0];
                         break;
                     default:
                         $ids = array();
                         foreach ($components as $content) {
                             if ($content instanceof Horde_Icalendar_Vnote) {
                                 $note = $storage->fromiCalendar($content);
                                 $noteId = $storage->add($note['desc'], $note['body'], !empty($note['tags']) ? $note['tags'] : '');
                                 $ids[] = $noteId;
                             }
                         }
                         return $ids;
                 }
             }
             $note = $storage->fromiCalendar($content);
             $noteId = $storage->add($note['desc'], $note['body'], !empty($note['tags']) ? $note['tags'] : '');
             break;
         case 'activesync':
             // We only support plaintext
             if ($content->body->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
                 $body = Horde_Text_Filter::filter($content->body->data, 'Html2text');
             } else {
                 $body = $content->body->data;
             }
             $noteId = $storage->add($content->subject, $body, $content->categories);
             break;
         default:
             throw new Mnemo_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType));
     }
     $note = $storage->get($noteId);
     return $note['uid'];
 }
예제 #22
0
 /**
  * @dataProvider emailsProvider
  */
 public function testEmails($input, $expected)
 {
     $this->assertEquals($expected, Horde_Text_Filter::filter($input, 'emails', array('class' => 'pagelink')));
 }
예제 #23
0
파일: Mail.php 프로젝트: pzhu2004/moodle
 /**
  * Sets the HTML message body text.
  *
  * @param string $body          The message content.
  * @param string $charset       The character set of the message.
  * @param boolean $alternative  If true, a multipart/alternative message is
  *                              created and the text/plain part is
  *                              generated automatically. If false, a
  *                              text/html message is generated.
  */
 public function setHtmlBody($body, $charset = null, $alternative = true)
 {
     if (!$charset) {
         $charset = $this->_charset;
     }
     $this->_htmlBody = new Horde_Mime_Part();
     $this->_htmlBody->setType('text/html');
     $this->_htmlBody->setCharset($charset);
     $this->_htmlBody->setContents($body);
     if ($alternative) {
         $this->setBody(Horde_Text_Filter::filter($body, 'Html2text', array('charset' => $charset, 'wrap' => false)), $charset);
     }
     $this->_base = null;
 }
예제 #24
0
파일: Task.php 프로젝트: horde/horde
 /**
  * Create a nag Task object from an activesync message
  *
  * @param Horde_ActiveSync_Message_Task $message  The task object
  */
 public function fromASTask(Horde_ActiveSync_Message_Task $message)
 {
     /* Owner is always current user. */
     $this->owner = $GLOBALS['registry']->getAuth();
     /* Must set _tags so we don't lazy load tags from the backend in the
      * case that this is an edit. For edits, all current tags will be passed
      * from the client.
      */
     $this->_tags = array();
     /* Notes and Title */
     if ($message->getProtocolVersion() >= Horde_ActiveSync::VERSION_TWELVE) {
         if ($message->airsyncbasebody->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
             $this->desc = Horde_Text_Filter::filter($message->airsyncbasebody->data, 'Html2text');
         } else {
             $this->desc = $message->airsyncbasebody->data;
         }
     } else {
         $this->desc = $message->body;
     }
     $this->name = $message->subject;
     $tz = date_default_timezone_get();
     /* Completion */
     if ($this->completed = $message->complete) {
         if ($message->datecompleted) {
             $message->datecompleted->setTimezone($tz);
             $this->completed_date = $message->datecompleted->timestamp();
         } else {
             $this->completed_date = null;
         }
     }
     /* Due Date */
     if ($due = $message->utcduedate) {
         $due->setTimezone($tz);
         $this->due = $due->timestamp();
     } elseif ($due = $message->duedate) {
         // "Local" date, sent as a UTC datetime string,
         // but must be interpreted as a local time. Since
         // we have no timezone information we have to assume it's the
         // same as $tz.
         $due = new Horde_Date(array('year' => $due->year, 'month' => $due->month, 'mday' => $due->mday, 'hour' => $due->hour, 'min' => $due->min), $tz);
         $this->due = $due->timestamp();
     }
     /* Start Date */
     if ($start = $message->utcstartdate) {
         $start->setTimezone($tz);
         $this->start = $start->timestamp();
     } elseif ($start = $message->startdate) {
         // See note above regarding utc vs local times.
         $start = new Horde_Date(array('year' => $start->year, 'month' => $start->month, 'mday' => $start->mday, 'hour' => $start->hour, 'min' => $start->min), $tz);
         $this->start = $start->timestamp();
     }
     /* Priority */
     switch ($message->getImportance()) {
         case Horde_ActiveSync_Message_Task::IMPORTANCE_LOW:
             $this->priority = 5;
             break;
         case Horde_ActiveSync_Message_Task::IMPORTANCE_NORMAL:
             $this->priority = 3;
             break;
         case Horde_ActiveSync_Message_Task::IMPORTANCE_HIGH:
             $this->priority = 1;
             break;
         default:
             $this->priority = 3;
     }
     if (($alarm = $message->getReminder()) && $this->due) {
         $alarm->setTimezone($tz);
         $this->alarm = ($this->due - $alarm->timestamp()) / 60;
     }
     if ($rrule = $message->getRecurrence()) {
         $this->recurrence = $rrule;
     }
     $this->tasklist = $GLOBALS['prefs']->getValue('default_tasklist');
     /* Categories */
     if (is_array($message->categories) && count($message->categories)) {
         $this->tags = implode(',', $message->categories);
     }
 }
예제 #25
0
 /**
  * Create a nag Task object from an activesync message
  *
  * @param Horde_ActiveSync_Message_Task $message  The task object
  */
 public function fromASTask(Horde_ActiveSync_Message_Task $message)
 {
     /* Owner is always current user. */
     $this->owner = $GLOBALS['registry']->getAuth();
     /* Notes and Title */
     if ($message->getProtocolVersion() >= Horde_ActiveSync::VERSION_TWELVE) {
         if ($message->airsyncbasebody->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
             $this->desc = Horde_Text_Filter::filter($message->airsyncbasebody->data, 'Html2text');
         } else {
             $this->desc = $message->airsyncbasebody->data;
         }
     } else {
         $this->desc = $message->body;
     }
     $this->name = $message->subject;
     $tz = date_default_timezone_get();
     /* Completion */
     if ($this->completed = $message->complete) {
         if ($message->datecompleted) {
             $message->datecompleted->setTimezone($tz);
             $this->completed_date = $message->datecompleted->timestamp();
         } else {
             $this->completed_date = null;
         }
     }
     /* Due Date */
     if (($due = $message->utcduedate) || ($due = $message->duedate)) {
         $due->setTimezone($tz);
         $this->due = $due->timestamp();
     }
     /* Start Date */
     if (($start = $message->utcstartdate) || ($start = $message->startdate)) {
         $start->setTimezone($tz);
         $this->start = $start->timestamp();
     }
     /* Priority */
     switch ($message->getImportance()) {
         case Horde_ActiveSync_Message_Task::IMPORTANCE_LOW:
             $this->priority = 5;
             break;
         case Horde_ActiveSync_Message_Task::IMPORTANCE_NORMAL:
             $this->priority = 3;
             break;
         case Horde_ActiveSync_Message_Task::IMPORTANCE_HIGH:
             $this->priority = 1;
             break;
         default:
             $this->priority = 3;
     }
     if (($alarm = $message->getReminder()) && $this->due) {
         $alarm->setTimezone($tz);
         $this->alarm = ($this->due - $alarm->timestamp()) / 60;
     }
     if ($rrule = $message->getRecurrence()) {
         $this->recurrence = $rrule;
     }
     $this->tasklist = $GLOBALS['prefs']->getValue('default_tasklist');
     /* Categories */
     if (is_array($message->categories) && count($message->categories)) {
         $this->tags = $message->categories;
     }
 }
예제 #26
0
파일: Api.php 프로젝트: platolin/horde
 /**
  * Replace the memo identified by UID with the content represented in
  * the specified contentType.
  *
  * @param string $uid          Idenfity the memo to replace.
  * @param string $content      The content of the memo.
  * @param string $contentType  What format is the data in? Currently supports:
  *                             text/plain
  *                             text/x-vnote
  *                             activesync
  * @throws Mnemo_Exception
  * @throws Horde_Exception_PermissionDenied
  */
 public function replace($uid, $content, $contentType)
 {
     $storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create();
     $memo = $storage->getByUID($uid);
     if (!array_key_exists($memo['memolist_id'], Mnemo::listNotepads(false, Horde_Perms::EDIT))) {
         throw new Horde_Exception_PermissionDenied();
     }
     switch ($contentType) {
         case 'text/plain':
             $storage->modify($memo['memo_id'], $storage->getMemoDescription($content), $content, null);
             break;
         case 'text/x-vnote':
             if (!$content instanceof Horde_Icalendar_Vnote) {
                 $iCal = new Horde_Icalendar();
                 if (!$iCal->parsevCalendar($content)) {
                     throw new Mnemo_Exception(_("There was an error importing the iCalendar data."));
                 }
                 $components = $iCal->getComponents();
                 switch (count($components)) {
                     case 0:
                         throw new Mnemo_Exception(_("No iCalendar data was found."));
                     case 1:
                         $content = $components[0];
                         break;
                     default:
                         throw new Mnemo_Exception(_("Multiple iCalendar components found; only one vNote is supported."));
                 }
             }
             $note = $storage->fromiCalendar($content);
             $storage->modify($memo['memo_id'], $note['desc'], $note['body'], !empty($note['tags']) ? $note['tags'] : '');
             break;
         case 'activesync':
             // We only support plaintext
             if ($content->body->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
                 $body = Horde_Text_Filter::filter($content->body->data, 'Html2text');
             } else {
                 $body = $content->body->data;
             }
             $storage->modify($memo['memo_id'], Horde_String::substr($content->subject, 0, 255), $body, $content->categories);
             break;
         default:
             throw new Mnemo_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType));
     }
 }
예제 #27
0
 /**
  * Build the data needed for the BodyPart part.
  *
  * @param  Horde_Imap_Client_Data_Fetch $data  The FETCH results.
  * @param  Horde_Mime_Part $mime  The plaintext MIME part.
  * @param boolean $to_html        If true, $id is assumed to be a text/plain
  *                                part and is converted to html.
  *
  * @return array  The BodyPart data.
  *     - charset:  (string)   The charset of the text.
  *     - body: (string)       The body text.
  *     - truncated: (boolean) True if text was truncated.
  *     - size: (integer)      The original part size, in bytes.
  */
 protected function _getBodyPart(Horde_Imap_Client_Data_Fetch $data, Horde_Mime_Part $mime, $to_html)
 {
     $id = $mime->getMimeId();
     $text = $data->getBodyPart($id);
     if (!$data->getBodyPartDecode($id)) {
         $mime->setContents($text);
         $text = $mime->getContents();
     }
     if ($to_html) {
         $text = Horde_Text_Filter::filter($text, 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO, 'charset' => $mime->getCharset()));
         $size = strlen($text);
     } else {
         $size = !is_null($data->getBodyPartSize($id)) ? $data->getBodyPartSize($id) : strlen($text);
     }
     if (!empty($this->_options['bodypartprefs']['truncationsize'])) {
         $text = Horde_String::substr($text, 0, $this->_options['bodypartprefs']['truncationsize'], $mime->getCharset());
     }
     return array('charset' => $mime->getCharset(), 'body' => $text, 'truncated' => $size > strlen($text), 'size' => $size);
 }
예제 #28
0
파일: WordsTest.php 프로젝트: horde/horde
 public function testDefaultReplacement()
 {
     $line = 'foo baz';
     $res = Horde_Text_Filter::filter($line, 'words', array('replacement' => null, 'words' => $this->words));
     $this->assertEquals('f** baz', $res);
 }
예제 #29
0
파일: Event.php 프로젝트: DSNS-LAB/Dmail
 /**
  * Export this event as a MS ActiveSync Message
  *
  * @param array $options  Options:
  *   - protocolversion: (float)  The EAS version to support
  *                      DEFAULT: 2.5
  *   - bodyprefs: (array)  A BODYPREFERENCE array.
  *                DEFAULT: none (No body prefs enforced).
  *   - truncation: (integer)  Truncate event body to this length
  *                 DEFAULT: none (No truncation).
  *
  * @return Horde_ActiveSync_Message_Appointment
  */
 public function toASAppointment(array $options = array())
 {
     global $prefs, $registry;
     $message = new Horde_ActiveSync_Message_Appointment(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion']));
     if (!$this->isPrivate()) {
         // Handle body/truncation
         if (!empty($options['bodyprefs'])) {
             if (Horde_String::length($this->description) > 0) {
                 $bp = $options['bodyprefs'];
                 $note = new Horde_ActiveSync_Message_AirSyncBaseBody();
                 // No HTML supported. Always use plaintext.
                 $note->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN;
                 if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) {
                     $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'];
                 } elseif (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) {
                     $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize'];
                     $this->description = Horde_Text_Filter::filter($this->description, 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
                 } else {
                     $truncation = false;
                 }
                 if ($truncation && Horde_String::length($this->description) > $truncation) {
                     $note->data = Horde_String::substr($this->desciption, 0, $truncation);
                     $note->truncated = 1;
                 } else {
                     $note->data = $this->description;
                 }
                 $note->estimateddatasize = Horde_String::length($this->description);
                 $message->airsyncbasebody = $note;
             }
         } else {
             $message->setBody($this->description);
         }
         $message->setLocation($this->location);
     }
     $message->setSubject($this->getTitle());
     $message->setDatetime(array('start' => $this->start, 'end' => $this->end, 'allday' => $this->isAllDay()));
     $message->setTimezone($this->start);
     // Organizer
     if (count($this->attendees)) {
         if ($this->creator == $registry->getAuth()) {
             $as_ident = $prefs->getValue('activesync_identity') == 'horde' ? $prefs->getValue('default_identity') : $prefs->getValue('activesync_identity');
             $name = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($this->creator)->getValue('fullname', $as_ident);
             $email = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($this->creator)->getValue('from_addr', $as_ident);
         } else {
             $name = Kronolith::getUserName($this->creator);
             $email = Kronolith::getUserEmail($this->creator);
         }
         $message->setOrganizer(array('name' => $name, 'email' => $email));
     }
     // Privacy
     $message->setSensitivity($this->private ? Horde_ActiveSync_Message_Appointment::SENSITIVITY_PRIVATE : Horde_ActiveSync_Message_Appointment::SENSITIVITY_NORMAL);
     // Busy Status
     switch ($this->status) {
         case Kronolith::STATUS_CANCELLED:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_FREE;
             break;
         case Kronolith::STATUS_CONFIRMED:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_BUSY;
             break;
         case Kronolith::STATUS_TENTATIVE:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_TENTATIVE;
         case Kronolith::STATUS_FREE:
         case Kronolith::STATUS_NONE:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_FREE;
     }
     $message->setBusyStatus($status);
     // DTStamp
     $message->setDTStamp($_SERVER['REQUEST_TIME']);
     // Recurrence
     if ($this->recurs()) {
         $message->setRecurrence($this->recurrence, $GLOBALS['prefs']->getValue('week_start_monday'));
         /* Exceptions are tricky. Exceptions, even those that represent
          * deleted instances of a recurring event, must be added. To do this
          * we query the storage for all the events that represent exceptions
          * (those with the baseid == $this->uid) and then remove the
          * exceptionoriginaldate from the list of exceptions we know about.
          * Any dates left in this list when we are done, must represent
          * deleted instances of this recurring event.*/
         if (!empty($this->recurrence) && ($exceptions = $this->recurrence->getExceptions())) {
             $results = $this->boundExceptions();
             foreach ($results as $exception) {
                 $e = new Horde_ActiveSync_Message_Exception(array('protocolversion' => $options['protocolversion']));
                 $e->setDateTime(array('start' => $exception->start, 'end' => $exception->end, 'allday' => $exception->isAllDay()));
                 // The start time of the *original* recurring event
                 $e->setExceptionStartTime($exception->exceptionoriginaldate);
                 $originaldate = $exception->exceptionoriginaldate->format('Ymd');
                 $key = array_search($originaldate, $exceptions);
                 if ($key !== false) {
                     unset($exceptions[$key]);
                 }
                 // Remaining properties that could be different
                 $e->setSubject($exception->getTitle());
                 if (!$exception->isPrivate()) {
                     $e->setLocation($exception->location);
                     $e->setBody($exception->description);
                 }
                 $e->setSensitivity($exception->private ? Horde_ActiveSync_Message_Appointment::SENSITIVITY_PRIVATE : Horde_ActiveSync_Message_Appointment::SENSITIVITY_NORMAL);
                 $e->setReminder($exception->alarm);
                 $e->setDTStamp($_SERVER['REQUEST_TIME']);
                 if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) {
                     switch ($exception->status) {
                         case Kronolith::STATUS_TENTATIVE:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_TENTATIVE;
                             break;
                         case Kronolith::STATUS_NONE:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NORESPONSE;
                             break;
                         case Kronolith::STATUS_CONFIRMED:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ACCEPTED;
                             break;
                         default:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NONE;
                     }
                 }
                 // Tags/Categories
                 if (!$exception->isPrivate()) {
                     foreach ($exception->tags as $tag) {
                         $e->addCategory($tag);
                     }
                 }
                 $message->addexception($e);
             }
             // Any dates left in $exceptions must be deleted exceptions
             foreach ($exceptions as $deleted) {
                 $e = new Horde_ActiveSync_Message_Exception(array('protocolversion' => $options['protocolversion']));
                 // Kronolith stores the date only, but some AS clients need
                 // the datetime.
                 list($year, $month, $mday) = sscanf($deleted, '%04d%02d%02d');
                 $st = clone $this->start;
                 $st->year = $year;
                 $st->month = $month;
                 $st->mday = $mday;
                 $e->setExceptionStartTime($st);
                 $e->deleted = true;
                 $message->addException($e);
             }
         }
     }
     // Attendees
     if (!$this->isPrivate() && count($this->attendees)) {
         $message->setMeetingStatus(Horde_ActiveSync_Message_Appointment::MEETING_IS_MEETING);
         foreach ($this->attendees as $email => $properties) {
             $attendee = new Horde_ActiveSync_Message_Attendee(array('protocolversion' => $options['protocolversion']));
             $adr_obj = new Horde_Mail_Rfc822_Address($email);
             $attendee->name = $adr_obj->label;
             $attendee->email = $adr_obj->bare_address;
             // AS only has required or optional, and only EAS Version > 2.5
             if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) {
                 $attendee->type = $properties['attendance'] !== Kronolith::PART_REQUIRED ? Horde_ActiveSync_Message_Attendee::TYPE_OPTIONAL : Horde_ActiveSync_Message_Attendee::TYPE_REQUIRED;
                 switch ($properties['response']) {
                     case Kronolith::RESPONSE_NONE:
                         $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_NORESPONSE;
                         break;
                     case Kronolith::RESPONSE_ACCEPTED:
                         $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_ACCEPT;
                         break;
                     case Kronolith::RESPONSE_DECLINED:
                         $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_DECLINE;
                         break;
                     case Kronolith::RESPONSE_TENTATIVE:
                         $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_TENTATIVE;
                         break;
                     default:
                         $attendee->status = Horde_ActiveSync_Message_Attendee::STATUS_UNKNOWN;
                 }
             }
             $message->addAttendee($attendee);
         }
     } else {
         $message->setMeetingStatus(Horde_ActiveSync_Message_Appointment::MEETING_NOT_MEETING);
     }
     // Resources
     if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) {
         $r = $this->getResources();
         foreach ($r as $id => $data) {
             $resource = Kronolith::getDriver('Resource')->getResource($id);
             // EAS *REQUIRES* an email field for Resources. If it is missing
             // a number of clients will fail, losing push.
             if ($resource->get('email')) {
                 $attendee = new Horde_ActiveSync_Message_Attendee(array('protocolversion' => $options['protocolversion']));
                 $attendee->email = $resource->get('email');
                 $attendee->type = Horde_ActiveSync_Message_Attendee::TYPE_RESOURCE;
                 $attendee->name = $data['name'];
                 $attendee->status = $data['response'];
                 $message->addAttendee($attendee);
             }
         }
     }
     // Reminder
     if ($this->alarm) {
         $message->setReminder($this->alarm);
     }
     // Categories (tags)
     if (!$this->isPrivate()) {
         foreach ($this->tags as $tag) {
             $message->addCategory($tag);
         }
     }
     // EAS 14
     if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) {
         // We don't track the actual responses we sent to other's invitations.
         // Set this based on the status flag.
         switch ($this->status) {
             case Kronolith::STATUS_TENTATIVE:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_TENTATIVE;
                 break;
             case Kronolith::STATUS_NONE:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NORESPONSE;
                 break;
             case Kronolith::STATUS_CONFIRMED:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ACCEPTED;
                 break;
             default:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NONE;
         }
     }
     // 14.1
     if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_FOURTEENONE) {
         $message->onlinemeetingexternallink = $this->url;
     }
     return $message;
 }
예제 #30
0
파일: Event.php 프로젝트: horde/horde
 /**
  * Export this event as a MS ActiveSync Message
  *
  * @param array $options  Options:
  *   - protocolversion: (float)  The EAS version to support
  *                      DEFAULT: 2.5
  *   - bodyprefs: (array)  A BODYPREFERENCE array.
  *                DEFAULT: none (No body prefs enforced).
  *   - truncation: (integer)  Truncate event body to this length
  *                 DEFAULT: none (No truncation).
  *
  * @return Horde_ActiveSync_Message_Appointment
  */
 public function toASAppointment(array $options = array())
 {
     global $prefs, $registry;
     // @todo This should be a required option.
     if (empty($options['protocolversion'])) {
         $options['protocolversion'] = 2.5;
     }
     $message = new Horde_ActiveSync_Message_Appointment(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion']));
     if (!$this->isPrivate()) {
         // Handle body/truncation
         if (!empty($options['bodyprefs'])) {
             if (Horde_String::length($this->description) > 0) {
                 $bp = $options['bodyprefs'];
                 $note = new Horde_ActiveSync_Message_AirSyncBaseBody();
                 // No HTML supported. Always use plaintext.
                 $note->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN;
                 if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) {
                     $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'];
                 } elseif (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) {
                     $truncation = $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize'];
                     $this->description = Horde_Text_Filter::filter($this->description, 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
                 } else {
                     $truncation = false;
                 }
                 if ($truncation && Horde_String::length($this->description) > $truncation) {
                     $note->data = Horde_String::substr($this->description, 0, $truncation);
                     $note->truncated = 1;
                 } else {
                     $note->data = $this->description;
                 }
                 $note->estimateddatasize = Horde_String::length($this->description);
                 $message->airsyncbasebody = $note;
             }
         } else {
             $message->setBody($this->description);
         }
         if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_SIXTEEN && !empty($this->location)) {
             $message->location = new Horde_ActiveSync_Message_AirSyncBaseLocation(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion']));
             // @todo - worth it to try to get full city/country etc...
             // from geotagging service if available??
             $message->location->displayname = $this->location;
         } else {
             $message->setLocation($this->location);
         }
     }
     $message->setSubject($this->getTitle());
     $message->alldayevent = $this->isAllDay();
     $st = clone $this->start;
     $et = clone $this->end;
     if ($this->isAllDay()) {
         // EAS requires all day to be from 12:00 to 12:00.
         if ($this->start->hour != 0 || $this->start->min != 0 || $this->start->sec != 0) {
             $st->hour = 0;
             $st->min = 0;
             $st->sec = 0;
         }
         // For end it's a bit trickier. If it's 11:59pm, bump it up to 12:00
         // am of the next day. Otherwise, if it's not 12:00am, make it 12:00
         // am of the same day. This *shouldn't* happen, but protect against
         // issues with EAS just in case.
         if ($this->end->hour != 0 || $this->end->min != 0 || $this->end->sec != 0) {
             if ($this->end->hour == 23 && $this->end->min == 59) {
                 $et->mday++;
             }
             $et->hour = 0;
             $et->min = 0;
             $et->sec = 0;
         }
     }
     $message->starttime = $st;
     $message->endtime = $et;
     $message->setTimezone($this->start);
     // Organizer
     $attendees = $this->attendees;
     $skipOrganizer = null;
     if ($this->organizer) {
         $message->setOrganizer(array('email' => $this->organizer));
     } elseif (count($attendees)) {
         if ($this->creator == $registry->getAuth()) {
             $as_ident = $prefs->getValue('activesync_identity') == 'horde' ? $prefs->getValue('default_identity') : $prefs->getValue('activesync_identity');
             $name = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($this->creator)->getValue('fullname', $as_ident);
             $email = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($this->creator)->getValue('from_addr', $as_ident);
         } else {
             $name = Kronolith::getUserName($this->creator);
             $email = Kronolith::getUserEmail($this->creator);
         }
         $message->setOrganizer(array('name' => $name, 'email' => $email));
         $skipOrganizer = $email;
     }
     // Privacy
     $message->setSensitivity($this->private ? Horde_ActiveSync_Message_Appointment::SENSITIVITY_PRIVATE : Horde_ActiveSync_Message_Appointment::SENSITIVITY_NORMAL);
     // Busy Status
     // This is the *busy* status of the time for this meeting. This is NOT
     // the Kronolith_Event::status or the attendance response for this
     // meeting. Kronolith does not (yet) support sepcifying the busy status
     // of the event time separate from the STATUS_FREE value of the
     // Kronolith_Event::status field, so for now we map these values the
     // best we can by assuming that STATUS_CONFIRMED meetings should always
     // show as BUSYSTATUS_BUSY etc...
     switch ($this->status) {
         case Kronolith::STATUS_CANCELLED:
         case Kronolith::STATUS_FREE:
         case Kronolith::STATUS_NONE:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_FREE;
             break;
         case Kronolith::STATUS_CONFIRMED:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_BUSY;
             break;
         case Kronolith::STATUS_TENTATIVE:
             $status = Horde_ActiveSync_Message_Appointment::BUSYSTATUS_TENTATIVE;
     }
     $message->setBusyStatus($status);
     // DTStamp
     $message->setDTStamp($_SERVER['REQUEST_TIME']);
     // Recurrence
     if ($this->recurs()) {
         $message->setRecurrence($this->recurrence, $GLOBALS['prefs']->getValue('week_start_monday'));
         /* Exceptions are tricky. Exceptions, even those that represent
          * deleted instances of a recurring event, must be added. To do this
          * we query the storage for all the events that represent exceptions
          * (those with the baseid == $this->uid) and then remove the
          * exceptionoriginaldate from the list of exceptions we know about.
          * Any dates left in this list when we are done, must represent
          * deleted instances of this recurring event.*/
         if (!empty($this->recurrence) && ($exceptions = $this->recurrence->getExceptions())) {
             $results = $this->boundExceptions();
             foreach ($results as $exception) {
                 $e = new Horde_ActiveSync_Message_Exception(array('protocolversion' => $options['protocolversion']));
                 $e->setDateTime(array('start' => $exception->start, 'end' => $exception->end, 'allday' => $exception->isAllDay()));
                 // The start time of the *original* recurring event.
                 // EAS < 16.0 uses 'exceptionstarttime'. Otherwise it's
                 // 'instanceid'.
                 if ($options['protocolversion'] < Horde_ActiveSync::VERSION_SIXTEEN) {
                     $e->setExceptionStartTime($exception->exceptionoriginaldate);
                 } else {
                     $e->instanceid = $exception->exceptionoriginaldate;
                 }
                 $originaldate = $exception->exceptionoriginaldate->format('Ymd');
                 $key = array_search($originaldate, $exceptions);
                 if ($key !== false) {
                     unset($exceptions[$key]);
                 }
                 // Remaining properties that could be different
                 $e->setSubject($exception->getTitle());
                 if (!$exception->isPrivate()) {
                     $e->setLocation($exception->location);
                     $e->setBody($exception->description);
                 }
                 $e->setSensitivity($exception->private ? Horde_ActiveSync_Message_Appointment::SENSITIVITY_PRIVATE : Horde_ActiveSync_Message_Appointment::SENSITIVITY_NORMAL);
                 $e->setReminder($exception->alarm);
                 $e->setDTStamp($_SERVER['REQUEST_TIME']);
                 if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE) {
                     switch ($exception->status) {
                         case Kronolith::STATUS_TENTATIVE:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_TENTATIVE;
                             break;
                         case Kronolith::STATUS_NONE:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NORESPONSE;
                             break;
                         case Kronolith::STATUS_CONFIRMED:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ACCEPTED;
                             break;
                         default:
                             $e->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NONE;
                     }
                 }
                 // Tags/Categories
                 if (!$exception->isPrivate()) {
                     foreach ($exception->tags as $tag) {
                         $e->addCategory($tag);
                     }
                 }
                 $message->addexception($e);
             }
             // Any dates left in $exceptions must be deleted exceptions
             foreach ($exceptions as $deleted) {
                 $e = new Horde_ActiveSync_Message_Exception(array('protocolversion' => $options['protocolversion']));
                 // Kronolith stores the date only, but some AS clients need
                 // the datetime.
                 list($year, $month, $mday) = sscanf($deleted, '%04d%02d%02d');
                 $st = clone $this->start;
                 $st->year = $year;
                 $st->month = $month;
                 $st->mday = $mday;
                 if ($options['protocolversion'] < Horde_ActiveSync::VERSION_SIXTEEN) {
                     $e->setExceptionStartTime($st);
                 } else {
                     $e->instanceid = $st;
                 }
                 $e->deleted = true;
                 $message->addException($e);
             }
         }
     }
     // Attendees
     if (!$this->isPrivate() && count($attendees)) {
         $message->setMeetingStatus($this->status == Kronolith::STATUS_CANCELLED ? Horde_ActiveSync_Message_Appointment::MEETING_CANCELLED : Horde_ActiveSync_Message_Appointment::MEETING_IS_MEETING);
         foreach ($attendees as $attendee) {
             if ($skipOrganizer && $attendee->email == $skipOrganizer) {
                 continue;
             }
             $attendeeAS = new Horde_ActiveSync_Message_Attendee(array('protocolversion' => $options['protocolversion']));
             $attendeeAS->name = $attendee->addressObject->label;
             $attendeeAS->email = $attendee->addressObject->bare_address;
             // AS only has required or optional, and only EAS Version > 2.5
             if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) {
                 $attendeeAS->type = $attendee->role !== Kronolith::PART_REQUIRED ? Horde_ActiveSync_Message_Attendee::TYPE_OPTIONAL : Horde_ActiveSync_Message_Attendee::TYPE_REQUIRED;
                 switch ($attendee->response) {
                     case Kronolith::RESPONSE_NONE:
                         $attendeeAS->status = Horde_ActiveSync_Message_Attendee::STATUS_NORESPONSE;
                         break;
                     case Kronolith::RESPONSE_ACCEPTED:
                         $attendeeAS->status = Horde_ActiveSync_Message_Attendee::STATUS_ACCEPT;
                         break;
                     case Kronolith::RESPONSE_DECLINED:
                         $attendeeAS->status = Horde_ActiveSync_Message_Attendee::STATUS_DECLINE;
                         break;
                     case Kronolith::RESPONSE_TENTATIVE:
                         $attendeeAS->status = Horde_ActiveSync_Message_Attendee::STATUS_TENTATIVE;
                         break;
                     default:
                         $attendeeAS->status = Horde_ActiveSync_Message_Attendee::STATUS_UNKNOWN;
                 }
             }
             $message->addAttendee($attendeeAS);
         }
     } elseif ($this->status == Kronolith::STATUS_CANCELLED) {
         $message->setMeetingStatus(Horde_ActiveSync_Message_Appointment::MEETING_CANCELLED);
     } else {
         $message->setMeetingStatus(Horde_ActiveSync_Message_Appointment::MEETING_NOT_MEETING);
     }
     // Resources
     if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) {
         $r = $this->getResources();
         foreach ($r as $id => $data) {
             $resource = Kronolith::getDriver('Resource')->getResource($id);
             // EAS *REQUIRES* an email field for Resources. If it is missing
             // a number of clients will fail, losing push.
             if ($resource->get('email')) {
                 $attendeeAS = new Horde_ActiveSync_Message_Attendee(array('protocolversion' => $options['protocolversion']));
                 $attendeeAS->email = $resource->get('email');
                 $attendeeAS->type = Horde_ActiveSync_Message_Attendee::TYPE_RESOURCE;
                 $attendeeAS->name = $data['name'];
                 $attendeeAS->status = $data['response'];
                 $message->addAttendee($attendeeAS);
             }
         }
     }
     // Reminder
     if ($this->alarm) {
         $message->setReminder($this->alarm);
     }
     // Categories (tags)
     if (!$this->isPrivate()) {
         foreach ($this->tags as $tag) {
             $message->addCategory($tag);
         }
     }
     // EAS 14, and only if it is a meeting.
     if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWELVEONE && $message->getMeetingStatus() == Horde_ActiveSync_Message_Appointment::MEETING_IS_MEETING) {
         // Are we the
         if (empty($this->organizer) && $this->creator == $registry->getAuth()) {
             $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ORGANIZER;
         }
         // We don't track the actual responses we sent to other's invitations.
         // Set this based on the status flag.
         switch ($this->status) {
             case Kronolith::STATUS_TENTATIVE:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_TENTATIVE;
                 break;
             case Kronolith::STATUS_NONE:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NORESPONSE;
                 break;
             case Kronolith::STATUS_CONFIRMED:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_ACCEPTED;
                 break;
             default:
                 $message->responsetype = Horde_ActiveSync_Message_Appointment::RESPONSE_NONE;
         }
     }
     // 14.1
     if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_FOURTEENONE) {
         $message->onlinemeetingexternallink = $this->url;
     }
     // 16.0
     if ($options['protocolversion'] >= Horde_ActiveSync::VERSION_SIXTEEN) {
         $files = $this->listFiles();
         if (count($files)) {
             foreach ($files as $file) {
                 $atc = new Horde_ActiveSync_Message_AirSyncBaseAttachment(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion']));
                 $atc->displayname = $file['name'];
                 $atc->attname = $this->_getEASFileReference($file['name']);
                 $atc->attmethod = Horde_ActiveSync_Message_AirSyncBaseAttachment::ATT_TYPE_NORMAL;
                 $atc->attsize = $file['size'];
                 $message->addAttachment($atc);
             }
         }
     }
     return $message;
 }