From: Chuck Hagenbuch Date: Sun, 9 Nov 2008 04:34:34 +0000 (-0500) Subject: now we're using the new Mime dir X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=d416f5efb94ca90a1eee63e6a35ce85fb2972d41;p=horde.git now we're using the new Mime dir --- diff --git a/framework/Mime/lib/Horde/Mime.php b/framework/Mime/lib/Horde/Mime.php new file mode 100644 index 000000000..9569c78f3 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime.php @@ -0,0 +1,443 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME +{ + /** + * Determines if a string contains 8-bit (non US-ASCII) characters. + * + * @param string $string The string to check. + * @param string $charset The charset of the string. Defaults to + * US-ASCII. + * + * @return boolean True if string contains non US-ASCII characters. + */ + static public function is8bit($string, $charset = null) + { + /* ISO-2022-JP is a 7bit charset, but it is an 8bit representation so + * it needs to be entirely encoded. */ + return is_string($string) && + ((stristr('iso-2022-jp', $charset) && + (strstr($string, "\x1b\$B"))) || + preg_match('/[\x80-\xff]/', $string)); + } + + /** + * Encodes a string containing non-ASCII characters according to RFC 2047. + * + * @param string $text The text to encode. + * @param string $charset The character set of the text. + * + * @return string The text, encoded only if it contains non-ASCII + * characters. + */ + static public function encode($text, $charset = null) + { + if (is_null($charset)) { + require_once 'Horde/NLS.php'; + $charset = NLS::getCharset(); + } + $charset = String::lower($charset); + + if (($charset == 'us-ascii') || !self::is8bit($text, $charset)) { + return $text; + } + + /* Get the list of elements in the string. */ + $size = preg_match_all('/([^\s]+)([\s]*)/', $text, $matches, PREG_SET_ORDER); + + $line = ''; + + /* Return if nothing needs to be encoded. */ + foreach ($matches as $key => $val) { + if (self::is8bit($val[1], $charset)) { + if ((($key + 1) < $size) && + self::is8bit($matches[$key + 1][1], $charset)) { + $line .= self::_encode($val[1] . $val[2], $charset) . ' '; + } else { + $line .= self::_encode($val[1], $charset) . $val[2]; + } + } else { + $line .= $val[1] . $val[2]; + } + } + + return rtrim($line); + } + + /** + * Internal recursive function to RFC 2047 encode a string. + * + * @param string $text The text to encode. + * @param string $charset The character set of the text. + * + * @return string The text, encoded only if it contains non-ASCII + * characters. + */ + static protected function _encode($text, $charset) + { + $encoded = trim(base64_encode($text)); + $c_size = strlen($charset) + 7; + + if ((strlen($encoded) + $c_size) > 75) { + $parts = explode("\r\n", rtrim(chunk_split($encoded, intval((75 - $c_size) / 4) * 4))); + } else { + $parts[] = $encoded; + } + + $p_size = count($parts); + $out = ''; + + foreach ($parts as $key => $val) { + $out .= '=?' . $charset . '?b?' . $val . '?='; + if ($p_size > $key + 1) { + /* RFC 2047 [2]: no encoded word can be more than 75 + * characters long. If longer, you must split the word with + * CRLF SPACE. */ + $out .= "\r\n "; + } + } + + return $out; + } + + /** + * Encodes a line via quoted-printable encoding. + * + * @param string $text The text to encode. + * @param string $eol The EOL sequence to use. + * @param integer $wrap Wrap a line at this many characters. + * + * @return string The quoted-printable encoded string. + */ + static public function quotedPrintableEncode($text, $eol, $wrap = 76) + { + $line = $output = ''; + $curr_length = 0; + + /* We need to go character by character through the data. */ + for ($i = 0, $length = strlen($text); $i < $length; ++$i) { + $char = $text[$i]; + + /* If we have reached the end of the line, reset counters. */ + if ($char == "\n") { + $output .= $eol; + $curr_length = 0; + continue; + } elseif ($char == "\r") { + continue; + } + + /* Spaces or tabs at the end of the line are NOT allowed. Also, + * ASCII characters below 32 or above 126 AND 61 must be + * encoded. */ + $ascii = ord($char); + if ((($ascii === 32) && + ($i + 1 != $length) && + (($text[$i + 1] == "\n") || ($text[$i + 1] == "\r"))) || + (($ascii < 32) || ($ascii > 126) || ($ascii === 61))) { + $char_len = 3; + $char = '=' . String::upper(sprintf('%02s', dechex($ascii))); + } else { + $char_len = 1; + } + + /* Lines must be $wrap characters or less. */ + $curr_length += $char_len; + if ($curr_length > $wrap) { + $output .= '=' . $eol; + $curr_length = $char_len; + } + $output .= $char; + } + + return $output; + } + + /** + * Encodes a string containing email addresses according to RFC 2047. + * + * This differs from encode() because it keeps email addresses legal, only + * encoding the personal information. + * + * @param mixed $addresses The email addresses to encode (either a + * string or an array of addresses). + * @param string $charset The character set of the text. + * @param string $defserver The default domain to append to mailboxes. + * + * @return string The text, encoded only if it contains non-ASCII + * characters, or PEAR_Error on error. + */ + static public function encodeAddress($addresses, $charset = null, + $defserver = null) + { + if (!is_array($addresses)) { + /* parseAddressList() does not process the null entry + * 'undisclosed-recipients:;' correctly. */ + $addresses = trim($addresses); + if (preg_match('/undisclosed-recipients:\s*;/i', $addresses)) { + return $addresses; + } + + $addresses = Horde_MIME_Address::parseAddressList($addresses, array('defserver' => $defserver, 'nestgroups' => true)); + if (is_a($addresses, 'PEAR_Error')) { + return $addresses; + } + } + + $text = ''; + foreach ($addresses as $addr) { + // Check for groups. + if (empty($addr['groupname'])) { + if (empty($addr['personal'])) { + $personal = ''; + } else { + if (($addr['personal'][0] == '"') && + (substr($addr['personal'], -1) == '"')) { + $addr['personal'] = stripslashes(substr($addr['personal'], 1, -1)); + } + $personal = self::encode($addr['personal'], $charset); + } + $text .= Horde_MIME_Address::writeAddress($addr['mailbox'], $addr['host'], $personal) . ', '; + } else { + $text .= Horde_MIME_Address::writeGroupAddress($addr['groupname'], $addr['addresses']) . ' '; + } + } + + return rtrim($text, ' ,'); + } + + /** + * Decodes an RFC 2047-encoded string. + * + * @param string $string The text to decode. + * @param string $to_charset The charset that the text should be decoded + * to. + * + * @return string The decoded text. + */ + static public function decode($string, $to_charset = null) + { + if (($pos = strpos($string, '=?')) === false) { + return $string; + } + + /* Take out any spaces between multiple encoded words. */ + $string = preg_replace('|\?=\s+=\?|', '?==?', $string); + + /* Save any preceding text. */ + $preceding = substr($string, 0, $pos); + + $search = substr($string, $pos + 2); + $d1 = strpos($search, '?'); + if ($d1 === false) { + return $string; + } + + $charset = substr($string, $pos + 2, $d1); + $search = substr($search, $d1 + 1); + + $d2 = strpos($search, '?'); + if ($d2 === false) { + return $string; + } + + $encoding = substr($search, 0, $d2); + $search = substr($search, $d2 + 1); + + $end = strpos($search, '?='); + if ($end === false) { + $end = strlen($search); + } + + $encoded_text = substr($search, 0, $end); + $rest = substr($string, (strlen($preceding . $charset . $encoding . $encoded_text) + 6)); + + if (is_null($to_charset)) { + require_once 'Horde/NLS.php'; + $to_charset = NLS::getCharset(); + } + + switch ($encoding) { + case 'Q': + case 'q': + $decoded = preg_replace('/=([0-9a-f]{2})/ie', 'chr(0x\1)', str_replace('_', ' ', $encoded_text)); + $decoded = String::convertCharset($decoded, $charset, $to_charset); + break; + + case 'B': + case 'b': + $decoded = String::convertCharset(base64_decode($encoded_text), $charset, $to_charset); + break; + + default: + $decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?='; + break; + } + + return $preceding . $decoded . self::decode($rest, $to_charset); + } + + /** + * Decodes an RFC 2047-encoded address string. + * + * @param string $string The text to decode. + * @param string $to_charset The charset that the text should be decoded + * to. + * + * @return string The decoded text. + */ + static public function decodeAddrString($string, $to_charset = null) + { + $addr_list = array(); + foreach (Horde_MIME_Address::parseAddressList($string) as $ob) { + $ob['personal'] = isset($ob['personal']) + ? self::decode($ob['personal'], $to_charset) + : ''; + $addr_list[] = $ob; + } + + return Horde_MIME_Address::addrArray2String($addr_list); + } + + /** + * Encodes a parameter string pursuant to RFC 2231. + * + * @param string $name The parameter name. + * @param string $string The string to encode. + * @param string $charset The charset the text should be encoded with. + * @param string $lang The language to use when encoding. + * + * @return array The encoded parameter string. + */ + static public function encodeParamString($name, $string, $charset, + $lang = null) + { + $encode = $wrap = false; + $output = array(); + + if (self::is8bit($string, $charset)) { + $string = String::lower($charset) . '\'' . (is_null($lang) ? '' : String::lower($lang)) . '\'' . rawurlencode($string); + $encode = true; + } + + // 4 = '*', 2x '"', ';' + $pre_len = strlen($name) + 4 + (($encode) ? 1 : 0); + if (($pre_len + strlen($string)) > 76) { + while ($string) { + $chunk = 76 - $pre_len; + $pos = min($chunk, strlen($string) - 1); + if (($chunk == $pos) && ($pos > 2)) { + for ($i = 0; $i <= 2; $i++) { + if ($string[$pos-$i] == '%') { + $pos -= $i + 1; + break; + } + } + } + $lines[] = substr($string, 0, $pos + 1); + $string = substr($string, $pos + 1); + } + $wrap = true; + } else { + $lines = array($string); + } + + $i = 0; + foreach ($lines as $val) { + $output[] = + $name . + (($wrap) ? ('*' . $i++) : '') . + (($encode) ? '*' : '') . + '="' . $val . '"'; + } + + return implode('; ', $output); + } + + /** + * Decodes a parameter string encoded pursuant to RFC 2231. + * + * @param string $string The entire string to decode, including the + * parameter name. + * @param string $to_charset The charset the text should be decoded to. + * + * @return array The decoded text, or the original string if it was not + * encoded. + */ + static public function decodeParamString($string, $to_charset = null) + { + if (($pos = strpos($string, '*')) === false) { + return false; + } + + if (!isset($to_charset)) { + require_once 'Horde/NLS.php'; + $to_charset = NLS::getCharset(); + } + + $attribute = substr($string, 0, $pos); + $charset = $lang = null; + $output = ''; + + /* Get the character set and language used in the encoding, if + * any. */ + if (preg_match("/^[^=]+\*\=([^']*)'([^']*)'/", $string, $matches)) { + $charset = $matches[1]; + $lang = $matches[2]; + $string = str_replace($charset . "'" . $lang . "'", '', $string); + } + + $lines = preg_split('/\s*' . preg_quote($attribute) . '(?:\*\d)*/', $string); + foreach ($lines as $line) { + if (strpos($line, '*=') === 0) { + $output .= urldecode(str_replace(array('_', '='), array('%20', '%'), substr($line, 2))); + } else { + $output .= substr($line, 1); + } + } + + /* RFC 2231 uses quoted printable encoding. */ + if (!is_null($charset)) { + $output = String::convertCharset($output, $charset, $to_charset); + } + + return array( + 'attribute' => $attribute, + 'value' => $output + ); + } + + /** + * Generates a Message-ID string conforming to RFC 2822 [3.6.4] and the + * standards outlined in 'draft-ietf-usefor-message-id-01.txt'. + * + * @param string A message ID string. + */ + static public function generateMessageID() + { + return '<' . date('YmdHis') . '.' . self::generateRandomID() . '@' . $_SERVER['SERVER_NAME'] . '>'; + } + + /** + * Generates a Random-ID string suitable for use with MIME features that + * require a random string. + * + * @return string A random string. + */ + static public function generateRandomID() + { + return base_convert(dechex(strtr(microtime(), array('0.' => '', ' ' => ''))) . uniqid(), 16, 36); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Address.php b/framework/Mime/lib/Horde/Mime/Address.php new file mode 100644 index 000000000..1ca31fdc0 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Address.php @@ -0,0 +1,401 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME_Address +{ + /** + * Builds an RFC compliant email address. + * + * @param string $mailbox Mailbox name. + * @param string $host Domain name of mailbox's host. + * @param string $personal Personal name phrase. + * + * @return string The correctly escaped and quoted + * "$personal <$mailbox@$host>" string. + */ + static public function writeAddress($mailbox, $host, $personal = '') + { + $address = ''; + + if (strlen($personal)) { + $address .= self::encode($personal, 'personal') . ' <'; + } + + $address .= self::encode($mailbox, 'address') . '@' . ltrim($host, '@'); + + if (strlen($personal)) { + $address .= '>'; + } + + return $address; + } + + /** + * Write an RFC compliant group address, given the group name and a list + * of email addresses. + * + * @param string $groupname The name of the group. + * @param array $addresses The component email addresses. These e-mail + * addresses must be in RFC format. + * + * @return string The correctly quoted group string. + */ + static public function writeGroupAddress($groupname, $addresses = array()) + { + return self::encode($groupname, 'address') . ':' . (empty($addresses) ? '' : implode(', ', $addresses)) . ';'; + } + + /** + * If an email address has no personal information, get rid of any angle + * brackets (<>) around it. + * + * @param string $address The address to trim. + * + * @return string The trimmed address. + */ + static public function trimAddress($address) + { + $address = trim($address); + + if (($address[0] == '<') && (substr($address, -1) == '>')) { + $address = substr($address, 1, -1); + } + + return $address; + } + + /** + * Explodes an RFC string, ignoring a delimiter if preceded by a "\" + * character, or if the delimiter is inside single or double quotes. + * + * @param string $string The RFC compliant string. + * @param string $delimiters A string containing valid delimiters. + * Defaults to ','. + * + * @return array The exploded string in an array. + */ + static public function explode($string, $delimiters = ',') + { + if (!strlen($string)) { + return array($string); + } + + $emails = array(); + $pos = 0; + $in_group = $in_quote = false; + + for ($i = 0, $iMax = strlen($string); $i < $iMax; ++$i) { + $char = $string[$i]; + if ($char == '"') { + if (!$i || ($prev !== '\\')) { + $in_quote = !$in_quote; + } + } elseif ($in_group) { + if ($char == ';') { + $emails[] = substr($string, $pos, $i - $pos + 1); + $pos = $i + 1; + $in_group = false; + } + } elseif (!$in_quote) { + if ($char == ':') { + $in_group = true; + } elseif ((strpos($delimiters, $char) !== false) && + (!$i || ($prev !== '\\'))) { + $emails[] = $i ? substr($string, $pos, $i - $pos) : ''; + $pos = $i + 1; + } + } + $prev = $char; + } + + if ($pos != $i) { + /* The string ended without a delimiter. */ + $emails[] = substr($string, $pos, $i - $pos); + } + + return $emails; + } + + /** + * Takes an address object array and formats it as a string. + * + * Object array format for the address "John Doe " + * is: + *
+     * 'personal' = Personal name ("John Doe")
+     * 'mailbox' = The user's mailbox ("john_doe")
+     * 'host' = The host the mailbox is on ("example.com")
+     * 
+ * + * @param array $ob The address object to be turned into a string. + * @param mixed $filter A user@example.com style bare address to ignore. + * Either single string or an array of strings. If + * the address matches $filter, an empty string will + * be returned. + * + * @return string The formatted address. + */ + static public function addrObject2String($ob, $filter = '') + { + /* If the personal name is set, decode it. */ + $ob['personal'] = isset($ob['personal']) + ? Horde_MIME::decode($ob['personal']) + : ''; + + /* If both the mailbox and the host are empty, return an empty string. + * If we just let this case fall through, the call to writeAddress() + * will end up return just a '@', which is undesirable. */ + if (empty($ob['mailbox']) && empty($ob['host'])) { + return ''; + } + + /* Make sure these two variables have some sort of value. */ + if (!isset($ob['mailbox'])) { + $ob['mailbox'] = ''; + } elseif ($ob['mailbox'] == 'undisclosed-recipients') { + return ''; + } + if (!isset($ob['host'])) { + $ob['host'] = ''; + } + + /* Filter out unwanted addresses based on the $filter string. */ + if ($filter) { + if (!is_array($filter)) { + $filter = array($filter); + } + foreach ($filter as $f) { + if (strcasecmp($f, $ob['mailbox'] . '@' . $ob['host']) == 0) { + return ''; + } + } + } + + /* Return the formatted email address. */ + return self::writeAddress($ob['mailbox'], $ob['host'], $ob['personal']); + } + + /** + * Takes an array of address object arrays and passes each of them through + * addrObject2String(). + * + * @param array $addresses The array of address objects. + * @param mixed $filter A user@example.com style bare address to + * ignore. If any address matches $filter, it + * will not be included in the final string. + * + * @return string All of the addresses in a comma-delimited string. + * Returns the empty string on error/no addresses found. + */ + static public function addrArray2String($addresses, $filter = '') + { + if (!is_array($addresses)) { + return ''; + } + + $addrList = array(); + + foreach ($addresses as $addr) { + $val = self::addrObject2String($addr, $filter); + if (!empty($val)) { + $addrList[String::lower(self::bareAddress($val))] = $val; + } + } + + return implode(', ', $addrList); + } + + /** + * Return the list of addresses for a header object. + * + * @param array $obs An array of header objects. + * + * @return array An array of address information. Array elements: + *
+     * 'address' - (string) Full address
+     * 'display' - (string) A displayable version of the address
+     * 'groupname' - (string) The group name.
+     * 'host' - (string) Hostname
+     * 'inner' - (string) Trimmed, bare address
+     * 'personal' - (string) Personal string
+     * 
+ */ + static public function getAddressesFromObject($obs) + { + $ret = array(); + + if (!is_array($obs) || empty($obs)) { + return $ret; + } + + foreach ($obs as $ob) { + if (isset($ob['groupname'])) { + $ret[] = array( + 'addresses' => self::getAddressesFromObject($ob['addresses']), + 'groupname' => $ob['groupname'] + ); + continue; + } + + $ob = array_merge(array( + 'host' => '', + 'mailbox' => '', + 'personal' => '' + ), $ob); + + /* Ensure we're working with initialized values. */ + if (!empty($ob['personal'])) { + $ob['personal'] = stripslashes(trim(Horde_MIME::decode($ob['personal']), '"')); + } + + $inner = self::writeAddress($ob['mailbox'], $ob['host']); + + /* Generate the new object. */ + $ret[] = array( + 'address' => self::addrObject2String($ob), + 'display' => (empty($ob['personal']) ? '' : $ob['personal'] . ' <') . $inner . (empty($ob['personal']) ? '' : '>'), + 'host' => $ob['host'], + 'inner' => $inner, + 'personal' => $ob['personal'] + ); + } + + return $ret; + } + + /** + * Returns the bare address. + * + * @param string $address The address string. + * @param string $defserver The default domain to append to mailboxes. + * @param boolean $multiple Should we return multiple results? + * + * @return mixed If $multiple is false, returns the mailbox@host e-mail + * address. If $multiple is true, returns an array of + * these addresses. + */ + static public function bareAddress($address, $defserver = null, + $multiple = false) + { + $addressList = array(); + + $from = self::parseAddressList($address, array('defserver' => $defserver)); + if (is_a($from, 'PEAR_Error')) { + return $multiple ? array() : ''; + } + + foreach ($from as $entry) { + if (!empty($entry['mailbox'])) { + $addressList[] = $entry['mailbox'] . (isset($entry['host']) ? '@' . $entry['host'] : ''); + } + } + + return $multiple ? $addressList : array_pop($addressList); + } + + /** + * Parses a list of email addresses into its parts. Handles distribution + * lists. + * + * @param string $address The address string. + * @param array $options Additional options: + *
+     * 'defserver' - (string) The default domain to append to mailboxes.
+     *               DEFAULT: No domain appended.
+     * 'nestgroups' - (boolean) Nest the groups? (Will appear under the
+     *                'groupname' key)
+     *                DEFAULT: No.
+     * 'reterror' - (boolean) Return a PEAR_Error object on error?
+     *              DEFAULT: Returns an empty array on error.
+     * 'validate' - (boolean) Validate the address(es)?
+     *              DEFAULT: No.
+     * 
+ * + * @return mixed If 'reterror' is true, returns a PEAR_Error object on + * error. Otherwise, a list of arrays with the possible + * keys: 'mailbox', 'host', 'personal', 'adl', 'groupname', + * and 'comment'. + */ + static public function parseAddressList($address, $options = array()) + { + if (preg_match('/undisclosed-recipients:\s*;/i', trim($address))) { + return array(); + } + + $options = array_merge(array( + 'defserver' => null, + 'nestgroups' => false, + 'reterror' => false, + 'validate' => false + ), $options); + + static $parser; + if (!isset($parser)) { + require_once 'Mail/RFC822.php'; + $parser = new Mail_RFC822(); + } + + $ret = $parser->parseAddressList($address, $options['defserver'], $options['nestgroups'], $options['validate']); + if (is_a($ret, 'PEAR_Error')) { + return empty($options['reterror']) ? array() : $ret; + } + + /* Convert objects to arrays. */ + foreach (array_keys($ret) as $key) { + $ret[$key] = (array) $ret[$key]; + } + + return $ret; + } + + /** + * Quotes and escapes the given string if necessary using rules contained + * in RFC 2822 [3.2.5]. + * + * @param string $str The string to be quoted and escaped. + * @param string $type Either 'address' or 'personal'. + * + * @return string The correctly quoted and escaped string. + */ + static public function encode($str, $type = 'address') + { + // Excluded (in ASCII): 0-8, 10-31, 34, 40-41, 44, 58-60, 62, 64, + // 91-93, 127 + $filter = "\0\1\2\3\4\5\6\7\10\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\"(),:;<>@[\\]\177"; + + switch ($type) { + case 'address': + // RFC 2822 [3.4.1]: (HTAB, SPACE) not allowed in address + $filter .= "\11\40"; + break; + + case 'personal': + // RFC 2822 [3.4]: Period not allowed in display name + $filter .= '.'; + break; + } + + // Strip double quotes if they are around the string already. + // If quoted, we know that the contents are already escaped, so + // unescape now. + $str = trim($str); + if ($str && ($str[0] == '"') && (substr($str, -1) == '"')) { + $str = stripslashes(substr($str, 1, -1)); + } + + return (strcspn($str, $filter) != strlen($str)) + ? '"' . addcslashes($str, '\\"') . '"' + : $str; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Headers.php b/framework/Mime/lib/Horde/Mime/Headers.php new file mode 100644 index 000000000..164f7de10 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Headers.php @@ -0,0 +1,543 @@ + + * @package Horde_MIME + */ +class Horde_MIME_Headers +{ + /** + * The internal headers array. + * + * @var array + */ + protected $_headers = array(); + + /** + * The sequence to use as EOL for the headers. + * The default is currently to output the EOL sequence internally as + * just "\n" instead of the canonical "\r\n" required in RFC 822 & 2045. + * To be RFC complaint, the full EOL combination should be used + * when sending a message. + * + * @var string + */ + protected $_eol = "\n"; + + /** + * The User-Agent string to use. + * + * @var string + */ + protected $_agent = null; + + /** + * Returns the internal header array in array format. + * + * @param array $options Optional parameters: + *
+     * 'charset' => (string) Encodes the headers using this charset.
+     *              DEFAULT: No encoding.
+     * 'defserver' => (string) TODO
+     *              DEFAULT: NO
+     * 'nowrap' => (integer) Don't wrap the headers.
+     *             DEFAULT: Headers are wrapped.
+     * 
+ * + * @return array The headers in array format. + */ + public function toArray($options = array()) + { + $ret = array(); + $address_keys = empty($options['charset']) + ? array() + : $this->addressFields(); + + foreach ($this->_headers as $header => $ob) { + $val = is_array($ob['value']) ? $ob['value'] : array($ob['value']); + + foreach (array_keys($val) as $key) { + if (!empty($address_keys)) { + if (in_array($header, $address_keys)) { + $text = Horde_MIME::encodeAddress($val[$key], $charset, empty($options['defserver']) ? null : $options['defserver']); + if (is_a($text, 'PEAR_Error')) { + $text = $val[$key]; + } + } else { + $text = Horde_MIME::encode($val[$key], $options['charset']); + } + } else { + $text = $val[$key]; + } + + if (empty($options['nowrap'])) { + $text = $this->wrapHeaders($header, $text); + } + + $val[$key] = $text; + } + + $ret[$ob['header']] = (count($val) == 1) ? reset($val) : $val; + } + + return $ret; + } + + /** + * Returns the internal header array in string format. + * + * @param array $options Optional parameters: + *
+     * 'charset' => (string) Encodes the headers using this charset.
+     *              DEFAULT: No encoding.
+     * 'defserver' => (string) TODO
+     *              DEFAULT: NO
+     * 'nowrap' => (integer) Don't wrap the headers.
+     *             DEFAULT: Headers are wrapped.
+     * 
+ * + * @return string The headers in string format. + */ + public function toString($options = array()) + { + $text = ''; + + foreach ($this->toArray($options) as $key => $val) { + if (!is_array($val)) { + $val = array($val); + } + foreach ($val as $entry) { + $text .= $key . ': ' . $entry . $this->_eol; + } + } + + return $text . $this->_eol; + } + + /** + * Generate the 'Received' header for the Web browser->Horde hop + * (attempts to conform to guidelines in RFC 5321 [4.4]). + */ + public function addReceivedHeader() + { + $old_error = error_reporting(0); + if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + /* This indicates the user is connecting through a proxy. */ + $remote_path = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); + $remote_addr = $remote_path[0]; + $remote = gethostbyaddr($remote_addr); + } else { + $remote_addr = $_SERVER['REMOTE_ADDR']; + $remote = empty($_SERVER['REMOTE_HOST']) + ? gethostbyaddr($remote_addr) + : $_SERVER['REMOTE_HOST']; + } + error_reporting($old_error); + + if (!empty($_SERVER['REMOTE_IDENT'])) { + $remote_ident = $_SERVER['REMOTE_IDENT'] . '@' . $remote . ' '; + } elseif ($remote != $_SERVER['REMOTE_ADDR']) { + $remote_ident = $remote . ' '; + } else { + $remote_ident = ''; + } + + if (!empty($GLOBALS['conf']['server']['name'])) { + $server_name = $GLOBALS['conf']['server']['name']; + } elseif (!empty($_SERVER['SERVER_NAME'])) { + $server_name = $_SERVER['SERVER_NAME']; + } elseif (!empty($_SERVER['HTTP_HOST'])) { + $server_name = $_SERVER['HTTP_HOST']; + } else { + $server_name = 'unknown'; + } + + $received = 'from ' . $remote . ' (' . $remote_ident . + '[' . $remote_addr . ']) ' . + 'by ' . $server_name . ' (Horde Framework) with HTTP; ' . + date('r'); + + $this->addHeader('Received', $received); + } + + /** + * Generate the 'Message-ID' header. + */ + public function addMessageIdHeader() + { + require_once dirname(__FILE__) . '/../MIME.php'; + $this->addHeader('Message-ID', Horde_MIME::generateMessageID()); + } + + /** + * Generate the 'Resent' headers (conforms to guidelines in + * RFC 2822 [3.6.6]). + * + * @param string $from The address to use for 'Resent-From'. + * @param string $to The address to use for 'Resent-To'. + */ + public function addResentHeaders($from, $to) + { + require_once dirname(__FILE__) . '/../MIME.php'; + + /* We don't set Resent-Sender, Resent-Cc, or Resent-Bcc. */ + $this->addHeader('Resent-Date', date('r')); + $this->addHeader('Resent-From', $from); + $this->addHeader('Resent-To', $to); + $this->addHeader('Resent-Message-ID', Horde_MIME::generateMessageID()); + } + + /** + * Generate the user agent description header. + */ + public function addUserAgentHeader() + { + $this->addHeader('User-Agent', $this->getUserAgent()); + } + + /** + * Returns the user agent description header. + * + * @return string The user agent header. + */ + public function getUserAgent() + { + if (is_null($this->_agent)) { + $this->_agent = 'Horde Application Framework 4.0'; + } + return $this->_agent; + } + + /** + * Explicitly sets the User-Agent string. + * + * @param string $agent The User-Agent string to use. + */ + public function setUserAgent($agent) + { + $this->_agent = $agent; + } + + /** + * Add a header to the header array. + * + * @param string $header The header name. + * @param string $value The header value. + * @param boolean $decode MIME decode the value? + */ + public function addHeader($header, $value, $decode = false) + { + require_once 'Horde/String.php'; + + $header = trim($header); + $lcHeader = String::lower($header); + + if (!isset($this->_headers[$lcHeader])) { + $this->_headers[$lcHeader] = array(); + $this->_headers[$lcHeader]['header'] = $header; + } + $ptr = &$this->_headers[$lcHeader]; + + if ($decode) { + require_once dirname(__FILE__) . '/../MIME.php'; + + // Fields defined in RFC 2822 that contain address information + if (in_array($lcHeader, $this->addressFields())) { + $value = Horde_MIME::decodeAddrString($value); + } else { + $value = Horde_MIME::decode($value); + } + } + + if (isset($ptr['value'])) { + if (!is_array($ptr['value'])) { + $ptr['value'] = array($ptr['value']); + } + $ptr['value'][] = $value; + } else { + $ptr['value'] = $value; + } + } + + /** + * Remove a header from the header array. + * + * @param string $header The header name. + */ + public function removeHeader($header) + { + require_once 'Horde/String.php'; + unset($this->_headers[String::lower(trim($header))]); + } + + /** + * Set a value for a particular header ONLY if that header is set. + * + * @param string $header The header name. + * @param string $value The header value. + * @param boolean $decode MIME decode the value? + * + * @return boolean True if value was set. + */ + public function setValue($header, $value, $decode = false) + { + require_once 'Horde/String.php'; + + if (isset($this->_headers[String::lower($header)])) { + $this->addHeader($header, $value, $decode); + return true; + } + + return false; + } + + /** + * Attempts to return the header in the correct case. + * + * @param string $header The header to search for. + * + * @return string The value for the given header. + * If the header is not found, returns null. + */ + public function getString($header) + { + require_once 'Horde/String.php'; + + $lcHeader = String::lower($header); + return (isset($this->_headers[$lcHeader])) + ? $this->_headers[$lcHeader]['header'] + : null; + } + + /** + * Attempt to return the value for a given header. + * The following header fields can only have 1 entry, so if duplicate + * entries exist, the first value will be used: + * * To, From, Cc, Bcc, Date, Sender, Reply-to, Message-ID, In-Reply-To, + * References, Subject (RFC 2822 [3.6]) + * * All List Headers (RFC 2369 [3]) + * + * @param string $header The header to search for. + * + * @return mixed The value for the given header. + * If the header is not found, returns null. + */ + public function getValue($header) + { + require_once 'Horde/String.php'; + + $header = String::lower($header); + + if (isset($this->_headers[$header])) { + return (is_array($this->_headers[$header]['value']) && in_array($header, $this->singleFields(true))) + ? $this->_headers[$header]['value'][0] + : $this->_headers[$header]['value']; + } + + return null; + } + + /** + * Returns the list of RFC defined header fields that contain address + * info. + * + * @return array The list of headers, in lowercase. + */ + public function addressFields() + { + return array( + 'from', 'to', 'cc', 'bcc', 'reply-to', 'resent-to', 'resent-cc', + 'resent-bcc', 'resent-from', 'sender' + ); + } + + /** + * Returns the list of RFC defined header fields that can only contain + * a single value. + * + * @param boolean $list Return list-related headers also? + * + * @return array The list of headers, in lowercase. + */ + public function singleFields($list = true) + { + $single = array( + 'to', 'from', 'cc', 'bcc', 'date', 'sender', 'reply-to', + 'message-id', 'in-reply-to', 'references', 'subject', 'x-priority' + ); + + if ($list) { + $single = array_merge($single, array_keys($this->listHeaders())); + } + + return $single; + } + + /** + * Returns the list of valid mailing list headers. + * + * @return array The list of valid mailing list headers. + */ + public function listHeaders() + { + return array( + /* RFC 2369 */ + 'list-help' => _("List-Help"), + 'list-unsubscribe' => _("List-Unsubscribe"), + 'list-subscribe' => _("List-Subscribe"), + 'list-owner' => _("List-Owner"), + 'list-post' => _("List-Post"), + 'list-archive' => _("List-Archive"), + /* RFC 2919 */ + 'list-id' => _("List-Id") + ); + } + + /** + * Do any mailing list headers exist? + * + * @return boolean True if any mailing list headers exist. + */ + public function listHeadersExist() + { + return (bool) count(array_intersect(array_keys($this->listHeaders()), array_keys($this->_headers))); + } + + /** + * Sets a new string to use for EOLs. + * + * @param string $eol The string to use for EOLs. + */ + public function setEOL($eol) + { + $this->_eol = $eol; + } + + /** + * Get the string to use for EOLs. + * + * @return string The string to use for EOLs. + */ + public function getEOL() + { + return $this->_eol; + } + + /** + * Returns a header from the header object. + * + * @param string $field The header to return as an object. + * + * @return array The object for the field requested. + */ + public function getOb($field) + { + $val = $this->getValue($field); + return is_null($val) + ? array() + : Horde_MIME_Address::parseAddressList($val); + } + + /** + * Adds proper linebreaks to a header string. + * RFC 2822 says headers SHOULD only be 78 characters a line, but also + * says that a header line MUST not be more than 998 characters. + * + * @param string $header The header name. + * @param string $text The text of the header field. + * + * @return string The header value, with linebreaks inserted. + */ + public function wrapHeaders($header, $text) + { + $eol = $this->_eol; + $header_text = rtrim($header) . ': '; + + /* Remove any existing linebreaks. */ + $text = $header_text . preg_replace("/\r?\n\s?/", ' ', rtrim($text)); + + if (!in_array(strtolower($header), array('content-type', 'content-disposition'))) { + /* Wrap the line. */ + $line = wordwrap($text, 75, $eol . ' '); + + /* Make sure there are no empty lines. */ + $line = preg_replace('/' . $eol . ' ' . $eol . ' /', '/' . $eol . ' /', $line); + + return substr($line, strlen($header_text)); + } + + /* Split the line by the RFC parameter separator ';'. */ + $params = preg_split("/\s*;\s*/", $text); + + $line = ''; + $eollength = strlen($eol); + $length = 1000 - $eollength; + $paramcount = count($params); + + reset($params); + while (list($count, $val) = each($params)) { + /* If longer than RFC allows, then simply chop off the excess. */ + $moreparams = (($count + 1) != $paramcount); + $maxlength = $length - (!empty($line) ? 1 : 0) - (($moreparams) ? 1 : 0); + if (strlen($val) > $maxlength) { + $val = substr($val, 0, $maxlength); + + /* If we have an opening quote, add a closing quote after + * chopping the rest of the text. */ + if (strpos($val, '"') !== false) { + $val = substr($val, 0, -1) . '"'; + } + } + + if (!empty($line)) { + $line .= ' '; + } + $line .= $val . (($moreparams) ? ';' : '') . $eol; + } + + return substr($line, strlen($header_text), ($eollength * -1)); + } + + /** + * Builds a Horde_MIME_Headers object from header text. + * This function can be called statically: + * $headers = Horde_MIME_Headers::parseHeaders(). + * + * @param string $text A text string containing the headers. + * + * @return Horde_MIME_Headers A new Horde_MIME_Headers object. + */ + static public function parseHeaders($text) + { + $headers = new Horde_MIME_Headers(); + $currheader = $currtext = null; + + foreach (explode("\n", $text) as $val) { + $val = rtrim($val); + if (empty($val)) { + break; + } + + if (($val[0] == ' ') || ($val[0] == "\t")) { + $currtext .= ' ' . ltrim($val); + } else { + if (!is_null($currheader)) { + $headers->addHeader($currheader, $currtext, true); + } + $pos = strpos($val, ':'); + $currheader = substr($val, 0, $pos); + $currtext = ltrim(substr($val, $pos + 1)); + } + } + $headers->addHeader($currheader, $currtext, true); + + return $headers; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Magic.php b/framework/Mime/lib/Horde/Mime/Magic.php new file mode 100644 index 000000000..ef93b459d --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Magic.php @@ -0,0 +1,260 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME_Magic +{ + /** + * Returns a copy of the MIME extension map. + * + * @return array The MIME extension map. + */ + static protected function _getMimeExtensionMap() + { + static $mime_extension_map; + + if (!isset($mime_extension_map)) { + require dirname(__FILE__) . '/mime.mapping.php'; + } + + return $mime_extension_map; + } + + /** + * Returns a copy of the MIME magic file. + * + * @return array The MIME magic file. + */ + static protected function _getMimeMagicFile() + { + static $mime_magic; + + if (!isset($mime_magic)) { + require dirname(__FILE__) . '/mime.magic.php'; + } + + return $mime_magic; + } + + /** + * Attempt to convert a file extension to a MIME type, based + * on the global Horde and application specific config files. + * + * If we cannot map the file extension to a specific type, then + * we fall back to a custom MIME handler 'x-extension/$ext', which + * can be used as a normal MIME type internally throughout Horde. + * + * @param string $ext The file extension to be mapped to a MIME type. + * + * @return string The MIME type of the file extension. + */ + static public function extToMIME($ext) + { + if (empty($ext)) { + return 'application/octet-stream'; + } + + $ext = String::lower($ext); + $map = self::_getMimeExtensionMap(); + $pos = 0; + + while (!isset($map[$ext])) { + if (($pos = strpos($ext, '.')) === false) { + break; + } + $ext = substr($ext, $pos + 1); + } + + return isset($map[$ext]) + ? $map[$ext] + : 'x-extension/' . $ext; + } + + /** + * Attempt to convert a filename to a MIME type, based on the global Horde + * and application specific config files. + * + * @param string $filename The filename to be mapped to a MIME type. + * @param boolean $unknown How should unknown extensions be handled? If + * true, will return 'x-extension/*' types. If + * false, will return 'application/octet-stream'. + * + * @return string The MIME type of the filename. + */ + static public function filenameToMIME($filename, $unknown = true) + { + $pos = strlen($filename) + 1; + $type = ''; + + $map = self::_getMimeExtensionMap(); + for ($i = 0; $i <= $map['__MAXPERIOD__']; ++$i) { + $pos = strrpos(substr($filename, 0, $pos - 1), '.') + 1; + if ($pos === false) { + break; + } + } + $type = self::extToMIME(substr($filename, $pos)); + + return (empty($type) || (!$unknown && (strpos($type, 'x-extension') !== false))) + ? 'application/octet-stream' + : $type; + } + + /** + * Attempt to convert a MIME type to a file extension, based + * on the global Horde and application specific config files. + * + * If we cannot map the type to a file extension, we return false. + * + * @param string $type The MIME type to be mapped to a file extension. + * + * @return string The file extension of the MIME type. + */ + static public function MIMEToExt($type) + { + if (empty($type)) { + return false; + } + + if (($key = array_search($type, self::_getMimeExtensionMap())) === false) { + list($major, $minor) = explode('/', $type); + if ($major == 'x-extension') { + return $minor; + } + if (strpos($minor, 'x-') === 0) { + return substr($minor, 2); + } + return false; + } + + return $key; + } + + /** + * Uses variants of the UNIX "file" command to attempt to determine the + * MIME type of an unknown file. + * + * @param string $path The path to the file to analyze. + * @param string $magic_db Path to the mime magic database. + * + * @return string The MIME type of the file. Returns false if the file + * type isn't recognized or an error happened. + */ + static public function analyzeFile($path, $magic_db = null) + { + /* If the PHP Mimetype extension is available, use that. */ + if (Util::extensionExists('fileinfo')) { + $res = empty($magic_db) + ? @finfo_open(FILEINFO_MIME) + : @finfo_open(FILEINFO_MIME, $magic_db); + + if ($res) { + $type = finfo_file($res, $path); + finfo_close($res); + + /* Remove any additional information. */ + foreach (array(';', ',', '\\0') as $separator) { + if (($pos = strpos($type, $separator)) !== false) { + $type = rtrim(substr($type, 0, $pos)); + } + } + + if (preg_match('|^[a-z0-9]+/[.-a-z0-9]+$|i', $type)) { + return $type; + } + } + } + + if (Util::extensionExists('mime_magic')) { + return trim(mime_content_type($path)); + } + + /* Use a built-in magic file. */ + $mime_magic = self::_getMimeMagicFile(); + if (!($fp = @fopen($path, 'rb'))) { + return false; + } + + reset($mime_magic); + while (list($offset, $odata) = each($mime_magic)) { + reset($odata); + while (list($length, $ldata) = each($odata)) { + @fseek($fp, $offset, SEEK_SET); + $lookup = @fread($fp, $length); + if (!empty($ldata[$lookup])) { + fclose($fp); + return $ldata[$lookup]; + } + } + } + fclose($fp); + + return false; + } + + /** + * Uses variants of the UNIX "file" command to attempt to determine the + * MIME type of an unknown byte stream. + * + * @param string $data The file data to analyze. + * @param string $magic_db Path to the mime magic database. + * + * @return string The MIME type of the file. Returns false if the file + * type isn't recognized or an error happened. + */ + static public function analyzeData($data, $magic_db = null) + { + /* If the PHP Mimetype extension is available, use that. */ + if (Util::extensionExists('fileinfo')) { + $res = empty($magic_db) + ? @finfo_open(FILEINFO_MIME) + : @finfo_open(FILEINFO_MIME, $magic_db); + + if (!$res) { + return false; + } + + $type = finfo_buffer($res, $data); + finfo_close($res); + + /* Remove any additional information. */ + if (($pos = strpos($type, ';')) !== false) { + $type = rtrim(substr($type, 0, $pos)); + } + + if (($pos = strpos($type, ',')) !== false) { + $type = rtrim(substr($type, 0, $pos)); + } + + return $type; + } + + /* Use a built-in magic file. */ + $mime_magic = self::_getMimeMagicFile(); + reset($mime_magic); + while (list($offset, $odate) = each($mime_magic)) { + reset($odata); + while (list($length, $ldata) = each($odata)) { + $lookup = substr($data, $offset, $length); + if (!empty($ldata[$lookup])) { + return $ldata[$lookup]; + } + } + } + + return false; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Mail.php b/framework/Mime/lib/Horde/Mime/Mail.php new file mode 100644 index 000000000..289fc9a6c --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Mail.php @@ -0,0 +1,507 @@ + + * @package Horde_MIME + */ +class Horde_MIME_Mail +{ + /** + * The message headers. + * + * @var Horde_MIME_Headers + */ + protected $_headers; + + /** + * The main body part. + * + * @var Horde_MIME_Part + */ + protected $_body; + + /** + * The main HTML body part. + * + * @var Horde_MIME_Part + */ + protected $_htmlBody; + + /** + * The message recipients. + * + * @var array + */ + protected $_recipients = array(); + + /** + * All MIME parts except the main body part. + * + * @var array + */ + protected $_parts = array(); + + /** + * The Mail driver name. + * + * @link http://pear.php.net/Mail + * @var string + */ + protected $_mailer_driver = 'smtp'; + + /** + * The Mail driver parameters. + * + * @link http://pear.php.net/Mail + * @var array + */ + protected $_mailer_params = array(); + + /** + * Constructor. + * + * @param string $subject The message subject. + * @param string $body The message body. + * @param string $to The message recipient(s). + * @param string $from The message sender. + * @param string $charset The character set of the message. + */ + function __construct($subject = null, $body = null, $to = null, + $from = null, $charset = 'iso-8859-1') + { + /* Set SERVER_NAME. */ + if (!isset($_SERVER['SERVER_NAME'])) { + $_SERVER['SERVER_NAME'] = php_uname('n'); + } + + $this->_headers = new Horde_MIME_Headers(); + + if ($subject) { + $this->addHeader('Subject', $subject, $charset); + } + if ($to) { + $this->addHeader('To', $to, $charset); + } + if ($from) { + $this->addHeader('From', $from, $charset); + } + if ($body) { + $this->setBody($body, $charset); + } + } + + /** + * Adds several message headers at once. + * + * @param array $header Hash with header names as keys and header + * contents as values. + * @param string $charset The header value's charset. + */ + public function addHeaders($headers = array(), $charset = 'iso-8859-1') + { + foreach ($headers as $header => $value) { + if (is_a($added = $this->addHeader($header, $value, $charset), 'PEAR_Error')) { + return $added; + } + } + } + + /** + * Adds a message header. + * + * @param string $header The header name. + * @param string $value The header value. + * @param string $charset The header value's charset. + * @param boolean $overwrite If true, an existing header of the same name + * is being overwritten; if false, multiple + * headers are added; if null, the correct + * behaviour is automatically chosen depending + * on the header name. + */ + public function addHeader($header, $value, $charset = 'iso-8859-1', + $overwrite = null) + { + $lc_header = String::lower($header); + + /* Only encode value if charset is explicitly specified, otherwise + * the message's charset will be used when building the message. */ + if (!empty($charset)) { + if (in_array($lc_header, $this->_headers->addressFields())) { + $value = Horde_MIME::encodeAddress($value, $charset); + } else { + $value = Horde_MIME::encode($value, $charset); + } + } + + if (is_null($overwrite)) { + if (in_array($lc_header, $this->_headers->singleFields(true))) { + $overwrite = true; + } + } + + if ($overwrite) { + $this->_headers->removeHeader($header); + } + + if ($lc_header !== 'bcc') { + $this->_headers->addHeader($header, $value); + } + + if (in_array($lc_header, array('to', 'cc', 'bcc'))) { + return $this->addRecipients($value); + } + } + + /** + * Removes a message header. + * + * @param string $header The header name. + */ + public function removeHeader($header) + { + $value = $this->_headers->getValue($header); + $this->_headers->removeHeader($header); + if (in_array(String::lower($header), array('to', 'cc', 'bcc'))) { + $this->removeRecipients($value); + } + } + + /** + * Sets the message body text. + * + * @param string $body The message content. + * @param string $charset The character set of the message. + * @param boolean|integer $wrap If true, wrap the message at column 76; + * If an integer wrap the message at that + * column. Don't use wrapping if sending + * flowed messages. + */ + public function setBody($body, $charset = 'iso-8859-1', $wrap = false) + { + if ($wrap) { + $body = String::wrap($body, $wrap === true ? 76 : $wrap, "\n"); + } + $this->_body = new Horde_MIME_Part('text/plain', $body, $charset); + } + + /** + * 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 = 'iso-8859-1', + $alternative = true) + { + $this->_htmlBody = new Horde_MIME_Part('text/html', $body, $charset); + if ($alternative) { + require_once 'Horde/Text/Filter.php'; + $body = Text_Filter::filter($body, 'html2text', array('wrap' => false)); + $this->_body = new Horde_MIME_Part('text/plain', $body, $charset); + } + } + + /** + * Adds a message part. + * + * @param string $mime_type The content type of the part. + * @param string $content The content of the part. + * @param string $charset The character set of the part. + * @param string $disposition The content disposition of the part. + * + * @return integer The part number. + */ + public function addPart($mime_type, $content, $charset = 'us-ascii', + $disposition = null) + { + $part = new Horde_MIME_Part($mime_type, $content, $charset, $disposition); + $part->transferEncodeContents(); + $this->_parts[] = $part; + return count($this->_parts) - 1; + } + + /** + * Adds a MIME message part. + * + * @param Horde_MIME_Part $part A Horde_MIME_Part object. + * + * @return integer The part number. + */ + public function addMIMEPart($part) + { + $part->transferEncodeContents(); + $this->_parts[] = $part; + return count($this->_parts) - 1; + } + + /** + * Adds an attachment. + * + * @param string $file The path to the file. + * @param string $name The file name to use for the attachment. + * @param string $type The content type of the file. + * @param string $charset The character set of the part (only relevant for + * text parts. + * + * @return integer The part number. + */ + public function addAttachment($file, $name = null, $type = null, + $charset = 'us-ascii') + { + if (empty($name)) { + $name = basename($file); + } + if (empty($type)) { + require_once dirname(__FILE__) . '/Magic.php'; + $type = Horde_MIME_Magic::filenameToMIME($file, false); + } + + $part = new Horde_MIME_Part($type, file_get_contents($file), $charset, 'attachment'); + $part->setName($name); + $part->transferEncodeContents(); + $this->_parts[] = $part; + + return count($this->_parts) - 1; + } + + /** + * Removes a message part. + * + * @param integer $part The part number. + */ + public function removePart($part) + { + if (isset($this->_parts[$part])) { + unset($this->_parts[$part]); + } + } + + /** + * Adds message recipients. + * + * Recipients specified by To:, Cc:, or Bcc: headers are added + * automatically. + * + * @param string|array List of recipients, either as a comma separated + * list or as an array of email addresses. + */ + public function addRecipients($recipients) + { + $recipients = $this->_buildRecipients($recipients); + if (is_a($recipients, 'PEAR_Error')) { + return $recipients; + } + $this->_recipients = array_merge($this->_recipients, $recipients); + } + + /** + * Removes message recipients. + * + * @param string|array List of recipients, either as a comma separated + * list or as an array of email addresses. + */ + public function removeRecipients($recipients) + { + $recipients = $this->_buildRecipients($recipients); + if (is_a($recipients, 'PEAR_Error')) { + return $recipients; + } + $this->_recipients = array_diff($this->_recipients, $recipients); + } + + /** + * Removes all message recipients. + */ + public function clearRecipients() + { + $this->_recipients = array(); + } + + /** + * Builds a recipients list. + * + * @param string|array List of recipients, either as a comma separated + * list or as an array of email addresses. + * + * @return array Normalized list of recipients or PEAR_Error on failure. + */ + protected function _buildRecipients($recipients) + { + if (is_string($recipients)) { + $recipients = Horde_MIME::explode($recipients, ','); + } + $recipients = array_filter(array_map('trim', $recipients)); + + $addrlist = array(); + foreach ($recipients as $email) { + if (!empty($email)) { + $unique = Horde_MIME::bareAddress($email); + if ($unique) { + $addrlist[$unique] = $email; + } else { + $addrlist[$email] = $email; + } + } + } + + foreach (Horde_MIME::bareAddress(implode(', ', $addrlist), null, true) as $val) { + if (Horde_MIME::is8bit($val)) { + return PEAR::raiseError(sprintf(_("Invalid character in e-mail address: %s."), $val)); + } + } + + return $addrlist; + } + + /** + * Sends this message. + * + * For the possible Mail drivers and parameters see the PEAR Mail + * documentation. + * @link http://pear.php.net/Mail + * + * @param string $driver The Mail driver to use. + * @param array $params Any parameters necessary for the Mail driver. + * @param boolean $resend If true, the message id and date are re-used; + * If false, they will be updated. + * @param boolean $flowed Send message in flowed text format. @since + * Horde 3.2.1 + * + * @return mixed True on success, PEAR_Error on error. + */ + public function send($driver = null, $params = array(), $resend = false, + $flowed = true) + { + /* Add mandatory headers if missing. */ + if (!$resend || !$this->_headers->getString('Message-ID')) { + $this->_headers->addMessageIdHeader(); + } + if (!$this->_headers->getString('User-Agent')) { + $this->_headers->addAgentHeader(); + } + if (!$resend || !$this->_headers->getString('Date')) { + $this->_headers->addHeader('Date', date('r')); + } + + /* Send in flowed format. */ + if ($flowed && !empty($this->_body)) { + require_once 'Text/Flowed.php'; + $flowed = new Text_Flowed($this->_body->getContents(), + $this->_body->getCharset()); + $flowed->setDelSp(true); + $this->_body->setContentTypeParameter('DelSp', 'Yes'); + $this->_body->setContents($flowed->toFlowed()); + $this->_body->setContentTypeParameter('format', 'flowed'); + } + + /* Build mime message. */ + $mime = new Horde_MIME_Message(); + if (!empty($this->_body) && !empty($this->_htmlBody)) { + $basepart = new Horde_MIME_Part('multipart/alternative'); + $this->_body->setDescription(_("Plaintext Version of Message")); + $basepart->addPart($this->_body); + $this->_htmlBody->setDescription(_("HTML Version of Message")); + $basepart->addPart($this->_htmlBody); + $mime->addPart($basepart); + } elseif (!empty($this->_htmlBody)) { + $mime->addPart($this->_htmlBody); + } elseif (!empty($this->_body)) { + $mime->addPart($this->_body); + } + foreach ($this->_parts as $mime_part) { + $mime->addPart($mime_part); + } + + /* Check mailer configuration. */ + if (!empty($driver)) { + $this->_mailer_driver = $driver; + } + if (!empty($params)) { + $this->_mailer_params = $params; + } + + /* Send message. */ + return $mime->send(implode(', ', $this->_recipients), $this->_headers, + $this->_mailer_driver, $this->_mailer_params); + } + + /** + * Return error string corresponding to a sendmail error code. + * + * @param integer $code The error code. + * + * @return string The error string, or null if the code is unknown. + */ + static public function sendmailError($code) + { + switch ($code) { + case 64: // EX_USAGE + return 'sendmail: ' . _("command line usage error") . ' (64)'; + + case 65: // EX_DATAERR + return 'sendmail: ' . _("data format error") . ' (65)'; + + case 66: // EX_NOINPUT + return 'sendmail: ' . _("cannot open input") . ' (66)'; + + case 67: // EX_NOUSER + return 'sendmail: ' . _("addressee unknown") . ' (67)'; + + case 68: // EX_NOHOST + return 'sendmail: ' . _("host name unknown") . ' (68)'; + + case 69: // EX_UNAVAILABLE + return 'sendmail: ' . _("service unavailable") . ' (69)'; + + case 70: // EX_SOFTWARE + return 'sendmail: ' . _("internal software error") . ' (70)'; + + case 71: // EX_OSERR + return 'sendmail: ' . _("system error") . ' (71)'; + + case 72: // EX_OSFILE + return 'sendmail: ' . _("critical system file missing") . ' (72)'; + + case 73: // EX_CANTCREAT + return 'sendmail: ' . _("cannot create output file") . ' (73)'; + + case 74: // EX_IOERR + return 'sendmail: ' . _("input/output error") . ' (74)'; + + case 75: // EX_TEMPFAIL + return 'sendmail: ' . _("temporary failure") . ' (75)'; + + case 76: // EX_PROTOCOL + return 'sendmail: ' . _("remote error in protocol") . ' (76)'; + + case 77: // EX_NOPERM + return 'sendmail: ' . _("permission denied") . ' (77)'; + + case 78: // EX_CONFIG + return 'sendmail: ' . _("configuration error") . ' (78)'; + + case 79: // EX_NOTFOUND + return 'sendmail: ' . _("entry not found") . ' (79)'; + } + + return null; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Mdn.php b/framework/Mime/lib/Horde/Mime/Mdn.php new file mode 100644 index 000000000..d567c88ac --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Mdn.php @@ -0,0 +1,238 @@ + + * @package Horde_MIME + */ +class Horde_MIME_MDN +{ + /** + * The Horde_MIME_Headers object. + * + * @var Horde_MIME_Headers + */ + protected $_headers; + + /** + * The text of the original message. + * + * @var string + */ + protected $_msgtext = false; + + /** + * Constructor. + * + * @param Horde_MIME_Headers $mime_headers A Horde_MIME_Headers object. + */ + function __construct($headers = null) + { + $this->_headers = $headers; + } + + /** + * Returns the address to return the MDN to. + * + * @return string The address to send the MDN to. Returns null if no + * MDN is requested. + */ + public function getMDNReturnAddr() + { + /* RFC 3798 [2.1] requires the Disposition-Notificaion-To header + * for an MDN to be created. */ + return $this->_headers->getValue('Disposition-Notification-To'); + } + + /** + * Is user input required to send the MDN? + * Explicit confirmation is needed in some cases to prevent mail loops + * and the use of MDNs for mail bombing. + * + * @return boolean Is explicit user input required to send the MDN? + */ + public function userConfirmationNeeded() + { + $return_path = $this->_headers->getValue('Return-Path'); + + /* RFC 3798 [2.1]: Explicit confirmation is needed if there is no + * Return-Path in the header. Also, "if the message contains more + * than one Return-Path header, the implementation may [] treat the + * situation as a failure of the comparison." */ + if (empty($return_path) || is_array($return_path)) { + return true; + } + + require_once dirname(__FILE__) . '/Address.php'; + + /* RFC 3798 [2.1]: Explicit confirmation is needed if there is more + * than one distinct address in the Disposition-Notification-To + * header. */ + $addr_arr = Horde_MIME_Address::parseAddressList($this->getMDNReturnAddr()); + if (count($addr_arr) > 1) { + return true; + } + + /* RFC 3798 [2.1] states that "MDNs SHOULD NOT be sent automatically + * if the address in the Disposition-Notification-To header differs + * from the address in the Return-Path header." This comparison is + * case-sensitive for the mailbox part and case-insensitive for the + * host part. */ + $ret_arr = Horde_MIME_Address::parseAddressList($return_path); + return ($addr_arr[0]['mailbox'] == $ret_arr[0]['mailbox']) && + (String::lower($addr_arr[0]['host']) == String::lower($ret_arr[0]['host'])); + } + + /** + * When generating the MDN, should we return the enitre text of the + * original message? The default is no - we only return the headers of + * the original message. If the text is passed in via this method, we + * will return the entire message. + * + * @param string $text The text of the original message. + */ + public function originalMessageText($text) + { + $this->_msgtext = $text; + } + + /** + * Generate the MDN according to the specifications listed in RFC + * 3798 [3]. + * + * @param boolean $action Was this MDN type a result of a manual action + * on part of the user? + * @param boolean $sending Was this MDN sent as a result of a manual + * action on part of the user? + * @param string $type The type of action performed by the user. + *
+     * Per RFC 3798 [3.2.6.2] the following types are valid:
+     * =====================================================
+     * 'displayed'
+     * 'deleted'
+     * 
+ * @param array $mod The list of modifications. + *
+     * Per RFC 3798 [3.2.6.3] the following modifications are valid:
+     * =============================================================
+     * 'error'
+     * 
+ * @param array $err If $mod is 'error', the additional information + * to provide. Key is the type of modification, + * value is the text. + * + * @return mixed True on success, PEAR_Error object on error. + */ + public function generate($action, $sending, $type, $mod = array(), + $err = array()) + { + require_once dirname(__FILE__) . '/Headers.php'; + require_once dirname(__FILE__) . '/Message.php'; + require_once 'Horde/Identity.php'; + require_once 'Horde/Text.php'; + + /* Set up some variables we use later. */ + $identity = &Identity::singleton(); + $from_addr = $identity->getDefaultFromAddress(); + + $to = $this->getMDNReturnAddr(); + $ua = $this->_headers->getAgentHeader(); + + $orig_recip = $this->_headers->getValue('Original-Recipient'); + if (!empty($orig_recip) && is_array($orig_recip)) { + $orig_recip = $orig_recip[0]; + } + + $msg_id = $this->_headers->getValue('Message-ID'); + + /* Create the Disposition field now (RFC 3798 [3.2.6]). */ + $dispo = 'Disposition: ' . + (($action) ? 'manual-action' : 'automatic-action') . + '/' . + (($sending) ? 'MDN-sent-manually' : 'MDN-sent-automatically') . + '; ' . + $type; + if (!empty($mod)) { + $dispo .= '/' . implode(', ', $mod); + } + + /* Set up the mail headers. */ + $msg_headers = new Horde_MIME_Headers(); + $msg_headers->addMessageIdHeader(); + $msg_headers->addAgentHeader($ua); + $msg_headers->addHeader('Date', date('r')); + $msg_headers->addHeader('From', $from_addr); + $msg_headers->addHeader('To', $this->getMDNReturnAddr()); + $msg_headers->addHeader('Subject', _("Disposition Notification")); + + /* MDNs are a subtype of 'multipart/report'. */ + $msg = new Horde_MIME_Message(); + $msg->setType('multipart/report'); + $msg->setContentTypeParameter('report-type', 'disposition-notification'); + + $charset = NLS::getCharset(); + + /* The first part is a human readable message. */ + $part_one = new Horde_MIME_Part('text/plain'); + $part_one->setCharset($charset); + if ($type == 'displayed') { + $contents = sprintf(_("The message sent on %s to %s with subject \"%s\" has been displayed.\n\nThis is no guarantee that the message has been read or understood."), $this->_headers->getValue('Date'), $this->_headers->getValue('To'), $this->_headers->getValue('Subject')); + require_once 'Text/Flowed.php'; + $flowed = new Text_Flowed($contents, $charset); + $flowed->setDelSp(true); + $part_one->setContentTypeParameter('format', 'flowed'); + $part_one->setContentTypeParameter('DelSp', 'Yes'); + $part_one->setContents($flowed->toFlowed()); + } + // TODO: Messages for other notification types. + $msg->addPart($part_one); + + /* The second part is a machine-parseable description. */ + $part_two = new Horde_MIME_Part('message/disposition-notification'); + $part_two->setContents('Reporting-UA: ' . $GLOBALS['conf']['server']['name'] . '; ' . $ua . "\n"); + if (!empty($orig_recip)) { + $part_two->appendContents('Original-Recipient: rfc822;' . $orig_recip . "\n"); + } + $part_two->appendContents('Final-Recipient: rfc822;' . $from_addr . "\n"); + if (!empty($msg_id)) { + $part_two->appendContents('Original-Message-ID: rfc822;' . $msg_id . "\n"); + } + $part_two->appendContents($dispo . "\n"); + if (in_array('error', $mod) && isset($err['error'])) { + $part_two->appendContents('Error: ' . $err['error'] . "\n"); + } + $msg->addPart($part_two); + + /* The third part is the text of the original message. RFC 3798 [3] + * allows us to return only a portion of the entire message - this + * is left up to the user. */ + $part_three = new Horde_MIME_Part('message/rfc822'); + $part_three->setContents($this->_headers->toString()); + if (!empty($this->_msgtext)) { + $part_three->appendContents($part_three->getEOL() . $this->_msgtext); + } + $msg->addPart($part_three); + + return $msg->send($to, $msg_headers); + } + + /** + * Add a MDN (read receipt) request headers to the Horde_MIME_Headers:: + * object. + * + * @param Horde_MIME_Headers &$ob The object to add the headers to. + * @param string $to The address the receipt should be + * mailed to. + */ + public function addMDNRequestHeaders(&$ob, $to) + { + /* This is the RFC 3798 way of requesting a receipt. */ + $ob->addHeader('Disposition-Notification-To', $to); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Message.php b/framework/Mime/lib/Horde/Mime/Message.php new file mode 100644 index 000000000..6844080f2 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Message.php @@ -0,0 +1,384 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME_Message extends Horde_MIME_Part +{ + /** + * Create a Horde_MIME_Message object from a Horde_MIME_Part object. + * This function can be called statically via: + * $mime_message = Horde_MIME_Message::convertMIMEPart(); + * + * @todo Is this needed? + * + * @param Horde_MIME_Part $mime_part The Horde_MIME_Part object. + * + * @return Horde_MIME_Message The new Horde_MIME_Message object. + */ + static public function convertMIMEPart($mime_part) + { + if (!$mime_part->getMIMEId()) { + $mime_part->setMIMEId(1); + } + + $mime_message = new Horde_MIME_Message(); + $mime_message->addPart($mime_part); + + return $mime_message; + } + + /** + * Sends this message. + * + * @param string $email The address list to send to. + * @param Horde_MIME_Headers $headers The Horde_MIME_Headers object + * holding this message's headers. + * @param string $driver The Mail:: driver to use. + * @param array $params Any parameters necessary for the + * Mail driver. + * + * @return mixed True on success, PEAR_Error on error. + */ + public function send($email, $headers, $driver = null, $params = array()) + { + if (!isset($driver)) { + $driver = $GLOBALS['conf']['mailer']['type']; + $params = $GLOBALS['conf']['mailer']['params']; + } + + require_once 'Mail.php'; + $mailer = Mail::factory($driver, $params); + + /* Add MIME Headers if they don't already exist. */ + if (!$headers->getValue('MIME-Version')) { + $headers = $this->addMIMEHeaders($headers); + } + $headerArray = $headers->toArray($this->getCharset()); + + /* Does the SMTP backend support 8BITMIME (RFC 1652) or + * BINARYMIME (RFC 3030) extensions? Requires PEAR's Mail package + * version 1.2+ and Net_SMTP version 1.3+. */ + if (($driver == 'smtp') && method_exists($mailer, 'getSMTPObject')) { + $net_smtp = $mailer->getSMTPObject(); + if (!is_a($net_smtp, 'PEAR_Error') && + method_exists($net_smtp, 'getServiceExtensions')) { + $smtp_ext = $net_smtp->getServiceExtensions(); + $message->strict7bit(false); + $encoding = $message->getTransferEncoding(); + if (($encoding == '8bit') && + isset($smtp_ext['8BITMIME'])) { + $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); + } elseif (($encoding == 'binary') && + isset($smtp_ext['BINARYMIME'])) { + $mailer->addServiceExtensionParameter('BODY', 'BINARYMIME'); + } else { + $message->strict7bit(true); + $encoding = $message->getTransferEncoding(); + } + $headers->addHeader('Content-Transfer-Encoding', $encoding); + } + } + + /* Make sure the message has a trailing newline. */ + $msg = $this->toString(); + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + + $result = $mailer->send(Horde_MIME::encodeAddress($email), $headerArray, $msg); + + if (is_a($result, 'PEAR_Error') && ($driver == 'sendmail')) { + $error = Horde_MIME_Mail::sendmailError($result->getCode()); + if (is_null($error)) { + $error = $result; + $userinfo = null; + } else { + $userinfo = $result->toString(); + } + return PEAR::raiseError($error, null, null, null, $userinfo); + } + + return $result; + } + + /** + * Get the list of MIME headers for this part in an array. + * + * @return array The full set of MIME headers. + */ + public function getHeaderArray() + { + /* Per RFC 2045 [4], this MUST appear in the message headers. */ + return parent::header(array('MIME-Version' => '1.0')); + } + + /** + * Parse an array of MIME structure information into a Horde_MIME_Message + * object. + * This function can be called statically via: + * $mime_message = Horde_MIME_Message::parseStructure(); + * + * @param array $structure An array of structure information in the + * following format: + *
+     * MANDATORY:
+     *   'type' - (string) The MIME type
+     *   'subtype' - (string) The MIME subtype
+     *
+     * The array MAY contain the following information:
+     *   'disposition' - (string) The disposition type of the part (e.g.
+     *                   'attachment', 'inline').
+     *   'dparameters' - (array) Attribute/value pairs from the part's
+     *                   Content-Disposition header.
+     *   'language' - (array) A list of body language values.
+     *   'location' - (string) The body content URI.
+     *
+     * Depending on the MIME type of the part, the array will also contain
+     * further information. If labeled as [OPTIONAL], the array MAY
+     * contain this information, but only if 'noext' is false and the
+     * server returned the requested information. Else, the value is not
+     * set.
+     *
+     * multipart/* parts:
+     * ==================
+     * 'parts' - (array) An array of subparts (follows the same format as
+     *           the base structure array).
+     * 'parameters' - [OPTIONAL] (array) Attribute/value pairs from the
+     *                part's Content-Type header.
+     *
+     * All other parts:
+     * ================
+     * 'parameters' - (array) Attribute/value pairs from the part's
+     *                Content-Type header.
+     * 'id' - (string) The part's Content-ID value.
+     * 'description' - (string) The part's Content-Description value.
+     * 'encoding' - (string) The part's Content-Transfer-Encoding value.
+     * 'size' - (integer) - The part's size in bytes.
+     * 'envelope' - [ONLY message/rfc822] (array) See 'envelope' response.
+     * 'structure' - [ONLY message/rfc822] (array) See 'structure'
+     *               response.
+     * 'lines' - [ONLY message/rfc822 and text/*] (integer) The size of
+     *           the body in text lines.
+     * 'md5' - [OPTIONAL] (string) The part's MD5 value.
+     * 
+ * + * @return object A Horde_MIME_Message object. + */ + static public function parseStructure($structure) + { + $ob = self::_parseStructure($structure, true); + $ob->buildMIMEIds(); + return $ob; + } + + /** + * Parse a subpart of a MIME message into a + * Horde_MIME_Message/Horde_MIME_Part object. + * + * @param array $data Structure information in the format described + * in parseStructure(). + * @param boolean $rfc822 Force the part to be treated as a + * message/rfc822 part. + * + * @return mixed Returns either a Horde_MIME_Message or a Horde_MIME_Part + * object, depending on the part's MIME type. + */ + static protected function _parseStructure($data, $rfc822 = false) + { + $type = $data['type'] . '/' . $data['subtype']; + + if ($rfc822 || ($type == 'message/rfc822')) { + $ob = new Horde_MIME_Message(); + } else { + $ob = new Horde_MIME_Part(); + } + + $ob->setType($type); + + if (isset($data['encoding'])) { + $ob->setTransferEncoding($data['encoding']); + } + + if (isset($data['disposition'])) { + $ob->setDisposition($data['disposition']); + if (!empty($data['dparameters'])) { + foreach ($data['dparameters'] as $key => $val) { + $ob->setDispositionParameter($key, $val); + } + } + } + + if (isset($data['size'])) { + $ob->setBytes($data['size']); + } + + if (isset($data['id'])) { + $ob->setContentID($data['id']); + } + + if (!empty($data['parameters'])) { + foreach ($data['parameters'] as $key => $val) { + $ob->setContentTypeParameter($key, $val); + } + } + + /* Set the default character set. */ + if (($data['subtype'] == 'text') && + (String::lower($ob->getCharset()) == 'us-ascii') && + isset($GLOBALS['mime_structure']['default_charset'])) { + /* @todo - switch to using static variable for this. */ + //$ob->setCharset($GLOBALS['mime_structure']['default_charset']); + } + + if (isset($data['description'])) { + $ob->setDescription($data['description']); + } + + /* Set the name. */ + if (!$ob->getName()) { + $ob->setName($ob->getDispositionParameter('filename')); + } + + // @todo Handle language, location, md5, lines, envelope + + /* Add multipart parts. */ + if (!empty($data['parts'])) { + reset($data['parts']); + while (list(,$val) = each($data['parts'])) { + $ob->addPart(self::_parseStructure($val)); + } + } elseif (!empty($data['structure'])) { + $ob->addPart(self::_parseStructure($data['structure'])); + } + + return $ob; + } + + /** + * Attempts to build a Horde_MIME_Message object from message text. + * This function can be called statically via: + * $mime_message = Horde_MIME_Message::parseMessage(); + * + * @param string $text The text of the MIME message. + * + * @return Horde_MIME_Message A Horde_MIME_Message object, or false on + * error. + */ + static public function parseMessage($text) + { + /* Set up the options for the mimeDecode class. */ + $decode_args = array( + 'include_bodies' => true, + 'decode_bodies' => false, + 'decode_headers' => false + ); + + require_once 'Mail/mimeDecode.php'; + $mimeDecode = new Mail_mimeDecode($text, Horde_MIME_Part::EOL); + if (!($ob = $mimeDecode->decode($decode_args))) { + return false; + } + + return self::parseStructure(self::_convertMimeDecodeData($ob)); + } + + /** + * Convert the output from Mail_mimeDecode::decode() into a structure that + * parse() can handle. + * + * @param stdClass $ob The output from Mail_mimeDecode::decode(). + * + * @return array An array of structure information. + */ + static protected function _convertMimeDecodeData($ob) + { + /* Primary content-type. */ + if (isset($ob->ctype_primary)) { + $part = array( + 'type' => strtolower($ob->ctype_primary), + 'subtype' => isset($ob->ctype_secondary) ? strtolower($ob->ctype_secondary) : 'x-unknown' + ); + } else { + $part = array( + 'type' => 'application', + 'subtype' => 'octet-stream' + ); + } + + /* Content transfer encoding. */ + if (isset($ob->headers['content-transfer-encoding'])) { + $part['encoding'] = strtolower($ob->headers['content-transfer-encoding']); + } + + /* Content-type and Disposition parameters. */ + $param_types = array( + 'ctype_parameters' => 'parameters', + 'd_parameters' => 'dparameters' + ); + + foreach ($param_types as $param_key => $param_value) { + if (isset($ob->$param_key)) { + $part[$param_value] = array(); + foreach ($ob->$param_key as $key => $val) { + $part[$param_value][strtolower($key)] = $val; + } + } + } + + /* Content-Description. */ + if (isset($ob->headers['content-description'])) { + $part['description'] = $ob->headers['content-description']; + } + + /* Content-Disposition. */ + if (isset($ob->headers['content-disposition'])) { + $hdr = $ob->headers['content-disposition']; + $pos = strpos($hdr, ';'); + if ($pos !== false) { + $hdr = substr($hdr, 0, $pos); + } + $part['disposition'] = strtolower($hdr); + } + + /* Content-ID. */ + if (isset($ob->headers['content-id'])) { + $part['id'] = $ob->headers['content-id']; + } + + /* Get file size (if 'body' text is set). */ + if (isset($ob->body) && + ($part['type'] != 'message') && + ($part['subtype'] != 'rfc822')) { + /* Mail_mimeDecode puts an extra linebreak at the end of body + * text. */ + $size = strlen(str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $ob->body)) - 2; + $part['size'] = ($size < 0) ? 0 : $size; + } + + /* Process parts also. */ + if (isset($ob->parts)) { + $part['parts'] = array(); + reset($ob->parts); + while (list($key,) = each($ob->parts)) { + $part['parts'][] = self::_convertMimeDecodeData($ob->parts[$key]); + } + } + + return $part; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Part.php b/framework/Mime/lib/Horde/Mime/Part.php new file mode 100644 index 000000000..6af6251b6 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Part.php @@ -0,0 +1,1324 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME_Part +{ + /* The character(s) used internally for EOLs. */ + const EOL = "\n"; + + /* The character string designated by RFC 2045 to designate EOLs in MIME + * messages. */ + const RFC_EOL = "\r\n"; + + /* The default MIME character set. */ + const DEFAULT_CHARSET = 'us-ascii'; + + /* The default MIME disposition. */ + const DEFAULT_DISPOSITION = 'inline'; + + /* The default MIME encoding. */ + const DEFAULT_ENCODING = '7bit'; + + /** + * The type (ex.: text) of this part. + * Per RFC 2045, the default is 'application'. + * + * @var string + */ + protected $_type = 'application'; + + /** + * The subtype (ex.: plain) of this part. + * Per RFC 2045, the default is 'octet-stream'. + * + * @var string + */ + protected $_subtype = 'octet-stream'; + + /** + * The body of the part. + * + * @var string + */ + protected $_contents = ''; + + /** + * The desired transfer encoding of this part. + * + * @var string + */ + protected $_transferEncoding = self::DEFAULT_ENCODING; + + /** + * Should the message be encoded via 7-bit? + * + * @var boolean + */ + protected $_encode7bit = true; + + /** + * The description of this part. + * + * @var string + */ + protected $_description = ''; + + /** + * The disposition of this part (inline or attachment). + * + * @var string + */ + protected $_disposition = self::DEFAULT_DISPOSITION; + + /** + * The disposition parameters of this part. + * + * @var array + */ + protected $_dispParams = array(); + + /** + * The content type parameters of this part. + * + * @var array + */ + protected $_contentTypeParams = array(); + + /** + * The subparts of this part. + * + * @var array + */ + protected $_parts = array(); + + /** + * Information/Statistics on the subpart. + * + * @var array + */ + protected $_information = array(); + + /** + * The list of CIDs for this part. + * + * @var array + */ + protected $_cids = array(); + + /** + * The MIME ID of this part. + * + * @var string + */ + protected $_mimeid = null; + + /** + * The sequence to use as EOL for this part. + * The default is currently to output the EOL sequence internally as + * just "\n" instead of the canonical "\r\n" required in RFC 822 & 2045. + * To be RFC complaint, the full EOL combination should be used + * when sending a message. + * It is not crucial here since the PHP/PEAR mailing functions will handle + * the EOL details. + * + * @var string + */ + protected $_eol = self::EOL; + + /** + * Internal class flags. + * + * @var array + */ + protected $_flags = array(); + + /** + * Unique Horde_MIME_Part boundary string. + * + * @var string + */ + protected $_boundary = null; + + /** + * Default value for this Part's size. + * + * @var integer + */ + protected $_bytes = 0; + + /** + * The content-ID for this part. + * + * @var string + */ + protected $_contentid = null; + + /** + * Do we need to reindex the current part. + * + * @var boolean + */ + protected $_reindex = false; + + /** + * TODO + */ + protected $_headers; + + /** + * Set the content-disposition of this part. + * + * @param string $disposition The content-disposition to set (inline or + * attachment). + */ + public function setDisposition($disposition) + { + $disposition = String::lower($disposition); + + if (in_array($disposition, array('inline', 'attachment'))) { + $this->_disposition = $disposition; + } + } + + /** + * Get the content-disposition of this part. + * + * @return string The part's content-disposition. + */ + public function getDisposition() + { + return $this->_disposition; + } + + /** + * Add a disposition parameter to this part. + * + * @param string $label The disposition parameter label. + * @param string $data The disposition parameter data. + */ + public function setDispositionParameter($label, $data) + { + $this->_dispParams[$label] = Horde_MIME::decode($data); + } + + /** + * Get a disposition parameter from this part. + * + * @param string $label The disposition parameter label. + * + * @return string The data requested. + * Returns null if $label is not set. + */ + public function getDispositionParameter($label) + { + return (isset($this->_dispParams[$label])) + ? $this->_dispParams[$label] + : null; + } + + /** + * Get all parameters from the Content-Disposition header. + * + * @return array An array of all the parameters + * Returns the empty array if no parameters set. + */ + public function getAllDispositionParameters() + { + return $this->_dispParams; + } + + /** + * Set the name of this part. + * + * @param string $name The name to set. + */ + public function setName($name) + { + $this->setContentTypeParameter('name', $name); + } + + /** + * Get the name of this part. + * + * @param boolean $default If the name parameter doesn't exist, should we + * use the default name from the description + * parameter? + * + * @return string The name of the part. + */ + public function getName($default = false) + { + $name = $this->getContentTypeParameter('name'); + + if ($default && empty($name)) { + $name = preg_replace('|\W|', '_', $this->getDescription(false)); + } + + return $name; + } + + /** + * Set the body contents of this part. + * + * @param string $contents The part body. + * @param string $encoding The current encoding of the contents. + */ + public function setContents($contents, $encoding = null) + { + $this->_contents = $contents; + $this->_flags['contentsSet'] = true; + $this->_flags['currentEncoding'] = is_null($encoding) ? $this->getCurrentEncoding() : $encoding; + } + + /** + * Add to the body contents of this part. + * + * @param string $contents The contents to append to the current part + * body. + * @param string $encoding The current encoding of the contents. If not + * specified, will try to auto determine the + * encoding. + */ + public function appendContents($contents, $encoding = null) + { + if (empty($this->_flags['contentsSet'])) { + $this->setContents($contents, $encoding); + } else { + if (!is_null($encoding) && + ($encoding != $this->getCurrentEncoding())) { + $this->setTransferEncoding($encoding); + $this->transferDecodeContents(); + } + $this->setContents($this->_contents . $contents, $encoding); + } + } + + /** + * Clears the body contents of this part. + */ + public function clearContents() + { + $this->_contents = ''; + unset($this->_flags['contentsSet'], $this->_flags['currentEncoding']); + } + + /** + * Return the body of the part. + * + * @return string The raw body of the part. + */ + public function getContents() + { + return $this->_contents; + } + + /** + * Returns the contents in strict RFC 822 & 2045 output - namely, all + * newlines end with the canonical sequence. + * + * @return string The raw body of the part, with EOL.. + */ + public function getCanonicalContents() + { + return $this->replaceEOL($this->_contents, self::RFC_EOL); + } + + /** + * Transfer encode the contents (to the transfer encoding identified via + * getTransferEncoding()) and set as the part's new contents. + */ + public function transferEncodeContents() + { + $contents = $this->transferEncode(); + $encode = $this->_flags['currentEncoding'] = $this->_flags['lastTransferEncode']; + $this->setContents($contents, $encode); + $this->setTransferEncoding($encode); + } + + /** + * Transfer decode the contents and set them as the new contents. + */ + public function transferDecodeContents() + { + $contents = $this->transferDecode(); + $encode = $this->_flags['currentEncoding'] = $this->_flags['lastTransferDecode']; + $this->setTransferEncoding($encode); + + /* Don't set contents if they are empty, because this will do stuff + like reset the internal bytes field, even though we shouldn't do + that (the user has their reasons to set the bytes field to a + non-zero value without putting the contents into this part). */ + if (strlen($contents)) { + $this->setContents($contents, $encode); + } + } + + /** + * Set the MIME type of this part. + * + * @param string $mimetype The MIME type to set (ex.: text/plain). + */ + public function setType($mimetype) + { + /* RFC 2045: Any entity with unrecognized encoding must be treated + as if it has a Content-Type of "application/octet-stream" + regardless of what the Content-Type field actually says. */ + if ($this->_transferEncoding == 'x-unknown') { + return; + } + + list($this->_type, $this->_subtype) = explode('/', String::lower($mimetype)); + + /* Known types. */ + $known = array( + 'text', 'multipart', 'message', 'application', 'audio', 'image', + 'video', 'model' + ); + + if (in_array($this->_type, $known)) { + /* Set the boundary string for 'multipart/*' parts. */ + if ($this->_type == 'multipart') { + if (!$this->getContentTypeParameter('boundary')) { + $this->setContentTypeParameter('boundary', $this->_generateBoundary()); + } + } else { + $this->clearContentTypeParameter('boundary'); + } + } else { + $this->_type = 'x-unknown'; + $this->clearContentTypeParameter('boundary'); + } + } + + /** + * Get the full MIME Content-Type of this part. + * + * @param boolean $charset Append character set information to the end + * of the content type if this is a text/* part? + * + * @return string The mimetype of this part + * (ex.: text/plain; charset=us-ascii). + */ + public function getType($charset = false) + { + if (!isset($this->_type) || !isset($this->_subtype)) { + return false; + } + + $ptype = $this->getPrimaryType(); + $type = $ptype . '/' . $this->getSubType(); + if ($charset && ($ptype == 'text')) { + $type .= '; charset=' . $this->getCharset(); + } + + return $type; + } + + /** + * If the subtype of a MIME part is unrecognized by an application, the + * default type should be used instead (See RFC 2046). This method + * returns the default subtype for a particular primary MIME type. + * + * @return string The default MIME type of this part (ex.: text/plain). + */ + public function getDefaultType() + { + switch ($this->getPrimaryType()) { + case 'text': + /* RFC 2046 (4.1.4): text parts default to text/plain. */ + return 'text/plain'; + + case 'multipart': + /* RFC 2046 (5.1.3): multipart parts default to multipart/mixed. */ + return 'multipart/mixed'; + + default: + /* RFC 2046 (4.2, 4.3, 4.4, 4.5.3, 5.2.4): all others default to + application/octet-stream. */ + return 'application/octet-stream'; + } + } + + /** + * Get the primary type of this part. + * + * @return string The primary MIME type of this part. + */ + public function getPrimaryType() + { + return $this->_type; + } + + /** + * Get the subtype of this part. + * + * @return string The MIME subtype of this part. + */ + public function getSubType() + { + return $this->_subtype; + } + + /** + * Set the character set of this part. + * + * @param string $charset The character set of this part. + */ + public function setCharset($charset) + { + $this->setContentTypeParameter('charset', $charset); + } + + /** + * Get the character set to use for of this part. Returns a charset for + * all types (not just 'text/*') since we use this charset to determine + * how to encode text in MIME headers. + * + * @return string The character set of this part. Returns null if there + * is no character set. + */ + public function getCharset() + { + $charset = $this->getContentTypeParameter('charset'); + return empty($charset) ? null : $charset; + } + + /** + * Set the description of this part. + * + * @param string $description The description of this part. + */ + public function setDescription($description) + { + $this->_description = Horde_MIME::decode($description); + } + + /** + * Get the description of this part. + * + * @param boolean $default If the name parameter doesn't exist, should we + * use the default name from the description + * parameter? + * + * @return string The description of this part. + */ + public function getDescription($default = false) + { + $desc = $this->_description; + + if ($default && empty($desc)) { + $desc = $this->getName(); + } + + return $desc; + } + + /** + * Set the transfer encoding to use for this part. + * + * @param string $encoding The transfer encoding to use. + */ + public function setTransferEncoding($encoding) + { + $known = array('7bit', '8bit', 'binary', 'base64', 'quoted-printable'); + $encoding = String::lower($encoding); + + if (in_array($encoding, $known)) { + $this->_transferEncoding = $encoding; + } else { + /* RFC 2045: Any entity with unrecognized encoding must be treated + as if it has a Content-Type of "application/octet-stream" + regardless of what the Content-Type field actually says. */ + $this->setType('application/octet-stream'); + $this->_transferEncoding = 'x-unknown'; + } + } + + /** + * Add a MIME subpart. + * + * @param Horde_MIME_Part $mime_part Add a subpart to the current object. + */ + public function addPart($mime_part) + { + $this->_parts[] = $mime_part; + $this->_reindex = true; + } + + /** + * Get a list of all MIME subparts. + * + * @return array An array of the Horde_MIME_Part subparts. + */ + public function getParts() + { + return $this->_parts; + } + + /** + * Retrieve a specific MIME part. + * + * @param string $id The MIME ID. + * + * @return Horde_MIME_Part A pointer to the part requested, or null if + * the part doesn't exist. + */ + public function &getPart($id) + { + $this_id = $this->getMIMEId(); + if ($id == $this_id) { + return $this; + } + + if ($this->_reindex) { + $this->buildMIMEIds(is_null($this_id) ? '1' : $this_id); + } + + return $this->_partFind($id, $this->_parts); + } + + /** + * Remove a subpart. + * + * @param string $id The MIME part to delete. + */ + public function removePart($id) + { + $ob = &$this->getPart($id); + if ($ob !== null) { + unset($ob); + } + } + + /** + * Alter a current MIME subpart. + * + * @param string $id The MIME part ID to alter. + * @param Horde_MIME_Part $mime_part The MIME part to store. + */ + public function alterPart($id, $mime_part) + { + $ob = &$this->getPart($id); + if ($ob !== null) { + $ob = $mime_part; + } + } + + /** + * Function used to find a specific MIME part by ID. + * + * @param string $id The MIME ID. + * @param array &$parts A list of Horde_MIME_Part objects. + */ + protected function &_partFind($id, &$parts) + { + foreach (array_keys($parts) as $val) { + $ret = $parts[$val]->getPart($id); + if ($ret !== null) { + return $ret; + } + } + + $ret = null; + return $ret; + } + + /** + * Add a content type parameter to this part. + * + * @param string $label The disposition parameter label. + * @param string $data The disposition parameter data. + */ + public function setContentTypeParameter($label, $data) + { + $this->_contentTypeParams[$label] = $data; + } + + /** + * Clears a content type parameter from this part. + * + * @param string $label The disposition parameter label. + * @param string $data The disposition parameter data. + */ + public function clearContentTypeParameter($label) + { + unset($this->_contentTypeParams[$label]); + } + + /** + * Get a content type parameter from this part. + * + * @param string $label The content type parameter label. + * + * @return string The data requested. + * Returns null if $label is not set. + */ + public function getContentTypeParameter($label) + { + return isset($this->_contentTypeParams[$label]) + ? $this->_contentTypeParams[$label] + : null; + } + + /** + * Get all parameters from the Content-Type header. + * + * @return array An array of all the parameters + * Returns the empty array if no parameters set. + */ + public function getAllContentTypeParameters() + { + return $this->_contentTypeParameters; + } + + /** + * Sets a new string to use for EOLs. + * + * @param string $eol The string to use for EOLs. + */ + public function setEOL($eol) + { + $this->_eol = $eol; + } + + /** + * Get the string to use for EOLs. + * + * @return string The string to use for EOLs. + */ + public function getEOL() + { + return $this->_eol; + } + + /** + * Returns a Horde_MIME_Header object containing all MIME headers needed + * for the part. + * + * @param Horde_MIME_Headers $headers The Horde_MIME_Headers object to + * add the MIME headers to. If not + * specified, adds the headers to a + * new object. + * + * @return Horde_MIME_Headers A Horde_MIME_Headers object. + */ + public function addMIMEHeaders($headers = null) + { + if (is_null($headers)) { + $headers = new Horde_MIME_Headers(); + } + + foreach ($this->getHeaderArray() as $key => $val) { + $headers->addHeader($key, $val); + } + + return $headers; + } + + /** + * Get the list of MIME headers for this part in an array. + * + * @return array The full set of MIME headers. + */ + public function getHeaderArray() + { + $ptype = $this->getPrimaryType(); + $stype = $this->getSubType(); + + /* Get the character set for this part. */ + $charset = $this->getCharset(); + + /* Get the Content-Type - this is ALWAYS required. */ + $ctype = $this->getType(true); + + /* Manually encode Content-Type and Disposition parameters in here, + * rather than in Horde_MIME_Headers, since it is easier to do when + * the paramters are broken down. Encoding in the headers object will + * ignore these headers Since they will already be in 7bit. */ + foreach ($this->getAllContentTypeParameters() as $key => $value) { + /* Skip the charset key since that would have already been + * added to $ctype by getType(). */ + if ($key == 'charset') { + continue; + } + + $encode_2231 = Horde_MIME::encodeParamString($key, $value, $charset); + /* Try to work around non RFC 2231-compliant MUAs by sending both + * a RFC 2047-like parameter name and then the correct RFC 2231 + * parameter. See: + * http://lists.horde.org/archives/dev/Week-of-Mon-20040426/014240.html */ + if (!empty($GLOBALS['conf']['mailformat']['brokenrfc2231']) && + (strpos($encode_2231, '*=') !== false)) { + $ctype .= '; ' . $key . '="' . Horde_MIME::encode($value, $charset) . '"'; + } + $ctype .= '; ' . $encode_2231; + } + $headers['Content-Type'] = $ctype; + + /* Get the description, if any. */ + if (($descrip = $this->getDescription())) { + $headers['Content-Description'] = $descrip; + } + + /* RFC 2045 [4] - message/rfc822 and message/partial require the + MIME-Version header only if they themselves claim to be MIME + compliant. */ + if (($ptype == 'message') && + (($stype == 'rfc822') || ($stype == 'partial'))) { + // TODO - Check for "MIME-Version" in message/rfc822 part. + $headers['MIME-Version'] = '1.0'; + } + + /* message/* parts require no additional header information. */ + if ($ptype == 'message') { + return $headers; + } + + /* Don't show Content-Disposition for multipart messages unless + there is a name parameter. */ + $name = $this->getName(); + if (($ptype != 'multipart') || !empty($name)) { + $disp = $this->getDisposition(); + + /* Add any disposition parameter information, if available. */ + if (!empty($name)) { + $encode_2231 = Horde_MIME::encodeParamString('filename', $name, $charset); + /* Same broken RFC 2231 workaround as above. */ + if (!empty($GLOBALS['conf']['mailformat']['brokenrfc2231']) && + (strpos($encode_2231, '*=') !== false)) { + $disp .= '; filename="' . Horde_MIME::encode($name, $charset) . '"'; + } + $disp .= '; ' . $encode_2231; + } + + $headers['Content-Disposition'] = $disp; + } + + /* Add transfer encoding information. */ + $headers['Content-Transfer-Encoding'] = $this->getTransferEncoding(); + + /* Add content ID information. */ + if (!is_null($this->_contentid)) { + $headers['Content-ID'] = $this->_contentid; + } + + return $headers; + } + + /** + * Return the entire part in MIME format. Includes headers on request. + * + * @param boolean $headers Include the MIME headers? + * + * @return string The MIME string. + */ + public function toString($headers = true) + { + $eol = $this->getEOL(); + $ptype = $this->getPrimaryType(); + $text = ''; + + if ($headers) { + $hdr_ob = $this->addMIMEHeaders(); + $hdr_ob->setEOL($eol); + $text = $hdr_ob->toString(array('charset' => $this->getCharset())); + } + + /* Any information about a message/* is embedded in the message + contents themself. Simply output the contents of the part + directly and return. */ + if ($ptype == 'message') { + return $text . $this->_contents; + } + + $text .= $this->transferEncode(); + + /* Deal with multipart messages. */ + if ($ptype == 'multipart') { + $this->_generateBoundary(); + $boundary = trim($this->getContentTypeParameter('boundary'), '"'); + if (!strlen($this->_contents)) { + $text .= 'This message is in MIME format.' . $eol; + } + reset($this->_parts); + while (list(,$part) = each($this->_parts)) { + $text .= $eol . '--' . $boundary . $eol; + $oldEOL = $part->getEOL(); + $part->setEOL($eol); + $text .= $part->toString(true); + $part->setEOL($oldEOL); + } + $text .= $eol . '--' . $boundary . '--' . $eol; + } + + return $text; + } + + /** + * Returns the encoded part in strict RFC 822 & 2045 output - namely, all + * newlines end with the canonical sequence. + * + * @param boolean $headers Include the MIME headers? + * + * @return string The entire MIME part. + */ + public function toCanonicalString($headers = true) + { + $string = $this->toString($headers); + return $this->replaceEOL($string, self::RFC_EOL); + } + + /** + * Should we make sure the message is encoded via 7-bit (e.g. to adhere + * to mail delivery standards such as RFC 2821)? + * + * @param boolean $use7bit Use 7-bit encoding? + */ + public function strict7bit($use7bit) + { + $this->_encode7bit = $use7bit; + } + + /** + * Get the transfer encoding for the part based on the user requested + * transfer encoding and the current contents of the part. + * + * @return string The transfer-encoding of this part. + */ + public function getTransferEncoding() + { + /* If there are no contents, return whatever the current value of + $_transferEncoding is. */ + if (empty($this->_contents)) { + return $encoding; + } + + $encoding = $this->_transferEncoding; + $ptype = $this->getPrimaryType(); + + switch ($ptype) { + case 'message': + /* RFC 2046 [5.2.1] - message/rfc822 messages only allow 7bit, + 8bit, and binary encodings. If the current encoding is either + base64 or q-p, switch it to 8bit instead. + RFC 2046 [5.2.2, 5.2.3, 5.2.4] - All other message/* messages + only allow 7bit encodings. */ + $encoding = ($this->getSubType() == 'rfc822') ? '8bit' : '7bit'; + break; + + case 'text': + if (Horde_MIME::is8bit($this->_contents)) { + $encoding = ($this->_encode7bit) ? 'quoted-printable' : '8bit'; + } elseif (preg_match("/(?:\n|^)[^\n]{999,}(?:\n|$)/", $this->_contents)) { + /* If the text is longer than 998 characters between + * linebreaks, use quoted-printable encoding to ensure the + * text will not be chopped (i.e. by sendmail if being sent + * as mail text). */ + $encoding = 'quoted-printable'; + } + break; + + default: + if (Horde_MIME::is8bit($this->_contents)) { + $encoding = ($this->_encode7bit) ? 'base64' : '8bit'; + } + break; + } + + /* Need to do one last check for binary data if encoding is 7bit or + * 8bit. If the message contains a NULL character at all, the message + * MUST be in binary format. RFC 2046 [2.7, 2.8, 2.9]. Q-P and base64 + * can handle binary data fine so no need to switch those encodings. */ + if (in_array($encoding, array('8bit', '7bit')) && + preg_match('/\x00/', $this->_encoding)) { + $encoding = ($this->_encode7bit) ? 'base64' : 'binary'; + } + + return $encoding; + } + + /** + * Retrieves the current encoding of the contents in the object. + * + * @return string The current encoding. + */ + public function getCurrentEncoding() + { + return empty($this->_flags['currentEncoding']) + ? $this->_transferEncoding + : $this->_flags['currentEncoding']; + } + + /** + * Encodes the contents with the part's transfer encoding. + * + * @return string The encoded text. + */ + public function transferEncode() + { + $encoding = $this->getTransferEncoding(); + $eol = $this->getEOL(); + + /* Set the 'lastTransferEncode' flag so that transferEncodeContents() + can save a call to getTransferEncoding(). */ + $this->_flags['lastTransferEncode'] = $encoding; + + /* If contents are empty, or contents are already encoded to the + correct encoding, return now. */ + if (!strlen($this->_contents) || + ($encoding == $this->_flags['currentEncoding'])) { + return $this->_contents; + } + + switch ($encoding) { + /* Base64 Encoding: See RFC 2045, section 6.8 */ + case 'base64': + /* Keeping these two lines separate seems to use much less + memory than combining them (as of PHP 4.3). */ + $encoded_contents = base64_encode($this->_contents); + return chunk_split($encoded_contents, 76, $eol); + + /* Quoted-Printable Encoding: See RFC 2045, section 6.7 */ + case 'quoted-printable': + $output = Horde_MIME::quotedPrintableEncode($this->_contents, $eol); + if (($eollength = String::length($eol)) && + (substr($output, $eollength * -1) == $eol)) { + return substr($output, 0, $eollength * -1); + } + return $output; + + default: + return $this->replaceEOL($this->_contents); + } + } + + /** + * Decodes the contents of the part to either a 7bit or 8bit encoding. + * + * @return string The decoded text. + * Returns the empty string if there is no text to decode. + */ + public function transferDecode() + { + $encoding = $this->getCurrentEncoding(); + + /* If the contents are empty, return now. */ + if (!strlen($this->_contents)) { + $this->_flags['lastTransferDecode'] = $encoding; + return $this->_contents; + } + + switch ($encoding) { + case 'base64': + $this->_flags['lastTransferDecode'] = '8bit'; + return base64_decode($this->_contents); + + case 'quoted-printable': + $message = preg_replace("/=\r?\n/", '', $this->_contents); + $message = quoted_printable_decode($this->replaceEOL($message)); + $this->_flags['lastTransferDecode'] = (Horde_MIME::is8bit($message)) ? '8bit' : '7bit'; + return $message; + + /* Support for uuencoded encoding - although not required by RFCs, + some mailers may still encode this way. */ + case 'uuencode': + case 'x-uuencode': + case 'x-uue': + $this->_flags['lastTransferDecode'] = '8bit'; + return convert_uuencode($this->_contents); + + default: + if (isset($this->_flags['lastTransferDecode']) && + ($this->_flags['lastTransferDecode'] != $encoding)) { + $message = $this->replaceEOL($this->_contents); + } else { + $message = $this->_contents; + } + $this->_flags['lastTransferDecode'] = $encoding; + return $message; + } + } + + /** + * Split the contents of the current Part into its respective subparts, + * if it is multipart MIME encoding. + * + * The boundary Content-Type parameter must be set for this function to + * work correctly. + * + * @return boolean True if the contents were successfully split. + * False if any error occurred. + */ + public function splitContents() + { + if ((!($boundary = $this->getContentTypeParameter('boundary'))) || + !strlen($this->_contents)) { + return false; + } + + $eol = $this->getEOL(); + $retvalue = false; + + $boundary = '--' . $boundary; + if (substr($this->_contents, 0, strlen($boundary)) == $boundary) { + $pos1 = 0; + } else { + $pos1 = strpos($this->_contents, $eol . $boundary); + if ($pos1 === false) { + return false; + } + } + + $pos1 = strpos($this->_contents, $eol, $pos1 + 1); + if ($pos1 === false) { + return false; + } + $pos1 += strlen($eol); + + reset($this->_parts); + $part_ptr = key($this->_parts); + + while ($pos2 = strpos($this->_contents, $eol . $boundary, $pos1)) { + $this->_parts[$part_ptr]->setContents(substr($this->_contents, $pos1, $pos2 - $pos1)); + $this->_parts[$part_ptr]->splitContents(); + next($this->_parts); + $part_ptr = key($this->_parts); + if (is_null($part_ptr)) { + return false; + } + $pos1 = strpos($this->_contents, $eol, $pos2 + 1); + if ($pos1 === false) { + return true; + } + $pos1 += strlen($eol); + } + + return true; + } + + /** + * Replace newlines in this part's contents with those specified by either + * the given newline sequence or the part's current EOL setting. + * + * @param string $text The text to replace. + * @param string $eol The EOL sequence to use. If not present, uses the + * part's current EOL setting. + * + * @return string The text with the newlines replaced by the desired + * newline sequence. + */ + public function replaceEOL($text, $eol = null) + { + if (is_null($eol)) { + $eol = $this->getEOL(); + } + return preg_replace("/\r?\n/", $eol, $text); + } + + /** + * Determine the size of this MIME part and its child members. + * + * @return integer Size of the part, in bytes. + */ + public function getBytes() + { + $bytes = 0; + + if (empty($this->_flags['contentsSet']) && $this->_bytes) { + $bytes = $this->_bytes; + } elseif ($this->getPrimaryType() == 'multipart') { + reset($this->_parts); + while (list(,$part) = each($this->_parts)) { + /* Skip multipart entries (since this may result in double + counting). */ + if ($part->getPrimaryType() != 'multipart') { + $bytes += $part->getBytes(); + } + } + } else { + $bytes = ($this->getPrimaryType() == 'text') + ? String::length($this->_contents, $this->getCharset()) + : strlen($this->_contents); + } + + return $bytes; + } + + /** + * Explicitly set the size (in bytes) of this part. This value will only + * be returned (via getBytes()) if there are no contents currently set. + * This function is useful for setting the size of the part when the + * contents of the part are not fully loaded (i.e. creating a + * Horde_MIME_Part object from IMAP header information without loading the + * data of the part). + * + * @param integer $bytes The size of this part in bytes. + */ + public function setBytes($bytes) + { + $this->_bytes = $bytes; + } + + /** + * Output the size of this MIME part in KB. + * + * @return string Size of the part, in string format. + */ + public function getSize() + { + $bytes = $this->getBytes(); + if (empty($bytes)) { + return $bytes; + } + + $localeinfo = NLS::getLocaleInfo(); + return number_format($bytes / 1024, 2, $localeinfo['decimal_point'], $localeinfo['thousands_sep']); + } + + /** + * Add to the list of CIDs for this part. + * + * @param array $cids A list of MIME IDs of the part. + * Key - MIME ID + * Value - CID for the part + */ + public function addCID($cids = array()) + { + $this->_cids += $cids; + asort($this->_cids, SORT_STRING); + } + + /** + * Returns the list of CIDs for this part. + * + * @return array The list of CIDs for this part. + */ + public function getCIDList() + { + return $this->_cids; + } + + /** + * Sets the Content-ID header for this part. + * + * @param string $cid Use this CID (if not already set). Else, generate + * a random CID. + */ + public function setContentID($cid = null) + { + if (is_null($this->_contentid)) { + $this->_contentid = (is_null($cid)) ? (Horde_MIME::generateRandomID() . '@' . $_SERVER['SERVER_NAME']) : $cid; + } + return $this->_contentid; + } + + /** + * Returns the Content-ID for this part. + * + * @return string The Content-ID for this part. + */ + public function getContentID() + { + return $this->_contentid; + } + + /** + * Alter the MIME ID of this part. + * + * @param string $mimeid The MIME ID. + */ + public function setMIMEId($mimeid) + { + $this->_mimeid = $mimeid; + } + + /** + * Returns the MIME ID of this part. + * + * @return string The MIME ID. + */ + public function getMIMEId() + { + return $this->_mimeid; + } + + /** + * Build the MIME IDs for this part and all subparts. + * + * @param string $id The ID of this part. + */ + public function buildMIMEIds($id = null) + { + if (is_null($id)) { + if (empty($this->_parts)) { + $this->setMIMEId('1'); + } else { + $this->setMIMEId('0'); + $i = 1; + foreach (array_keys($this->_parts) as $val) { + $this->_parts[$val]->buildMIMEIds($i++); + } + } + } else { + $this->setMIMEId($id . (($this->getType() == 'message/rfc822') ? '.0' : '')); + + if (!empty($this->_parts)) { + $i = 1; + foreach (array_keys($this->_parts) as $val) { + $this->_parts[$val]->buildMIMEIds($id . '.' . $i++); + } + } + } + + $this->_reindex = false; + } + + /** + * Generate the unique boundary string (if not already done). + * + * @return string The boundary string. + */ + protected function _generateBoundary() + { + if (is_null($this->_boundary)) { + $this->_boundary = '=_' . Horde_MIME::generateRandomID(); + } + return $this->_boundary; + } + + /** + * Returns a mapping of all MIME IDs to their content-types. + * + * @param boolean $sort Sort by MIME ID? + * + * @return array Keys: MIME ID; values: content type. + */ + public function contentTypeMap($sort = true) + { + $map = array($this->getMIMEId() => $this->getType()); + foreach ($this->_parts as $val) { + $map += $val->contentTypeMap(false); + } + + if ($sort) { + uksort($map, 'strnatcasecmp'); + } + + return $map; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer.php b/framework/Mime/lib/Horde/Mime/Viewer.php new file mode 100644 index 000000000..cfc47fc87 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer.php @@ -0,0 +1,332 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME_Viewer +{ + /** + * The config array. This array is shared between all instances of + * Horde_MIME_Viewer. + * + * @var array + */ + static protected $_config = array(); + + /** + * The driver cache array. + * + * @var array + */ + static protected $_drivercache = array(); + + /** + * Attempts to return a concrete Horde_MIME_Viewer_* object based on the + * MIME type. + * + * @param string $mime_type The MIME type. + * + * @return Horde_MIME_Viewer The Horde_MIME_Viewer object, or false on + * error. + */ + static final public function factory($mime_type) + { + /* Spawn the relevant driver, and return it (or false on failure). */ + if (($ob = self::_getDriver($mime_type, $GLOBALS['registry']->getApp())) && + self::_resolveDriver($ob['driver'], $ob['app']) && + class_exists($ob['class'])) { + return new $ob['class'](self::$_config['mime_drivers'][$ob['app']][$ob['driver']]); + } + + return false; + } + + /** + * Given a MIME type and an app name, determine which driver can best + * handle the data. + * + * @param string $mime_type MIME type to resolve. + * @param string $app App in which to search for the driver. + * + * @return mixed Returns false if driver could not be found. Otherwise, + * an array with the following elements: + *
+     * 'app' - (string) The app containing the driver (e.g. 'horde')
+     * 'driver' - (string) Name of driver (e.g. 'enscript')
+     * 'exact' - (boolean) Was the driver and exact match?
+     * 
+ */ + static final protected function _getDriver($mime_type, $app = 'horde') + { + $sig = $mime_type . '|' . $app; + if (isset(self::$_drivercache[$sig])) { + return self::$_drivercache[$sig]; + } + + /* Make sure 'horde' mime_drivers config is loaded. */ + if (empty(self::$_config['mime_drivers']['horde'])) { + $res = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde'); + if (is_a($res, 'PEAR_Error')) { + return false; + } + self::$_config = $res; + } + + /* Make sure app's' mime_drivers config is loaded. */ + if (($app != 'horde') && empty(self::$_config['mime_drivers'][$app])) { + $res = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), $app); + if (is_a($res, 'PEAR_Error')) { + return false; + } + + require_once 'Horde/Array.php'; + self::$_config = Horde_Array::array_merge_recursive_overwrite(self::$_config, $res); + } + + $driver = ''; + $exact = false; + + list($primary_type,) = explode('/', $mime_type, 2); + $allSub = $primary_type . '/*'; + + /* If the app doesn't exist in $mime_drivers_map, check for Horde-wide + * viewers. */ + if (!isset(self::$_config['mime_drivers_map'][$app]) && + ($app != 'horde')) { + return self::_getDriver($mime_type, 'horde'); + } + + $dr = self::$_config['mime_drivers'][$app]; + $map = self::$_config['mime_drivers_map'][$app]; + + /* If an override exists for this MIME type, then use that */ + if (isset($map['overrides'][$mime_type])) { + $driver = $map['overrides'][$mime_type]; + $exact = true; + } elseif (isset($map['overrides'][$allSub])) { + $driver = $map['overrides'][$allSub]; + $exact = true; + } elseif (isset($map['registered'])) { + /* Iterate through the list of registered drivers, and see if + * this MIME type exists in the MIME types that they claim to + * handle. If the driver handles it, then assign it as the + * rendering driver. If we find a generic handler, keep iterating + * to see if we can find a specific handler. */ + foreach ($map['registered'] as $val) { + if (in_array($mime_type, $dr[$val]['handles'])) { + $driver = $val; + $exact = true; + break; + } elseif (in_array($allSub, $dr[$val]['handles'])) { + $driver = $val; + } + } + } + + /* If this is an application specific app, and an exact match was + not found, search for a Horde-wide specific driver. Only use the + Horde-specific driver if it is NOT the 'default' driver AND the + Horde driver is an exact match. */ + if (!$exact && ($app != 'horde')) { + $ob = self::_getDriver($mime_type, 'horde'); + if (empty($driver) || + (($ob['driver'] != 'default') && $ob['exact'])) { + $driver = $ob['driver']; + $app = 'horde'; + } + } + + /* If the 'default' driver exists in this app, fall back to that. */ + if (empty($driver) && self::_resolveDriver('default', $app)) { + $driver = 'default'; + } + + if (empty($driver)) { + return false; + } + + self::$_drivercache[$sig] = array( + 'app' => $app, + 'class' => (($app == 'horde') ? '' : $app . '_') . 'Horde_MIME_Viewer_' . $driver, + 'driver' => $driver, + 'exact' => $exact, + ); + + return self::$_drivercache[$sig]; + } + + /** + * Given a driver and an application, attempts to load the library file. + * + * @param string $driver Driver name. + * @param string $app Application name. + * + * @return boolean True if library file was loaded. + */ + static final protected function _resolveDriver($driver = 'default', + $app = 'horde') + { + $file = ($app == 'horde') + ? dirname(__FILE__) . '/Viewer/' . $driver . '.php' + : $GLOBALS['registry']->applications[$app]['fileroot'] . '/lib/MIME/Viewer/' . $driver . '.php'; + + require_once dirname(__FILE__) . '/Viewer/Driver.php'; + + $old_error = error_reporting(0); + $ret = require_once $file; + error_reporting($old_error); + + return $ret; + } + + /** + * Prints out the status message for a given MIME Part. + * + * @param string $msg The message to output. + * @param string $img An image link to add to the beginning of the + * message. + * @param string $class An optional style for the status box. + * + * @return string The formatted status message string. + */ + static public function formatStatusMsg($msg, $img = null, $class = null) + { + if (empty($msg)) { + return ''; + } + + if (!is_array($msg)) { + $msg = array($msg); + } + + /* If we are viewing as an attachment, don't print HTML code. */ + if (self::viewAsAttachment()) { + return implode("\n", $msg); + } + + if (is_null($class)) { + $class = 'mimeStatusMessage'; + } + $text = ''; + + /* If no image, simply print out the message. */ + if (is_null($img)) { + foreach ($msg as $val) { + $text .= '' . "\n"; + } + } else { + $text .= '' . "\n"; + } + + return $text . '
' . $val . '
' . $img . ''; + if (count($msg) == 1) { + $text .= $msg[0]; + } else { + $text .= ''; + foreach ($msg as $val) { + $text .= '' . "\n"; + } + $text .= '
' . $val . '
'; + } + $text .= '
'; + } + + /** + * Given a MIME type, this function will return an appropriate icon. + * + * @param string $mime_type The MIME type that we need an icon for. + * + * @return string The URL to the appropriate icon. + */ + static final public function getIcon($mime_type) + { + $app = $GLOBALS['registry']->getApp(); + $ob = self::_getIcon($mime_type, $app); + + if (is_null($ob)) { + if ($app == 'horde') { + return null; + } + + $obHorde = self::_getIcon($mime_type, 'horde'); + return is_null($obHorde) ? null : $obHorde['url']; + } elseif (($ob['match'] !== 0) && ($app != 'horde')) { + $obHorde = self::_getIcon($mime_type, 'horde'); + if (!is_null($ob['match']) && + ($obHorde['match'] <= $ob['match'])) { + return $obHorde['url']; + } + } + + return $ob['url']; + } + + /** + * Given an input MIME type and app, this function returns the URL of an + * icon that can be associated with it + * + * @param string $mime_type MIME type to get the icon for. + * + * @return mixed Null if not found, or an array with the following keys: + *
+     * 'exact' - (integer) How exact the match is.
+     *           0 => 'exact', 1 => 'primary', 2 => 'driver',
+     *           3 => 'default', or null.
+     * 'url' - (string) URL to an icon, or null if none could be found.
+     * 
+ */ + static final protected function _getIcon($mime_type, $app = 'horde') + { + if (!($ob = self::_getDriver($mime_type, $app))) { + return null; + } + $driver = $ob['driver']; + + list($primary_type,) = explode('/', $mime_type, 2); + $allSub = $primary_type . '/*'; + $ret = null; + + /* If the app doesn't exist in $mime_drivers, return now. */ + if (!isset(self::$_config['mime_drivers'][$app])) { + return null; + } + + $dr = self::$_config['mime_drivers'][$app]; + + /* If a specific icon for this driver and mimetype is defined, + then use that. */ + if (isset($dr[$driver]['icons'])) { + $icondr = $dr[$driver]['icons']; + $iconList = array($mime_type => 0, $allSub => 1, 'default' => 2); + foreach ($iconList as $key => $val) { + if (isset($icondr[$key])) { + $ret = array('match' => $val, 'url' => $icondr[$key]); + break; + } + } + } + + /* Try to use a default icon if none already obtained. */ + if (is_null($ret['url']) && + isset($dr['default']['icons']['default'])) { + $ret = array('match' => 3, 'url' => $dr['default']['icons']['default']); + } + + if (!is_null($ret)) { + $ret['url'] = $GLOBALS['registry']->getImageDir($app) . '/mime/' . $ret['url']; + } + + return $ret; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/Driver.php b/framework/Mime/lib/Horde/Mime/Viewer/Driver.php new file mode 100644 index 000000000..e441e2713 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/Driver.php @@ -0,0 +1,186 @@ + + * @author Michael Slusarz + * @package Horde_MIME + */ +class Horde_MIME_Viewer_Driver +{ + /** + * Viewer configuration. + * + * @var array + */ + protected $_conf = array(); + + /** + * The Horde_MIME_Part object to render. + * + * @var Horde_MIME_Part + */ + protected $_mimepart = null; + + /** + * Viewer parameters. + * + * @var array + */ + protected $_params = array(); + + /** + * Can this driver render various views? + * + * @var boolean + */ + protected $_canrender = array( + 'full' => false, + 'info' => false, + 'inline' => false, + ); + + /** + * Constructor. + * + * @param array $conf Configuration specific to the driver. + */ + function __construct($conf = array()) + { + $this->_conf = $conf; + } + + /** + * Sets the Horde_MIME_Part object for the class. + * + * @param Horde_MIME_Part &$mime_part Reference to an object with the + * information to be rendered. + */ + public function setMIMEPart(&$mime_part) + { + $this->_mimepart = $mime_part; + } + + /** + * Set parameters for use with this object. + * + * @param array $params An array of params to add to the internal + * params list. + */ + public function setParams($params = array()) + { + $this->_params = array_merge($this->_params, $params); + } + + /** + * Return the rendered version of the Horde_MIME_Part object. + * + * @return array TODO + */ + public function render() + { + return (is_null($this->_mimepart) || !$this->canDisplay()) + ? array('data' => '', 'type' => 'text/plain') + : $this->_render(); + } + + /** + * Return the rendered version of the Horde_MIME_Part object. + * + * @return string Rendered version of the Horde_MIME_Part object. + */ + protected function _render() + { + } + + /** + * Return the rendered inline version of the Horde_MIME_Part object. + * + * @return string Rendered version of the Horde_MIME_Part object. + */ + public function renderInline() + { + return (is_null($this->_mimepart) || !$this->canDisplayInline()) + ? '' + : $this->_renderInline(); + } + + /** + * Return the rendered inline version of the Horde_MIME_Part object. + * + * @return string Rendered version of the Horde_MIME_Part object. + */ + protected function _renderInline() + { + } + + /** + * Return the rendered information about the Horde_MIME_Part object. + * + * @return string Rendered information on the Horde_MIME_Part object. + */ + public function renderInfo() + { + return (is_null($this->_mimepart) || !$this->canDisplayInfo()) + ? '' + : $this->_renderInfo(); + } + + /** + * Return the rendered information about the Horde_MIME_Part object. + * + * @return string Rendered information on the Horde_MIME_Part object. + */ + protected function _renderInfo() + { + } + + /** + * Can this driver render the the data? + * + * @return boolean True if the driver can render data. + */ + public function canDisplay() + { + return $this->_canrender['full']; + } + + /** + * Can this driver render the the data inline? + * + * @return boolean True if the driver can display inline. + */ + public function canDisplayInline() + { + return $this->getConfigParam('inline') && $this->_canrender['inline']; + } + + /** + * Can this driver render the the data inline? + * + * @return boolean True if the driver can display inline. + */ + public function canDisplayInfo() + { + return $this->_canrender['info']; + } + + /** + * Return a configuration parameter for the current viewer. + * + * @param string $param The parameter name. + * + * @return mixed The value of the parameter; returns null if the + * parameter doesn't exist. + */ + public function getConfigParam($param) + { + return isset($this->_conf[$param]) ? $this->_conf[$param] : null; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/audio.php b/framework/Mime/lib/Horde/Mime/Viewer/audio.php new file mode 100644 index 000000000..df83fbeb6 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/audio.php @@ -0,0 +1,25 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_audio extends Horde_MIME_Viewer_Driver +{ + /** + * Return the content-type. + * + * @return string The content-type of the output. + */ + public function getType() + { + return $this->mime_part->getType(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/css.php b/framework/Mime/lib/Horde/Mime/Viewer/css.php new file mode 100644 index 000000000..d11ebed79 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/css.php @@ -0,0 +1,109 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_css extends Horde_MIME_Viewer_source +{ + /** + * Render out the currently set contents. + * + * @param array $params Any parameters the viewer may need. + * + * @return string The rendered text. + */ + public function render($params = null) + { + $css = htmlspecialchars($this->mime_part->getContents(), ENT_NOQUOTES); + $css = preg_replace_callback('!(}|\*/).*?({|/\*)!s', array($this, '_handles'), $css); + $css = preg_replace_callback('!{[^}]*}!s', array($this, '_attributes'), $css); + $css = preg_replace_callback('!/\*.*?\*/!s', array($this, '_comments'), $css); + $css = trim($css); + + // Educated Guess at whether we are inline or not. + if (headers_sent() || ob_get_length()) { + return $this->lineNumber($css); + } else { + return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') . + $this->lineNumber($css) . + Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); + } + } + + /** + */ + protected function _comments($matches) + { + $patterns[] = '!(http://[/\w-.]+)!s'; + $replaces[] = '\\1'; + + $comments = preg_replace($patterns, $replaces, $matches[0]); + + return '' . $comments . ''; + } + + /** + */ + protected function _attributes($matches) + { + // Attributes. + $patterns[] = '!([-\w]+\s*):!s'; + $replaces[] = '\\1:'; + + // Values. + $patterns[] = '!:(\s*)(.+?)(\s*;)!s'; + $replaces[] = ':\\1\\2\\3'; + + // URLs. + $patterns[] = '!(url\([\'"]?)(.*?)([\'"]?\))!s'; + $replaces[] = '\\1\\2\\3'; + + // Colors. + $patterns[] = '!(#[[:xdigit:]]{3,6})!s'; + $replaces[] = '\\1'; + + // Parentheses. + $patterns[] = '!({|})!s'; + $replaces[] = '\\1'; + + // Unity. + $patterns[] = '!(em|px|%)\b!s'; + $replaces[] = '\\1'; + + return preg_replace($patterns, $replaces, $matches[0]); + } + + /** + */ + protected function _handles($matches) + { + // HTML Tags. + $patterns[] = '!\b(body|h\d|a|span|div|acronym|small|strong|em|pre|ul|ol|li|p)\b!s'; + $replaces[] = '\\1\\2'; + + // IDs. + $patterns[] = '!(#[-\w]+)!s'; + $replaces[] = '\\1'; + + // Class. + $patterns[] = '!(\.[-\w]+)\b!s'; + $replaces[] = '\\1'; + + // METAs. + $patterns[] = '!(:link|:visited|:hover|:active|:first-letter)!s'; + $replaces[] = '\\1'; + + return preg_replace($patterns, $replaces, $matches[0]); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/deb.php b/framework/Mime/lib/Horde/Mime/Viewer/deb.php new file mode 100644 index 000000000..7afdc97d9 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/deb.php @@ -0,0 +1,54 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_deb extends Horde_MIME_Viewer_Driver +{ + /** + * Render the data. + * + * @param array $params Any parameters the viewer may need. + * + * @return string The rendered data. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['deb']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['deb']['location']) . '
'; + } + + $tmp_deb = Horde::getTempFile('horde_deb'); + + $fh = fopen($tmp_deb, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + $fh = popen($GLOBALS['mime_drivers']['horde']['deb']['location'] . " -f $tmp_deb 2>&1", 'r'); + while (($rc = fgets($fh, 8192))) { + $data .= $rc; + } + pclose($fh); + + return '
' . htmlspecialchars($data) . '
'; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/default.php b/framework/Mime/lib/Horde/Mime/Viewer/default.php new file mode 100644 index 000000000..4872f75f2 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/default.php @@ -0,0 +1,17 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_default extends Horde_MIME_Viewer_Driver +{ +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/enriched.php b/framework/Mime/lib/Horde/Mime/Viewer/enriched.php new file mode 100644 index 000000000..a46db587f --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/enriched.php @@ -0,0 +1,158 @@ + command and the next balancing + * removes all other formatting commands (all text enclosed + * in angle brackets), and outside of environments converts + * any series of n CRLFs to n-1 CRLFs, and converts any lone CRLF + * pairs to SPACE. + * + * We don't qualify as we don't currently track the + * environment, that is we do CRLF conversion even if is + * specified in the text, but we're close at least. + * + * Copyright 2001-2008 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @author Eric Rostetter + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_enriched extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the currently set contents in HTML format. The + * $mime_part class variable has the information to render out, + * encapsulated in a MIME_Part object. + */ + public function render() + { + if (($text = $this->mime_part->getContents()) === false) { + return false; + } + + if (trim($text) == '') { + return $text; + } + + // We add space at the beginning and end of the string as it will + // make some regular expression checks later much easier (so we + // don't have to worry about start/end of line characters) + $text = ' ' . $text . ' '; + + // We need to preserve << tags, so map them to ascii 1 or ascii 255 + // We make the assumption here that there would never be an ascii + // 1 in an email, which may not be valid, but seems reasonable... + // ascii 255 would work if for some reason you don't like ascii 1 + // ascii 0 does NOT seem to work for this, though I'm not sure why + $text = str_replace('<<', chr(1), $text); + + // Remove any unrecognized tags in the text (via RFC minimal specs) + // any tags we just don't want to implement can also be removed here + // Note that this will remove any html links, but this is intended + $implementedTags = '' . + '
' . + ''; + // $unImplementedTags = ''; + $text = strip_tags($text, $implementedTags); + + // restore the << tags as < tags now... + $text = str_replace(chr(1), '<<', $text); + // $text = str_replace(chr(255), '<', $text); + + // Get color parameters into a more useable format. + $text = preg_replace('/([\da-fA-F]+),([\da-fA-F]+),([\da-fA-F]+)<\/param>/Uis', '', $text); + $text = preg_replace('/(red|blue|green|yellow|cyan|magenta|black|white)<\/param>/Uis', '', $text); + + // Get font family parameters into a more useable format. + $text = preg_replace('/(\w+)<\/param>/Uis', '', $text); + + // Just remove any remaining parameters -- we won't use + // them. Any tags with parameters that we want to implement + // will have to come before this Someday we hope to use these + // tags (e.g. for tags) + $text = preg_replace('/.*<\/param>/Uis', '', $text); + + // Single line breaks become spaces, double line breaks are a + // real break. This needs to do tracking to be + // compliant but we don't want to deal with state at this + // time, so we fake it some day we should rewrite this to + // handle correctly. + $text = preg_replace('/([^\n])\r\n([^\r])/', '\1 \2', $text); + $text = preg_replace('/(\r\n)\r\n/', '\1', $text); + + // We try to protect against bad stuff here. + $text = @htmlspecialchars($text, ENT_QUOTES, $this->mime_part->getCharset()); + + // Now convert the known tags to html. Try to remove any tag + // parameters to stop people from trying to pull a fast one + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace_callback('/(?\2', $text); + $text = preg_replace('/(?\2', $text); + $text = preg_replace('/(?', $text); + $text = preg_replace('/(?', $text); + $text = preg_replace('/(?', $text); + $text = preg_replace('/(?', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + $text = preg_replace('/(?\1', $text); + + // Replace << with < now (from translated HTML form). + $text = str_replace('<<', '<', $text); + + // Now we remove the leading/trailing space we added at the + // start. + $text = preg_replace('/^ (.*) $/s', '\1', $text); + + // Make URLs clickable. + require_once 'Horde/Text/Filter.php'; + $text = Text_Filter::filter($text, 'linkurls', array('callback' => 'Horde::externalUrl')); + + // Wordwrap -- note this could impact on our above RFC + // compliance *IF* we honored nofill tags (which we don't + // yet). + $text = str_replace("\t", ' ', $text); + $text = str_replace(' ', '  ', $text); + $text = str_replace("\n ", "\n ", $text); + if ($text[0] == ' ') { + $text = ' ' . substr($text, 1); + } + $text = nl2br($text); + $text = '

' . $text . '

'; + + return $text; + } + + /** + */ + public function colorize($colors) + { + for ($i = 1; $i < 4; $i++) { + $colors[$i] = sprintf('%02X', round(hexdec($colors[$i]) / 255)); + } + return '' . $colors[4] . ''; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/enscript.php b/framework/Mime/lib/Horde/Mime/Viewer/enscript.php new file mode 100644 index 000000000..7d3edb18b --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/enscript.php @@ -0,0 +1,132 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_enscript extends Horde_MIME_Viewer_source +{ + /** + * Render out the data using Enscript. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered data. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['enscript']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['enscript']['location']) . '
'; + } + + /* Create temporary files for input to Enscript. Note that we + cannot use a pipe, since enscript must have access to the + whole file to determine its type for coloured syntax + highlighting. */ + $tmpin = Horde::getTempFile('EnscriptIn'); + + /* Write the contents of our buffer to the temporary input file. */ + $contents = $this->mime_part->getContents(); + $fh = fopen($tmpin, 'wb'); + fwrite($fh, $contents, strlen($contents)); + fclose($fh); + + /* Execute the enscript command. */ + $lang = escapeshellarg($this->_typeToLang($this->mime_part->getType())); + $results = shell_exec($GLOBALS['mime_drivers']['horde']['enscript']['location'] . " -E$lang --language=html --color --output=- < $tmpin"); + + /* Strip out the extraneous HTML from Enscript, and output it. */ + $res_arr = preg_split('/\<\/?pre\>/i', $results); + if (count($res_arr) == 3) { + $results = trim($res_arr[1]); + } + + /* Educated Guess at whether we are inline or not. */ + if (headers_sent() || ob_get_length()) { + return $this->lineNumber($results); + } else { + return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') . + $this->lineNumber($results) . + Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); + } + } + + /** + * Attempts to determine what language to use for the enscript program + * from a MIME type. + * + * @param string $type The MIME type. + * + * @return string The enscript 'language' parameter string. + */ + protected function _typeToLang($type) + { + include_once dirname(__FILE__) . '/../Magic.php'; + + $ext = Horde_MIME_Magic::MIMEToExt($type); + + switch ($ext) { + case 'cs': + return 'java'; + + case 'el': + return 'elisp'; + + case 'h': + return 'c'; + + case 'C': + case 'H': + case 'cc': + case 'hh': + case 'c++': + case 'cxx': + case 'cpp': + return 'cpp'; + + case 'htm': + case 'shtml': + case 'xml': + return 'html'; + + case 'js': + return 'javascript'; + + case 'pas': + return 'pascal'; + + case 'al': + case 'cgi': + case 'pl': + case 'pm': + return 'perl'; + + case 'ps': + return 'postscript'; + + case 'vb': + return 'vba'; + + case 'vhd': + return 'vhdl'; + + case 'patch': + case 'diff': + return 'diffu'; + + default: + return $ext; + } + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/html.php b/framework/Mime/lib/Horde/Mime/Viewer/html.php new file mode 100644 index 000000000..b8317b7c8 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/html.php @@ -0,0 +1,166 @@ + + * @author Jon Parise + * @author Michael Slusarz + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_html extends Horde_MIME_Viewer_Driver +{ + /** + * Can this driver render various views? + * + * @var boolean + */ + protected $_canrender = array( + 'full' => true, + 'info' => false, + 'inline' => true, + ); + + /** + * Render out the currently set contents. + * + * @return string The rendered text. + */ + public function _render() + { + return array('data' => $this->_cleanHTML($this->_mimepart->getContents(), false), 'type' => $this->_mimepart->getType(true)); + } + + /** + * TODO + */ + public function _renderInline() + { + return String::convertCharset($this->_cleanHTML($this->_mimepart->getContents(), true), $this->_mimepart->getCharset()); + } + + /** + * Filters active content, dereferences external links, detects phishing, + * etc. + * + * @todo Use IP checks from + * http://lxr.mozilla.org/mailnews/source/mail/base/content/phishingDetector.js. + * + * @param string $data The HTML data. + * @param boolean $inline Are we viewing inline? + * + * @return string The cleaned HTML data. + */ + protected function _cleanHTML($data, $inline) + { + global $browser, $prefs; + + $phish_warn = false; + + /* Deal with tags in the HTML, since they will screw up our own + * relative paths. */ + if (preg_match('/ ]*)"? ?\/?>/i', $data, $matches)) { + $base = $matches[1]; + if (substr($base, -1) != '/') { + $base .= '/'; + } + + /* Recursively call _cleanHTML() to prevent clever fiends from + * sneaking nasty things into the page via $base. */ + $base = $this->_cleanHTML($base, $inline); + + /* Attempt to fix paths that were relying on a tag. */ + if (!empty($base)) { + $pattern = array('|src=(["\'])([^:"\']+)\1|i', + '|src=([^: >"\']+)|i', + '|href= *(["\'])([^:"\']+)\1|i', + '|href=([^: >"\']+)|i'); + $replace = array('src=\1' . $base . '\2\1', + 'src=' . $base . '\1', + 'href=\1' . $base . '\2\1', + 'href=' . $base . '\1'); + $data = preg_replace($pattern, $replace, $data); + } + } + + require_once 'Horde/Text/Filter.php'; + $strip_style_attributes = (($browser->isBrowser('mozilla') && + $browser->getMajor() == 4) || + $browser->isBrowser('msie')); + $strip_styles = $inline || $strip_style_attributes; + $data = Text_Filter::filter($data, 'xss', + array('body_only' => $inline, + 'strip_styles' => $strip_styles, + 'strip_style_attributes' => $strip_style_attributes)); + + /* Check for phishing exploits. */ + if ($this->getConfigParam('phishing_check')) { + if (preg_match('/href\s*=\s*["\']?\s*(http|https|ftp):\/\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:[^>]*>\s*(?:\\1:\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})[^<]*<\/a)?/i', $data, $m)) { + /* Check 1: Check for IP address links, but ignore if the link + * text has the same IP address. */ + if (!isset($m[3]) || ($m[2] != $m[3])) { + if (isset($m[3])) { + $data = preg_replace('/href\s*=\s*["\']?\s*(http|https|ftp):\/\/' . preg_quote($m[2], '/') . '(?:[^>]*>\s*(?:$1:\/\/)?' . preg_quote($m[3], '/') . '[^<]*<\/a)?/i', 'class="mimeStatusWarning" $0', $data); + } + $phish_warn = true; + } + } elseif (preg_match_all('/href\s*=\s*["\']?\s*(?:http|https|ftp):\/\/([^\s"\'>]+)["\']?[^>]*>\s*(?:(?:http|https|ftp):\/\/)?(.*?)<\/a/is', $data, $m)) { + /* $m[1] = Link; $m[2] = Target + * Check 2: Check for links that point to a different host than + * the target url; if target looks like a domain name, check it + * against the link. */ + for ($i = 0, $links = count($m[0]); $i < $links; ++$i) { + $link = strtolower(urldecode($m[1][$i])); + $target = strtolower(preg_replace('/^(http|https|ftp):\/\//', '', strip_tags($m[2][$i]))); + if (preg_match('/^[-._\da-z]+\.[a-z]{2,}/i', $target) && + (strpos($link, $target) !== 0) && + (strpos($target, $link) !== 0)) { + /* Don't consider the link a phishing link if the + * domain is the same on both links (e.g. + * adtracking.example.com & www.example.com). */ + preg_match('/\.?([^\.\/]+\.[^\.\/]+)[\/?]/', $link, $host1); + preg_match('/\.?([^\.\/]+\.[^\.\/ ]+)([\/ ].*)?$/', $target, $host2); + if (!(count($host1) && count($host2)) || + (strcasecmp($host1[1], $host2[1]) !== 0)) { + $data = preg_replace('/href\s*=\s*["\']?\s*(?:http|https|ftp):\/\/' . preg_quote($m[1][$i], '/') . '["\']?[^>]*>\s*(?:(?:http|https|ftp):\/\/)?' . preg_quote($m[2][$i], '/') . '<\/a/is', 'class="mimeStatusWarning" $0', $data); + $phish_warn = true; + } + } + } + } + } + + /* Try to derefer all external references. */ + $data = preg_replace_callback('/href\s*=\s*(["\'])?((?(1)[^\1]*?|[^\s>]+))(?(1)\1|)/i', + array($this, '_dereferExternalReferencesCallback'), + $data); + + /* Prepend phishing warning. */ + if ($phish_warn) { + $phish_warning = sprintf(_("%s: This message may not be from whom it claims to be. Beware of following any links in it or of providing the sender with any personal information.") . ' ' . _("The links that caused this warning have the same background color as this message."), _("Warning")); + if (!$inline) { + $phish_warning = '' . String::convertCharset($phish_warning, NLS::getCharset(), $this->_mimepart->getCharset()) . '
'; + } + $phish_warning = $this->formatStatusMsg($phish_warning, null, 'mimeStatusWarning'); + + $data = (stristr($data, ')(.*)/i', '$1' . $phish_warning . '$2', $data); + } + + return $data; + } + + /** + * TODO + */ + protected function _dereferExternalReferencesCallback($m) + { + return 'href="' . Horde::externalUrl($m[2]) . '"'; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/images.php b/framework/Mime/lib/Horde/Mime/Viewer/images.php new file mode 100644 index 000000000..ced92d7b1 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/images.php @@ -0,0 +1,95 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_images extends Horde_MIME_Viewer_Driver +{ + /** + * Return the content-type. + * + * @return string The content-type of the output. + */ + public function getType() + { + $type = $this->mime_part->getType(); + if ($GLOBALS['browser']->isBrowser('mozilla') && + ($type == 'image/pjpeg')) { + /* image/jpeg and image/pjpeg *appear* to be the same + * entity, but Mozilla don't seem to want to accept the + * latter. For our purposes, we will treat them the + * same. */ + return 'image/jpeg'; + } elseif ($type == 'image/x-png') { + /* image/x-png is equivalent to image/png. */ + return 'image/png'; + } else { + return $type; + } + } + + /** + * Generate HTML output for a javascript auto-resize view window. + * + * @param string $url The URL which contains the actual image data. + * @param string $title The title to use for the page. + * + * @return string The HTML output. + */ + protected function _popupImageWindow($url, $title) + { + global $browser; + + $str = << + +$title + +EOD; + + /* Only use javascript if we are using a DOM capable browser. */ + if ($browser->getFeature('dom')) { + /* Translate '&' entities to '&' for JS URL links. */ + $url = str_replace('&', '&', $url); + + /* Javascript display. */ + $loading = _("Loading..."); + $str .= << +function resizeWindow() +{ + + var h, img = document.getElementById('disp_image'), w; + document.getElementById('splash').style.display = 'none'; + img.style.display = 'block'; + window.moveTo(0, 0); + h = img.height - (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight)); + w = img.width - (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth)); + window.resizeBy(w, h); + self.focus(); +} + +$loading +EOD; + } else { + /* Non-javascript display. */ + $img_txt = _("Image"); + $str .= << + +$img_txt + + +EOD; + } + + return $str; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/msexcel.php b/framework/Mime/lib/Horde/Mime/Viewer/msexcel.php new file mode 100644 index 000000000..7b82a6417 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/msexcel.php @@ -0,0 +1,55 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_msexcel extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the currently data using xlhtml. + * + * @param array $params Any params this Viewer may need. + * + * @return string The rendered data. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['msexcel']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['msexcel']['location']) . '
'; + } + + $data = ''; + $tmp_xls = Horde::getTempFile('horde_msexcel'); + + $fh = fopen($tmp_xls, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + $fh = popen($GLOBALS['mime_drivers']['horde']['msexcel']['location'] . " -nh $tmp_xls 2>&1", 'r'); + while (($rc = fgets($fh, 8192))) { + $data .= $rc; + } + pclose($fh); + + return $data; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/mspowerpoint.php b/framework/Mime/lib/Horde/Mime/Viewer/mspowerpoint.php new file mode 100644 index 000000000..6bef4dec6 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/mspowerpoint.php @@ -0,0 +1,55 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_mspowerpoint extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current data using ppthtml. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['mspowerpoint']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['mspowerpoint']['location']) . '
'; + } + + $data = ''; + $tmp_ppt = Horde::getTempFile('horde_mspowerpoint'); + + $fh = fopen($tmp_ppt, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + $fh = popen($GLOBALS['mime_drivers']['horde']['mspowerpoint']['location'] . " $tmp_ppt 2>&1", 'r'); + while (($rc = fgets($fh, 8192))) { + $data .= $rc; + } + pclose($fh); + + return $data; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/msword.php b/framework/Mime/lib/Horde/Mime/Viewer/msword.php new file mode 100644 index 000000000..7892fb2dd --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/msword.php @@ -0,0 +1,69 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_msword extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current data using wvWare. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['msword']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['msword']['location']) . '
'; + } + + $data = ''; + $tmp_word = Horde::getTempFile('msword'); + $tmp_output = Horde::getTempFile('msword'); + $tmp_dir = Horde::getTempDir(); + $tmp_file = str_replace($tmp_dir . '/', '', $tmp_output); + + if (OS_WINDOWS) { + $args = ' -x ' . dirname($GLOBALS['mime_drivers']['horde']['msword']['location']) . "\\wvHtml.xml -d $tmp_dir -1 $tmp_word > $tmp_output"; + } else { + $version = exec($GLOBALS['mime_drivers']['horde']['msword']['location'] . ' --version'); + if (version_compare($version, '0.7.0') >= 0) { + $args = " --charset=" . NLS::getCharset() . " --targetdir=$tmp_dir $tmp_word $tmp_file"; + } else { + $args = " $tmp_word $tmp_output"; + } + } + + $fh = fopen($tmp_word, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + exec($GLOBALS['mime_drivers']['horde']['msword']['location'] . $args); + + if (!file_exists($tmp_output)) { + return _("Unable to translate this Word document"); + } + + return file_get_contents($tmp_output); + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo.php b/framework/Mime/lib/Horde/Mime/Viewer/ooo.php new file mode 100644 index 000000000..4c82e2de4 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo.php @@ -0,0 +1,88 @@ + + * @author Jan Schneider + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_ooo extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current data. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + $use_xslt = Util::extensionExists('xslt') || function_exists('domxml_xslt_stylesheet_file'); + if ($use_xslt) { + $tmpdir = Util::createTempDir(true); + } + + require_once 'Horde/Compress.php'; + $xml_tags = array('text:p', 'table:table ', 'table:table-row', 'table:table-cell', 'table:number-columns-spanned='); + $html_tags = array('p', 'table border="0" cellspacing="1" cellpadding="0" ', 'tr bgcolor="#cccccc"', 'td', 'colspan='); + $zip = &Horde_Compress::singleton('zip'); + $list = $zip->decompress($this->mime_part->getContents(), + array('action' => HORDE_COMPRESS_ZIP_LIST)); + foreach ($list as $key => $file) { + if ($file['name'] == 'content.xml' || + $file['name'] == 'styles.xml' || + $file['name'] == 'meta.xml') { + $content = $zip->decompress($this->mime_part->getContents(), + array('action' => HORDE_COMPRESS_ZIP_DATA, + 'info' => $list, + 'key' => $key)); + if ($use_xslt) { + $fp = fopen($tmpdir . $file['name'], 'w'); + fwrite($fp, $content); + fclose($fp); + } elseif ($file['name'] == 'content.xml') { + $content = str_replace($xml_tags, $html_tags, $content); + return $content; + } + } + } + if (!Util::extensionExists('xslt')) { + return; + } + + if (function_exists('domxml_xslt_stylesheet_file')) { + // Use DOMXML + $xslt = domxml_xslt_stylesheet_file(dirname(__FILE__) . '/ooo/main_html.xsl'); + $dom = domxml_open_file($tmpdir . 'content.xml'); + $result = @$xslt->process($dom, array('metaFileURL' => $tmpdir . 'meta.xml', 'stylesFileURL' => $tmpdir . 'styles.xml', 'disableJava' => true)); + return String::convertCharset($xslt->result_dump_mem($result), 'UTF-8', NLS::getCharset()); + } else { + // Use XSLT + $xslt = xslt_create(); + $result = @xslt_process($xslt, $tmpdir . 'content.xml', + dirname(__FILE__) . '/ooo/main_html.xsl', null, null, + array('metaFileURL' => $tmpdir . 'meta.xml', 'stylesFileURL' => $tmpdir . 'styles.xml', 'disableJava' => true)); + if (!$result) { + $result = xslt_error($xslt); + } + xslt_free($xslt); + return String::convertCharset($result, 'UTF-8', NLS::getCharset()); + } + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/common.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/common.xsl new file mode 100644 index 000000000..943a5b995 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/common.xsl @@ -0,0 +1,1165 @@ + + + + + + + + + + + + + + + + + + = + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + height: ; + + + width: ; + + + height: ; + width: ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + margin-left:; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +     + + + + + + + + + + + + + + + + + + + + + + + +     + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +     + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * + * + + + + + + + + + + + + * + * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/global_document.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/global_document.xsl new file mode 100644 index 000000000..fc4579ef3 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/global_document.xsl @@ -0,0 +1,1674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Matching child document header No. + absolute-chapter-level: + encodedTitle: + globalDocumentRefToCurrentFile: + *** + + + + + + + + + + + + + + + + + + + + + + + + + Matching global document header No. + absolute-chapter-level: + encodedTitle: + contentTableURL: + *** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creation of global document helper variable for the content table.... + + + + + + + + + + + + + + + + + Finished the Creation of global document helper variable for the content table! + + + + + Creation of global document helper variable for the child documents.... + + + + + + Finished the Creation of global document helper variable for the child documents! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + level: + title: + encoded-title: + file-url: + header-no: + ** + + ** + ** + + + childrenHeadings/heading-count: + + # + title: + ** + + + + + + + + + + + + + + + + + + Creating global document variable for chapter relations.... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Finished global document variable for chapter relations! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *** new heading + currentChapterID: + currentChapterTitle: + currentChapterID: + currentHeadingNo: + headingTitle: + headingLevel: + headingNo: + newChildURL: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + only a heading, but not a chapter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + All child documents have been walked through without finding the chapter name! + childrenHeadings/heading-count: + currentHeadingNo: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Parsing the global document... + + + + + + + + Parsing the child documents... + + + + + + + + + + + + + Starting the child transformations... + + + + + + Contentable data exists as global data! + + + No Contentable global data exists! + + + + + + + + + + + + + Java method transformChildren to transform all children of a global document could not be found. Be sure to use the XT processor. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Previous document + + + | + + + + + + + + + + + + + + + + + + # + + + + + + Content Table + + + + + + | + + + + + + + + + + + + + + + + + + + + + Next document + + + ] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + **** THE HEADING VARIABLE **** + content-table-url: + + + **** new heading: + content-table-id: + child-document-no: + file-url: + out-file-url: + level: + title: + encoded-title: + absolute-chapter-level: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + width: + + + + + + + + + + + + + + + + + + + + + + + + + + + + align: right + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/main_html.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/main_html.xsl new file mode 100644 index 000000000..443182a3e --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/main_html.xsl @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CSS helper variable will be created.... + + CSS variable ready, header will be created.... + + + CSS header creation finished! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + description + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creating the inline styles.... + + + + + Time for instantiating style variable: ms + + + + + + Creating the inline styles.... + + + + + Time for instantiating style variable: ms + + + + + + + + + + + Parameter dpi: + Parameter metaFileURL: + Parameter stylesFileURL: + Parameter absoluteSourceDirRef: + Parameter precedingChapterLevel1 : + Parameter precedingChapterLevel2 : + Parameter precedingChapterLevel3 : + Parameter precedingChapterLevel4 : + Parameter precedingChapterLevel5 : + Parameter precedingChapterLevel6 : + Parameter precedingChapterLevel7 : + Parameter precedingChapterLevel8 : + Parameter precedingChapterLevel9 : + Parameter precedingChapterLevel10: + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/palm.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/palm.xsl new file mode 100644 index 000000000..212edb167 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/palm.xsl @@ -0,0 +1,404 @@ + + + + + + + + + + + + + PalmComputingPlatform + true + + + HandheldFriendly + true + + + HistoryListText + Dateimanager : &date &time + + + description + StarPortal + + + keywords + starportal, staroffice, software + + + Content-Type + text/html; charset=iso-8859-1 + + + + + + + + + + + + + + + + + left + + + right + + + center + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + + + right + + + center + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #000000 + + + #FFFFFF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #000000 + + + #FFFFFF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_header.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_header.xsl new file mode 100644 index 000000000..eeb0c204a --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_header.xsl @@ -0,0 +1,379 @@ + + + + + + + + + + + + + The CSS style header method for setting styles + + + text/css + + + + + + + + + + + + + + + + + + + + + + + + + + + // + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + *.OOo_defaults + + + , + + + + + , + + + + { + margin-top:0cm; margin-bottom:0cm; } + + + + + + + + + + + + + + + + + + + + + + , + + + + + , + + + + + + + + + + + + + + { + + + } + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_inlined.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_inlined.xsl new file mode 100644 index 000000000..19159958c --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_inlined.xsl @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_mapping.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_mapping.xsl new file mode 100644 index 000000000..a9a858dc0 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/style_mapping.xsl @@ -0,0 +1,660 @@ + + + + + + + + + + + + + + + + + + + + + + + + float: right; + + + float: left; + + + + + + + + align: left; + + + align: right; + + + align: center; + + + + + + + + padding: + + ; + + + + + + + + + border-width:; + border-style:; + border-color:; + + + border-width:; + border-style:; + border-color:; + + + border-width:; + border-style:; + border-color:; + + + + + border-top: ; + + + border-bottom: ; + + + border-left: ; + + + border-right: ; + + + + + + width:; + + + width:; + + + + + + + + height:; + + + height:; + + + + + + + + width:; + + + width:; + + + + + + :; + + + font-family: + + + ; + + font-style:italic; + + + font-weight:bold; + + + + :; + + + :; + + + :; + + + :; + + + :; + + + :; + + + :; + + + :; + + + :; + + + + + + text-align:left ! important; + + + text-align:right ! important; + + + text-align: ! important; + + + + + :; + + + background-color:; + + + background-color:; + + + background-image:url(); + + + background-repeat:repeat; + + + background-repeat:no-repeat; + + + + + + :; + + + + text-decoration:line-through; + + + + + text-decoration:underline; + + + + + vertical-align:sub; + + + vertical-align:sup; + + + + + + + + + + + + + + + + + + + italic, + + + + + + + bold, + + + + + + underline, + + + + + + + align:left, + + + align:right, + + + align:center, + + + + + + + strike, + + + + + size::size, + + + + + + + color:#FFFFFF, + + + color:#000000, + + + + + + + + size::size, + + + + + + width::width, + + + width::width; + + + + + + + + height::height; + + + height::height; + + + + + + + + width::width; + + + width::width; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/table.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table.xsl new file mode 100644 index 000000000..36339ed73 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table.xsl @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + left + + + right + + + center + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + maxRowLength: + + numberOfHiddenColumns: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + #000000 + 2 + 0 + page-break-inside:avoid + + + + + + + + + + + + + + + + Time for checking BorderStyle: ms + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_cells.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_cells.xsl new file mode 100644 index 000000000..4671ea96f --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_cells.xsl @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + +--------------> table:table-cell has been entered with node value: + table:number-columns-repeated: -- + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NEW VALUE: column-position: -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +++++++++ starting cell writing +++++++++ + number-columns-repeated: -- + maxRowLength: -- + column-position: -- + + + + + + + + + + + + +++++++++ cell repetition +++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WriteTest -> If nothing between '-' write cell -- + + + + + TABLE COLUMN is hidden! + + + + + + + + TABLE COLUMN is hidden! + + + + + + + + + + + th + + + td + + + + + + + + + + + +*****************************************'' element has been added! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text-align:right; + text-align:left; + + + + + + + + + + + + + + + + + + + + text-align:right; + + + text-align:left; + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text-align:right; + + + text-align:left; + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + + ; + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_columns.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_columns.xsl new file mode 100644 index 000000000..a9a907ff8 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_columns.xsl @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DebugInformation: For each 'column-style-entry' of the 'allColumnStyleEntries' variable the style-name is given out. + In case of 'column-hidden-flag' attribute the text 'column is hidden' is given out. + + + + + column is hidden + + + + = + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_rows.xsl b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_rows.xsl new file mode 100644 index 000000000..6f7d17d62 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/ooo/table_rows.xsl @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +*************************'tr' element has been added! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/framework/Mime/lib/Horde/Mime/Viewer/pdf.php b/framework/Mime/lib/Horde/Mime/Viewer/pdf.php new file mode 100644 index 000000000..40e46eca7 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/pdf.php @@ -0,0 +1,26 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_pdf extends Horde_MIME_Viewer_Driver +{ + /** + * Return the content-type. + * + * @return string The content-type of the output. + */ + public function getType() + { + return 'application/pdf'; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/php.php b/framework/Mime/lib/Horde/Mime/Viewer/php.php new file mode 100644 index 000000000..0c0095487 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/php.php @@ -0,0 +1,138 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_php extends Horde_MIME_Viewer_source +{ + /** + * Renders out the contents. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + ini_set('highlight.comment', 'comment'); + ini_set('highlight.default', 'default'); + ini_set('highlight.keyword', 'keyword'); + ini_set('highlight.string', 'string'); + ini_set('highlight.html', 'html'); + + $code = $this->mime_part->getContents(); + if (strpos($code, 'lineNumber(str_replace('<?php ', '', highlight_string('lineNumber(highlight_string($code, true)); + } + + // Educated guess at whether we are inline or not. + if (headers_sent() || ob_get_length()) { + return $results; + } else { + return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') + . $results + . Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); + } + } + + /** + * Add line numbers to a block of code. + * + * @param string $code The code to number. + */ + public function lineNumber($code, $linebreak = "\n") + { + // Clean up. + $code = preg_replace(array('/\s*/', + '/\s*/', + '/\s*<\/span>\s*<\/span>\s*<\/code>/', + '/\s*<\/font>\s*<\/font>\s*<\/code>/'), + '', + $code); + $code = str_replace(array(' ', + '&', + '
', + '', + ), + array(' ', + '&', + "\n", + '', + ), + $code); + $code = trim($code); + + // Normalize newlines. + $code = str_replace("\r", '', $code); + $code = preg_replace('/\n\n\n+/', "\n\n", $code); + + $lines = explode("\n", $code); + + $results = array('
    '); + $previous = false; + foreach ($lines as $lineno => $line) { + if (substr($line, 0, 7) == '') { + $previous = false; + $line = substr($line, 7); + } + + if (empty($line)) { + $line = ' '; + } + + if ($previous) { + $line = "" . $line; + } + + // Save the previous style. + if (strpos($line, '') { + $previous = false; + } elseif ($previous) { + $line .= ''; + } + + $results[] = '
  1. ' . $line . '
  2. '; + } + + $results[] = '
'; + return implode("\n", $results); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/plain.php b/framework/Mime/lib/Horde/Mime/Viewer/plain.php new file mode 100644 index 000000000..ad0aa17b7 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/plain.php @@ -0,0 +1,83 @@ + + * @author Michael Slusarz + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_plain extends Horde_MIME_Viewer_Driver +{ + /** + * Can this driver render various views? + * + * @var boolean + */ + protected $_canrender = array( + 'full' => true, + 'info' => false, + 'inline' => true, + ); + + /** + * Render the contents. + * + * @return array TODO + */ + protected function _render() + { + $text = $this->_mimepart->getContents(); + $charset = $this->_mimepart->getCharset(); + + /* Check for 'flowed' text data. */ + if ($this->_mimepart->getContentTypeParameter('format') == 'flowed') { + $text = $this->_formatFlowed($text, $this->_mimepart->getContentTypeParameter('delsp')); + } + + require_once 'Horde/Text/Filter.php'; + return array( + 'data' => '' . Text_Filter::filter($text, 'text2html', array('parselevel' => TEXT_HTML_MICRO, 'charset' => $charset, 'class' => null)) . '', + 'type' => 'text/html; charset=' . $charset; + ); + } + + /** + * Render the contents for inline viewing. + * + * @return string The rendered contents. + */ + protected function _renderInline() + { + $text = String::convertCharset($this->_mimepart->getContents(), $this->_mimepart->getCharset()); + + /* Check for 'flowed' text data. */ + return ($this->_mimepart->getContentTypeParameter('format') == 'flowed') + ? $this->_formatFlowed($text, $this->_mimepart->getContentTypeParameter('delsp')) + : $text; + } + + /** + * Format flowed text for HTML output. + * + * @param string $text The text to format. + * @param boolean $delsp Was text created with DelSp formatting? + * + * @return string The formatted text. + */ + protected function _formatFlowed($text, $delsp = null) + { + require_once 'Text/Flowed.php'; + $flowed = new Text_Flowed($this->_mimepart->replaceEOL($text, "\n"), $this->_mimepart->getCharset()); + $flowed->setMaxLength(0); + if (!is_null($delsp)) { + $flowed->setDelSp($delsp); + } + return $flowed->toFixed(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/rar.php b/framework/Mime/lib/Horde/Mime/Viewer/rar.php new file mode 100644 index 000000000..5fe863aa1 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/rar.php @@ -0,0 +1,197 @@ + + * @author Michael Cochrane + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_rar extends Horde_MIME_Viewer_Driver +{ + /** + * Rar compression methods. + * + * @var array + */ + protected $_methods = array( + 0x30 => 'Store', + 0x31 => 'Fastest', + 0x32 => 'Fast', + 0x33 => 'Normal', + 0x34 => 'Good', + 0x35 => 'Best' + ); + + /** + * Render out the currently set contents using rar. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + $contents = $this->mime_part->getContents(); + + /* Make sure this is a valid rar file. */ + if ($this->checkRarData($contents) === false) { + return '
' . _("This does not appear to be a valid rar archive.") . '
'; + } + + require_once 'Horde/Text.php'; + + $rarData = $this->getRarData($contents); + $fileCount = count($rarData); + + $text = '' . htmlspecialchars(sprintf(_("Contents of \"%s\""), $this->mime_part->getName())) . ':' . "\n"; + $text .= '
'; + $text .= Text::htmlAllSpaces(_("Archive Name") . ': ' . $this->mime_part->getName()) . "\n"; + $text .= Text::htmlAllSpaces(_("Archive File Size") . ': ' . strlen($contents) . ' bytes') . "\n"; + $text .= Text::htmlAllSpaces(sprintf(ngettext("File Count: %d file", "File Count: %d files", $fileCount), $fileCount)); + $text .= "\n\n"; + $text .= Text::htmlAllSpaces( + String::pad(_("File Name"), 50, ' ', STR_PAD_RIGHT) . + String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) . + String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) . + String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) . + String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) . + String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT) + ) . "\n"; + + $text .= str_repeat('-', 109) . "\n"; + + foreach ($rarData as $val) { + $ratio = (empty($val['size'])) ? 0 : 100 * ($val['csize'] / $val['size']); + $text .= Text::htmlAllSpaces( + String::pad($val['name'], 50, ' ', STR_PAD_RIGHT) . + String::pad($val['attr'], 10, ' ', STR_PAD_LEFT) . + String::pad($val['size'], 10, ' ', STR_PAD_LEFT) . + String::pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) . + String::pad($val['method'], 10, ' ', STR_PAD_LEFT) . + String::pad(sprintf("%1.1f%%", $ratio), 10, ' ', STR_PAD_LEFT) + ) . "\n"; + } + + $text .= str_repeat('-', 106) . "\n"; + $text .= '
'; + + return nl2br($text); + } + + /** + * Returns the MIME type of this part. + * + * @return string The MIME type of this part. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } + + /** + * Checks to see if the data is a valid Rar archive. + * + * @param string &$data The rar archive data. + * + * @return boolean True if valid, false if invalid. + */ + public function checkRarData(&$data) + { + $fileHeader = "\x52\x61\x72\x21\x1a\x07\x00"; + if (strpos($data, $fileHeader) === false) { + return false; + } else { + return true; + } + } + + /** + * Get the list of files/data from the rar archive. + * + * @param string &$data The rar archive data. + * + * @return array KEY: Position in RAR archive + * VALUES: 'attr' -- File attributes + * 'date' -- File modification time + * 'csize' -- Compressed file size + * 'method' -- Compression method + * 'name' -- Filename + * 'size' -- Original file size + */ + public function getRarData(&$data) + { + $return_array = array(); + + $blockStart = strpos($data, "\x52\x61\x72\x21\x1a\x07\x00"); + $position = $blockStart + 7; + + while ($position < strlen($data)) { + $head_crc = substr($data, $position + 0, 2); + $head_type = ord(substr($data, $position + 2, 1)); + $head_flags = unpack('vFlags', substr($data, $position + 3, 2)); + $head_flags = $head_flags['Flags']; + $head_size = unpack('vSize', substr($data, $position + 5, 2)); + $head_size = $head_size['Size']; + + $position += 7; + $head_size -= 7; + + switch ($head_type) { + + case 0x73: + /* Archive header */ + $position += $head_size; + + break; + + case 0x74: + $file = array(); + + /* File Header */ + $info = unpack('VPacked/VUnpacked/COS/VCRC32/VTime/CVersion/CMethod/vLength/vAttrib', substr($data, $position)); + + $file['name'] = substr($data, $position + 25, $info['Length']); + $file['size'] = $info['Unpacked']; + $file['csize'] = $info['Packed']; + + $file['date'] = mktime((($info['Time'] >> 11) & 0x1f), + (($info['Time'] >> 5) & 0x3f), + (($info['Time'] << 1) & 0x3e), + (($info['Time'] >> 21) & 0x07), + (($info['Time'] >> 16) & 0x1f), + ((($info['Time'] >> 25) & 0x7f) + 80)); + + $file['method'] = $this->_methods[$info['Method']]; + + $file['attr'] = ''; + $file['attr'] .= ($info['Attrib'] & 0x10) ? 'D' : '-'; + $file['attr'] .= ($info['Attrib'] & 0x20) ? 'A' : '-'; + $file['attr'] .= ($info['Attrib'] & 0x03) ? 'S' : '-'; + $file['attr'] .= ($info['Attrib'] & 0x02) ? 'H' : '-'; + $file['attr'] .= ($info['Attrib'] & 0x01) ? 'R' : '-'; + + $return_array[] = $file; + + $position += $head_size; + $position += $info['Packed']; + break; + + default: + $position += $head_size; + if (isset($add_size)) { + $position += $add_size; + } + break; + + } + } + + return $return_array; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/report.php b/framework/Mime/lib/Horde/Mime/Viewer/report.php new file mode 100644 index 000000000..89197e62e --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/report.php @@ -0,0 +1,89 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_report extends Horde_MIME_Viewer_Driver +{ + /** + * Stores the Horde_MIME_Viewer of the specified protocol. + * + * @var Horde_MIME_Viewer + */ + protected $_viewer; + + /** + * Render the multipart/report data. + * + * @param array $params An array of parameters needed. + * + * @return string The rendered data. + */ + public function render($params = array()) + { + /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ + if (!($this->_resolveViewer())) { + return; + } + + /* Render using the loaded Horde_MIME_Viewer object. */ + return $this->_viewer->render($params); + } + + /** + * Returns the content-type of the Viewer used to view the part. + * + * @return string A content-type string. + */ + public function getType() + { + /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ + if (!($this->_resolveViewer())) { + return 'application/octet-stream'; + } else { + return $this->_viewer->getType(); + } + } + + /** + * Load a Horde_MIME_Viewer according to the report-type parameter stored + * in the MIME_Part to render. If unsuccessful, try to load a generic + * multipart Horde_MIME_Viewer. + * + * @return boolean True on success, false on failure. + */ + protected function _resolveViewer() + { + $type = $viewer = null; + + if (empty($this->_viewer)) { + if (($type = $this->mime_part->getContentTypeParameter('report-type'))) { + $viewer = &Horde_MIME_Viewer::factory($this->mime_part, 'message/' . String::lower($type)); + $type = $this->mime_part->getPrimaryType(); + } else { + /* If report-type is missing, the message is an improper + * multipart/report message. Attempt to fall back to a + * multipart/mixed viewer instead. */ + $type = 'multipart'; + } + + if (empty($viewer) || + (String::lower(get_class($viewer)) == 'mime_viewer_default')) { + if (!($viewer = &Horde_MIME_Viewer::factory($this->mime_part, $type . '/*'))) { + return false; + } + } + $this->_viewer = $viewer; + } + + return true; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/rfc822.php b/framework/Mime/lib/Horde/Mime/Viewer/rfc822.php new file mode 100644 index 000000000..b8a10be20 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/rfc822.php @@ -0,0 +1,98 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_rfc822 extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the currently set contents. + * + * @param array $params An array with any parameters needed. + * + * @return string The rendered text. + */ + public function render($params = array()) + { + if (!$this->mime_part) { + return $this->formatStatusMsg(_("There was an error displaying this message part")); + } + + $part = &Util::cloneObject($this->mime_part); + $part->transferDecodeContents(); + $text = $part->getContents(); + + return $text + ? $text + : $this->formatStatusMsg(_("There was an error displaying this message part")); + } + + /** + * Render out attachment information. + * + * @param array $params An array with any parameters needed. + * + * @return string The rendered text in HTML. + */ + public function renderAttachmentInfo($params = array()) + { + if (!$this->mime_part) { + return ''; + } + + /* Get the text of the part. Since we need to look for the end of + * the headers by searching for the CRLFCRLF sequence, use + * getCanonicalContents() to make sure we are getting the text with + * CRLF's. */ + $text = $this->mime_part->getCanonicalContents(); + if (empty($text)) { + return ''; + } + + /* Search for the end of the header text (CRLFCRLF). */ + $text = substr($text, 0, strpos($text, "\r\n\r\n")); + + /* Get the list of headers now. */ + require_once 'Horde/MIME/Headers.php'; + $headers = Horde_MIME_Headers::parseHeaders($text); + + $header_array = array( + 'date' => _("Date"), + 'from' => _("From"), + 'to' => _("To"), + 'cc' => _("Cc"), + 'bcc' => _("Bcc"), + 'reply-to' => _("Reply-To"), + 'subject' => _("Subject") + ); + $header_output = array(); + + foreach ($header_array as $key => $val) { + $hdr = $headers->getValue($key); + if (!empty($hdr)) { + $header_output[] = '' . $val . ': ' . htmlspecialchars($hdr); + } + } + + require_once 'Horde/Text/Filter.php'; + return '
' . Text_Filter::filter(implode("
\n", $header_output), 'emails') . '
'; + } + + /** + * Return the MIME content type for the rendered data. + * + * @return string The content type of the data. + */ + public function getType() + { + return 'text/plain; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/richtext.php b/framework/Mime/lib/Horde/Mime/Viewer/richtext.php new file mode 100644 index 000000000..e8c696565 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/richtext.php @@ -0,0 +1,152 @@ +" to + * "<", converts CRLFs to SPACE, converts to a newline according to + * local newline convention, removes everything between a command + * and the next balancing command, and removes all other + * formatting commands (all text enclosed in angle brackets). + * + * We implement the following tags: + * , , , , , ,
, + * , , , , , , + * , , , , + * + * The following tags are implemented differently than described in the RFC + * (due to limitations in HTML output): + * - Output as centered, bold text. + * - Output as centered, bold text. + * - Output as paragraph break. + * + * The following tags are NOT implemented: + * , , , , , + * , + * + * Copyright 2004-2008 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @author Michael Slusarz + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_richtext extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the currently set contents in HTML format. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + if (($text = $this->mime_part->getContents()) === false) { + return false; + } + + if (trim($text) == '') { + return $text; + } + + /* Use str_ireplace() if using PHP 5.0+. */ + $has_str_ireplace = function_exists('str_ireplace'); + + /* We add space at the beginning and end of the string as it will + * make some regular expression checks later much easier (so we + * don't have to worry about start/end of line characters). */ + $text = ' ' . $text . ' '; + + /* Remove everything between tags. */ + $text = preg_replace('/.*<\/comment>/Uis', '', $text); + + /* Remove any unrecognized tags in the text. We don't need + * in $tags since it doesn't do anything anyway. All tags + * have already been removed. */ + $tags = '
'; + $text = strip_tags($text, $tags); + + /* becomes a '<'. CRLF becomes a SPACE. */ + if ($has_str_ireplace) { + $text = str_ireplace(array('', "\r\n"), array('<', ' '), $text); + } else { + $text = preg_replace(array('//i', "/\r\n/"), array('<', ' '), $text); + } + + /* We try to protect against bad stuff here. */ + $text = @htmlspecialchars($text, ENT_QUOTES, $this->mime_part->getCharset()); + + /* becomes a newline (
); + * becomes a paragraph break (

). */ + if ($has_str_ireplace) { + $text = str_ireplace(array('<nl>', '<np>'), array('
', '

'), $text); + } else { + $text = preg_replace(array('/(?', '

'), $text); + } + + /* Now convert the known tags to html. Try to remove any tag + * parameters to stop people from trying to pull a fast one. */ + $pattern = array( + '/(?\1', + '\1', + '\1', + '\1', + '\1', + '\1', + '

\1
', + '
\1
', + '
\1
', + '
\1
', + '\1', + '\1', + '\1', + '
\1

', + '
\1

', + '

\1

', + '
\1
', + ); + $text = preg_replace($pattern, $replace, $text); + + /* Now we remove the leading/trailing space we added at the start. */ + $text = substr($text, 1, -1); + + /* Wordwrap. */ + $text = str_replace(array("\t", ' ', "\n "), array(' ', '  ', "\n "), $text); + if ($text[0] == ' ') { + $text = ' ' . substr($text, 1); + } + + return '

' . nl2br($text) . '

'; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/rpm.php b/framework/Mime/lib/Horde/Mime/Viewer/rpm.php new file mode 100644 index 000000000..5c12665b6 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/rpm.php @@ -0,0 +1,55 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_rpm extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the RPM contents. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['rpm']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['rpm']['location']) . '
'; + } + + $data = ''; + $tmp_rpm = Horde::getTempFile('horde_rpm'); + + $fh = fopen($tmp_rpm, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + $fh = popen($GLOBALS['mime_drivers']['horde']['rpm']['location'] . " -qip $tmp_rpm 2>&1", 'r'); + while (($rc = fgets($fh, 8192))) { + $data .= $rc; + } + pclose($fh); + + return '
' . htmlentities($data) . '
'; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/rtf.php b/framework/Mime/lib/Horde/Mime/Viewer/rtf.php new file mode 100644 index 000000000..e48e63466 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/rtf.php @@ -0,0 +1,57 @@ + + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @author Duck + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_rtf extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current data using UnRTF. + * + * @param array $params Any parameters the viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['rtf']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['rtf']['location']) . '
'; + } + + $tmp_rtf = Horde::getTempFile('rtf'); + $tmp_output = Horde::getTempFile('rtf'); + $args = " $tmp_rtf > $tmp_output"; + + $fh = fopen($tmp_rtf, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + exec($GLOBALS['mime_drivers']['horde']['rtf']['location'] . $args); + + if (!file_exists($tmp_output)) { + return _("Unable to translate this RTF document"); + } + + return file_get_contents($tmp_output); + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/security.php b/framework/Mime/lib/Horde/Mime/Viewer/security.php new file mode 100644 index 000000000..480b6e441 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/security.php @@ -0,0 +1,88 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_security extends Horde_MIME_Viewer_Driver +{ + /** + * Stores the Horde_MIME_Viewer of the specified security protocol. + * + * @var Horde_MIME_Viewer + */ + protected $_viewer; + + /** + * The $mime_part class variable has the information to render + * out, encapsulated in a Horde_MIME_Part object. + * + * @param $params mixed The parameters (if any) to pass to the underlying + * Horde_MIME_Viewer. + * + * @return string Rendering of the content. + */ + public function render($params = array()) + { + /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ + if (!($this->_resolveViewer())) { + return; + } + + /* Render using the loaded Horde_MIME_Viewer object. */ + return $this->_viewer->render($params); + } + + /** + * Returns the content-type of the Viewer used to view the part. + * + * @return string A content-type string. + */ + public function getType() + { + /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ + if (!($this->_resolveViewer())) { + return 'application/octet-stream'; + } else { + return $this->_viewer->getType(); + } + } + + /** + * Load a Horde_MIME_Viewer according to the protocol parameter stored + * in the Horde_MIME_Part to render. If unsuccessful, try to load a generic + * multipart Horde_MIME_Viewer. + * + * @return boolean True on success, false on failure. + */ + protected function _resolveViewer() + { + $viewer = null; + + if (empty($this->_viewer)) { + $protocol = $this->mime_part->getContentTypeParameter('protocol'); + if (empty($protocol)) { + return false; + } + $viewer = &Horde_MIME_Viewer::factory($this->mime_part, $protocol); + if (empty($viewer) || + (String::lower(get_class($viewer)) == 'mime_viewer_default')) { + $viewer = &Horde_MIME_Viewer::factory($this->mime_part, $this->mime_part->getPrimaryType() . '/*'); + if (empty($viewer)) { + return false; + } + } + $this->_viewer = $viewer; + } + + return true; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/simple.php b/framework/Mime/lib/Horde/Mime/Viewer/simple.php new file mode 100644 index 000000000..d2eecd342 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/simple.php @@ -0,0 +1,25 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_simple extends Horde_MIME_Viewer_Driver +{ + /** + * Return the MIME type of the rendered content. + * + * @return string MIME-type of the output content. + */ + public function getType() + { + return 'text/plain'; + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/smil.php b/framework/Mime/lib/Horde/Mime/Viewer/smil.php new file mode 100644 index 000000000..8f521a481 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/smil.php @@ -0,0 +1,98 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_smil extends Horde_MIME_Viewer_Driver +{ + /** + * Handle for the XML parser object. + * + * @var resource + */ + protected $_parser; + + /** + * String buffer to hold the generated content + * + * @var string + */ + protected $_content = ''; + + /** + * Renders out the contents. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Create a new parser and set its default properties. */ + $this->_parser = xml_parser_create(); + xml_set_object($this->_parser, $this); + xml_set_element_handler($this->_parser, '_startElement', '_endElement'); + xml_set_character_data_handler($this->_parser, '_defaultHandler'); + xml_parse($this->_parser, $this->mime_part->getContents(), true); + return $this->_content; + } + + /** + * User-defined function callback for start elements. + * + * @param object $parser Handle to the parser instance. + * @param string $name The name of this XML element. + * @param array $attrs List of this element's attributes. + */ + protected function _startElement($parser, $name, $attrs) + { + switch ($name) { + case 'IMG': + if (isset($attrs['SRC'])) { + $this->_content .= ''; + } + break; + } + } + + /** + * User-defined function callback for end elements. + * + * @param object $parser Handle to the parser instance. + * @param string $name The name of this XML element. + */ + protected function _endElement($parser, $name) + { + } + + /** + * User-defined function callback for character data. + * + * @param object $parser Handle to the parser instance. + * @param string $data String of character data. + */ + protected function _defaultHandler($parser, $data) + { + $data = trim($data); + if (!empty($data)) { + $this->_content .= ' ' . htmlspecialchars($data); + } + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/source.php b/framework/Mime/lib/Horde/Mime/Viewer/source.php new file mode 100644 index 000000000..336946be5 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/source.php @@ -0,0 +1,40 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_source extends Horde_MIME_Viewer_Driver +{ + /** + * Add line numbers to a block of code. + * + * @param string $code The code to number. + */ + public function lineNumber($code, $linebreak = "\n") + { + $lines = substr_count($code, $linebreak) + 1; + $html = '
'; + for ($l = 1; $l <= $lines; $l++) { + $html .= sprintf('%s
', $l, $l, $l) . "\n"; + } + return $html . '
' . $code . '
'; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/srchighlite.php b/framework/Mime/lib/Horde/Mime/Viewer/srchighlite.php new file mode 100644 index 000000000..aa04725a7 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/srchighlite.php @@ -0,0 +1,102 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_srchighlite extends Horde_MIME_Viewer_source +{ + /** + * Render out the currently set contents using Source-highlight + * + * @param array $params Any parameters the viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['srchighlite']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['srchighlite']['location']) . '
'; + } + + /* Create temporary files for Webcpp. */ + $tmpin = Horde::getTempFile('SrcIn'); + $tmpout = Horde::getTempFile('SrcOut', false); + + /* Write the contents of our buffer to the temporary input file. */ + $contents = $this->mime_part->getContents(); + $fh = fopen($tmpin, 'wb'); + fwrite($fh, $contents, strlen($contents)); + fclose($fh); + + /* Determine the language from the mime type. */ + $lang = ''; + switch ($this->mime_part->getType()) { + case 'text/x-java': + $lang = 'java'; + break; + + case 'text/x-csrc': + case 'text/x-c++src': + case 'text/cpp': + $lang = 'cpp'; + break; + + case 'application/x-perl': + $lang = 'perl'; + break; + + case 'application/x-php': + case 'x-extension/phps': + case 'x-extension/php3s': + case 'application/x-httpd-php': + case 'application/x-httpd-php3': + case 'application/x-httpd-phps': + $lang = 'php3'; + break; + + case 'application/x-python': + $lang = 'python'; + break; + + // $lang = 'prolog'; + // break; + + // $lang = 'flex'; + // break; + + // $lang = 'changelog'; + // break; + + // $lang = 'ruby'; + // break; + } + + /* Execute Source-Highlite. */ + exec($GLOBALS['mime_drivers']['horde']['srchighlite']['location'] . " --src-lang $lang --out-format xhtml --input $tmpin --output $tmpout"); + $results = file_get_contents($tmpout); + unlink($tmpout); + + /* Educated Guess at whether we are inline or not. */ + if (headers_sent() || ob_get_length()) { + return $this->lineNumber($results); + } else { + return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') . + $this->lineNumber($results) . + Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); + } + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/tgz.php b/framework/Mime/lib/Horde/Mime/Viewer/tgz.php new file mode 100644 index 000000000..4bd76649d --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/tgz.php @@ -0,0 +1,104 @@ + + * @author Michael Cochrane + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_tgz extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the currently set tar file contents. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + $contents = $this->mime_part->getContents(); + + /* Only decompress gzipped files. */ + $subtype = $this->mime_part->getSubType(); + if (($subtype == 'x-compressed-tar') || + ($subtype == 'tgz') || + ($subtype == 'x-tgz') || + ($subtype == 'gzip') || + ($subtype == 'x-gzip') || + ($subtype == 'x-gzip-compressed') || + ($subtype == 'x-gtar')) { + $gzip = &Horde_Compress::singleton('gzip'); + $contents = $gzip->decompress($contents); + if (empty($contents)) { + return _("Unable to open compressed archive."); + } elseif (is_a($contents, 'PEAR_Error')) { + return $contents->getMessage(); + } + } + + if ($subtype == 'gzip' || + $subtype == 'x-gzip' || + $subtype == 'x-gzip-compressed') { + global $conf; + require_once 'Horde/MIME/Magic.php'; + $mime_type = MIME_Magic::analyzeData($contents, isset($conf['mime']['magic_db']) ? $conf['mime']['magic_db'] : null); + if (!$mime_type) { + $mime_type = _("Unknown"); + } + return sprintf(_("Content type of compressed file: %s"), $mime_type); + } + + /* Obtain the list of files/data in the tar file. */ + $tar = Horde_Compress::factory('tar'); + $tarData = $tar->decompress($contents); + if (is_a($tarData, 'PEAR_Error')) { + return $tarData->getMessage(); + } + + $fileCount = count($tarData); + $text = '' . htmlspecialchars(sprintf(_("Contents of \"%s\""), $this->mime_part->getName())) . ':' . "\n" . + '
' . + Text::htmlAllSpaces(_("Archive Name") . ': ' . $this->mime_part->getName()) . "\n" . + Text::htmlAllSpaces(_("Archive File Size") . ': ' . strlen($contents) . ' bytes') . "\n" . + Text::htmlAllSpaces(sprintf(ngettext("File Count: %d file", "File Count: %d files", $fileCount), $fileCount)) . + "\n\n" . + Text::htmlAllSpaces( + str_pad(_("File Name"), 62, ' ', STR_PAD_RIGHT) . + str_pad(_("Attributes"), 15, ' ', STR_PAD_LEFT) . + str_pad(_("Size"), 10, ' ', STR_PAD_LEFT) . + str_pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) + ) . "\n" . + str_repeat('-', 106) . "\n"; + + foreach ($tarData as $val) { + $text .= Text::htmlAllSpaces( + str_pad($val['name'], 62, ' ', STR_PAD_RIGHT) . + str_pad($val['attr'], 15, ' ', STR_PAD_LEFT) . + str_pad($val['size'], 10, ' ', STR_PAD_LEFT) . + str_pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) + ) . "\n"; + } + + return nl2br($text . str_repeat('-', 106) . "\n" . + '
'); + } + + /** + * Return the content-type + * + * @return string The content-type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/tnef.php b/framework/Mime/lib/Horde/Mime/Viewer/tnef.php new file mode 100644 index 000000000..64856df00 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/tnef.php @@ -0,0 +1,54 @@ + + * @author Michael Slusarz + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_tnef extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current tnef data. + * + * @param array $params Any parameters the viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + require_once 'Horde/Compress.php'; + + $tnef = &Horde_Compress::singleton('tnef'); + + $data = ''; + $info = $tnef->decompress($this->mime_part->getContents()); + if (empty($info) || is_a($info, 'PEAR_Error')) { + $data .= ''; + } else { + $data .= ''; + foreach ($info as $part) { + $data .= ''; + } + } + $data .= '
' . _("MS-TNEF Attachment contained no data.") . '
' . _("Name") . '' . _("Mime Type") . '
' . $part['name'] . '' . $part['type'] . '/' . $part['subtype'] . '
'; + + return $data; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/vcard.php b/framework/Mime/lib/Horde/Mime/Viewer/vcard.php new file mode 100644 index 000000000..b116eb8b3 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/vcard.php @@ -0,0 +1,372 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_vcard extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the vcard contents. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = null) + { + global $registry, $prefs, $notification; + + require_once 'Horde/iCalendar.php'; + + $app = false; + $data = $this->mime_part->getContents(); + $html = ''; + $import_msg = null; + $title = _("vCard"); + + $iCal = new Horde_iCalendar(); + if (!$iCal->parsevCalendar($data, 'VCALENDAR', + $this->mime_part->getCharset())) { + $notification->push( + _("There was an error reading the contact data."), + 'horde.error'); + } + + if (Util::getFormData('import') && + Util::getFormData('source') && + $registry->hasMethod('contacts/import')) { + $source = Util::getFormData('source'); + $contacts = $registry->call('contacts/import', + array($data, 'text/x-vcard', $source)); + if (is_a($contacts, 'PEAR_Error')) { + $notification->push( + _("There was an error importing the contact data:") . ' ' + . $contacts->getMessage(), + 'horde.error'); + } else { + $notification->push(sprintf(ngettext( + "%d contact was successfully added to your address book.", + "%d contacts were successfully added to your address book.", + $iCal->getComponentCount()), + $iCal->getComponentCount()), + 'horde.success'); + } + } + + $html .= ''; + + $i = 0; + foreach ($iCal->getComponents() as $vc) { + if ($i > 0) { + $html .= ''; + } + ++$i; + + $html .= ''; + + $n = $vc->printableName(); + if (!empty($n)) { + $html .= $this->_row(_("Name"), $n); + } + + $aliases = $vc->getAttributeValues('ALIAS'); + if (!is_a($aliases, 'PEAR_Error')) { + $html .= $this->_row(_("Alias"), implode("\n", $aliases)); + } + $birthdays = $vc->getAttributeValues('BDAY'); + if (!is_a($birthdays, 'PEAR_Error')) { + $birthday = new Horde_Date($birthdays[0]); + $html .= $this->_row( + _("Birthday"), + $birthday->strftime($prefs->getValue('date_format'))); + } + + $photos = $vc->getAllAttributes('PHOTO'); + foreach ($photos as $photo) { + if (!isset($photo['params']['VALUE']) || + String::upper($photo['params']['VALUE']) != 'URI') { + continue; + } + $html .= $this->_row(_("Photo"), + '', + false); + } + + $labels = $vc->getAllAttributes('LABEL'); + foreach ($labels as $label) { + if (isset($label['params']['TYPE'])) { + if (!is_array($item['params']['TYPE'])) { + $item['params']['TYPE'] = array($item['params']['TYPE']); + } + } else { + $item['params']['TYPE'] = array_keys($item['params']); + } + $types = array(); + foreach ($item['params']['TYPE'] as $type) { + switch(String::upper($type)) { + case 'HOME': + $types[] = _("Home Address"); + break; + case 'WORK': + $types[] = _("Work Address"); + break; + case 'DOM': + $types[] = _("Domestic Address"); + break; + case 'INTL': + $types[] = _("International Address"); + break; + case 'POSTAL': + $types[] = _("Postal Address"); + break; + case 'PARCEL': + $types[] = _("Parcel Address"); + break; + case 'PREF': + $types[] = _("Preferred Address"); + break; + default: + $types[] = _("Address"); + break; + } + } + $html .= $this->_row(implode('/', $types), $label['value']); + } + + $adrs = $vc->getAllAttributes('ADR'); + foreach ($adrs as $item) { + if (isset($item['params']['TYPE'])) { + if (!is_array($item['params']['TYPE'])) { + $item['params']['TYPE'] = array($item['params']['TYPE']); + } + } else { + $item['params']['TYPE'] = array_keys($item['params']); + } + $address = $item['values']; + $a = array(); + if (isset($address[VCARD_ADR_STREET])) { + $a[] = $address[VCARD_ADR_STREET]; + } + if (isset($address[VCARD_ADR_LOCALITY])) { + $a[] = $address[VCARD_ADR_LOCALITY]; + } + if (isset($address[VCARD_ADR_REGION])) { + $a[] = $address[VCARD_ADR_REGION]; + } + if (isset($address[VCARD_ADR_POSTCODE])) { + $a[] = $address[VCARD_ADR_POSTCODE]; + } + if (isset($address[VCARD_ADR_COUNTRY])) { + $a[] = $address[VCARD_ADR_COUNTRY]; + } + $types = array(); + foreach ($item['params']['TYPE'] as $type) { + switch(String::upper($type)) { + case 'HOME': + $types[] = _("Home Address"); + break; + case 'WORK': + $types[] = _("Work Address"); + break; + case 'DOM': + $types[] = _("Domestic Address"); + break; + case 'INTL': + $types[] = _("International Address"); + break; + case 'POSTAL': + $types[] = _("Postal Address"); + break; + case 'PARCEL': + $types[] = _("Parcel Address"); + break; + case 'PREF': + $types[] = _("Preferred Address"); + break; + default: + $types[] = _("Address"); + break; + } + } + $html .= $this->_row(implode('/', $types), implode("\n", $a)); + } + + $numbers = $vc->getAllAttributes('TEL'); + + foreach ($numbers as $number) { + if (isset($number['params']['TYPE'])) { + if (!is_array($number['params']['TYPE'])) { + $number['params']['TYPE'] = array($number['params']['TYPE']); + } + foreach ($number['params']['TYPE'] as $type) { + $number['params'][String::upper($type)] = true; + } + } + if (isset($number['params']['FAX'])) { + $html .= $this->_row(_("Fax"), $number['value']); + } else { + if (isset($number['params']['HOME'])) { + $html .= $this->_row(_("Home Phone"), + $number['value']); + } elseif (isset($number['params']['WORK'])) { + $html .= $this->_row(_("Work Phone"), + $number['value']); + } elseif (isset($number['params']['CELL'])) { + $html .= $this->_row(_("Cell Phone"), + $number['value']); + } else { + $html .= $this->_row(_("Phone"), + $number['value']); + } + } + } + + $addresses = $vc->getAllAttributes('EMAIL'); + $emails = array(); + foreach ($addresses as $address) { + if (isset($address['params']['TYPE'])) { + if (!is_array($address['params']['TYPE'])) { + $address['params']['TYPE'] = array($address['params']['TYPE']); + } + foreach ($address['params']['TYPE'] as $type) { + $address['params'][String::upper($type)] = true; + } + } + $email = '' . htmlspecialchars($address['value']) . ''; + if (isset($address['params']['PREF'])) { + array_unshift($emails, $email); + } else { + $emails[] = $email; + } + } + + if (count($emails)) { + $html .= $this->_row(_("Email"), implode("\n", $emails), false); + } + + $title = $vc->getAttributeValues('TITLE'); + if (!is_a($title, 'PEAR_Error')) { + $html .= $this->_row(_("Title"), $title[0]); + } + + $role = $vc->getAttributeValues('ROLE'); + if (!is_a($role, 'PEAR_Error')) { + $html .= $this->_row(_("Role"), $role[0]); + } + + $org = $vc->getAttributeValues('ORG'); + if (!is_a($org, 'PEAR_Error')) { + $html .= $this->_row(_("Company"), $org[0]); + if (isset($org[1])) { + $html .= $this->_row(_("Department"), $org[1]); + } + } + + $notes = $vc->getAttributeValues('NOTE'); + if (!is_a($notes, 'PEAR_Error')) { + $html .= $this->_row(_("Notes"), $notes[0]); + } + + $url = $vc->getAttributeValues('URL'); + if (!is_a($url, 'PEAR_Error')) { + $html .= $this->_row( + _("URL"), + '' . htmlspecialchars($url[0]) + . '', + false); + } + } + + if ($registry->hasMethod('contacts/import') && + $registry->hasMethod('contacts/sources')) { + $html .= ''; + } + + $html .= '
 
'; + $fullname = $vc->getAttributeDefault('FN', false); + if ($fullname !== false) { + $html .= $fullname; + } + $html .= '
' + . Util::formInput(); + foreach ($_GET as $key => $val) { + $html .= ''; + } + + $sources = $registry->call('contacts/sources', array(true)); + if (count($sources) > 1) { + $html .= + '' + . '' + . '' + . ''; + } + + $html .= '
 
'; + + return + Util::bufferOutput( + 'include', + $registry->get('templates', 'horde') . '/common-header.inc') + . Util::bufferOutput(array($notification, 'notify'), + array('listeners' => 'status')) + . $html + . Util::bufferOutput( + 'include', + $registry->get('templates', 'horde') . '/common-footer.inc'); + } + + function _row($label, $value, $encode = true) + { + if ($encode) { + $label = htmlspecialchars($label); + $value = htmlspecialchars($value); + } + return '' . $label + . '' . nl2br($value) + . "\n"; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/webcpp.php b/framework/Mime/lib/Horde/Mime/Viewer/webcpp.php new file mode 100644 index 000000000..6c4ad0da8 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/webcpp.php @@ -0,0 +1,81 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_webcpp extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the currently set contents using Web C Plus Plus. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + protected function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['webcpp']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['webcpp']['location']) . '
'; + } + + /* Create temporary files for Webcpp. */ + $tmpin = Horde::getTempFile('WebcppIn'); + $tmpout = Horde::getTempFile('WebcppOut'); + + /* Write the contents of our buffer to the temporary input file. */ + $contents = $this->mime_part->getContents(); + $fh = fopen($tmpin, 'wb'); + fwrite($fh, $contents, strlen($contents)); + fclose($fh); + + /* Get the extension for the mime type. */ + include_once 'Horde/MIME/Magic.php'; + $ext = MIME_Magic::MIMEToExt($this->mime_part->getType()); + + /* Execute Web C Plus Plus. Specifying the in and out files didn't + work for me but pipes did. */ + exec($GLOBALS['mime_drivers']['horde']['webcpp']['location'] . " --pipe --pipe -x=$ext -l -a -t < $tmpin > $tmpout"); + $results = file_get_contents($tmpout); + + /* If we are not displaying inline, all the formatting is already + * done for us. */ + if (!$this->viewInline()) { + /* The first 2 lines are the Content-Type line and a blank line + * so we should remove them before outputting. */ + return preg_replace("/.*\n.*\n/", '', $results, 1); + } + + /* Extract the style sheet, removing any global body formatting + * if we're displaying inline. */ + $res = preg_split(';()|(
' . $body . '
'; + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + protected function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/wordperfect.php b/framework/Mime/lib/Horde/Mime/Viewer/wordperfect.php new file mode 100644 index 000000000..c65184cc3 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/wordperfect.php @@ -0,0 +1,58 @@ + + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_wordperfect extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current data using wpd2html. + * + * @param array $params Any parameters the viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + /* Check to make sure the program actually exists. */ + if (!file_exists($GLOBALS['mime_drivers']['horde']['wordperfect']['location'])) { + return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['wordperfect']['location']) . '
'; + } + + $tmp_wpd = Horde::getTempFile('wpd'); + $tmp_output = Horde::getTempFile('wpd'); + $args = " $tmp_wpd > $tmp_output"; + + $fh = fopen($tmp_wpd, 'w'); + fwrite($fh, $this->mime_part->getContents()); + fclose($fh); + + exec($GLOBALS['mime_drivers']['horde']['wordperfect']['location'] . $args); + + if (!file_exists($tmp_output)) { + return _("Unable to translate this WordPerfect document"); + } + + return file_get_contents($tmp_output); + } + + /** + * Return the MIME content type of the rendered content. + * + * @return string The content type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/Viewer/zip.php b/framework/Mime/lib/Horde/Mime/Viewer/zip.php new file mode 100644 index 000000000..ebdca0b94 --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/Viewer/zip.php @@ -0,0 +1,135 @@ + + * @author Michael Cochrane + * @package Horde_MIME_Viewer + */ +class Horde_MIME_Viewer_zip extends Horde_MIME_Viewer_Driver +{ + /** + * Render out the current zip contents. + * + * @param array $params Any parameters the Viewer may need. + * + * @return string The rendered contents. + */ + public function render($params = array()) + { + return $this->_render($this->mime_part->getContents()); + } + + /** + * Output the file list. + * + * @param string $contents The contents of the zip archive. + * @param mixed $callback The callback function to use on the zipfile + * information. + * + * @return string The file list. + */ + protected function _render($contents, $callback = null) + { + require_once 'Horde/Compress.php'; + + $zip = &Horde_Compress::factory('zip'); + + /* Make sure this is a valid zip file. */ + if ($zip->checkZipData($contents) === false) { + return '
' . _("This does not appear to be a valid zip file.")
+                . '
'; + } + + $zipInfo = $zip->decompress( + $contents, + array('action' => HORDE_COMPRESS_ZIP_LIST)); + if (is_a($zipInfo, 'PEAR_Error')) { + return $zipInfo->getMessage(); + } + $fileCount = count($zipInfo); + + /* Determine maximum file name length. */ + $maxlen = 0; + foreach ($zipInfo as $val) { + $maxlen = max($maxlen, strlen($val['name'])); + } + + require_once 'Horde/Text.php'; + + $text = '' + . htmlspecialchars(sprintf(_("Contents of \"%s\""), + $this->mime_part->getName())) + . ':' . "\n" + . '
' + . Text::htmlAllSpaces( + _("Archive Name") . ': ' . $this->mime_part->getName() . "\n" + . _("Archive File Size") . ': ' . strlen($contents) + . ' bytes' . "\n" + . sprintf( + ngettext("File Count: %d file", "File Count: %d files", + $fileCount), + $fileCount) + . "\n\n" + . String::pad(_("File Name"), $maxlen, ' ', STR_PAD_RIGHT) + . String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) + . String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) + . String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) + . String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) + . String::pad(_("CRC"), 10, ' ', STR_PAD_LEFT) + . String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT) + . "\n") + . str_repeat('-', 69 + $maxlen) . "\n"; + + foreach ($zipInfo as $key => $val) { + $ratio = (empty($val['size'])) + ? 0 + : 100 * ($val['csize'] / $val['size']); + + $val['name'] = String::pad($val['name'], + $maxlen, ' ', STR_PAD_RIGHT); + $val['attr'] = String::pad($val['attr'], + 10, ' ', STR_PAD_LEFT); + $val['size'] = String::pad($val['size'], + 10, ' ', STR_PAD_LEFT); + $val['date'] = String::pad(strftime("%d-%b-%Y %H:%M", + $val['date']), + 19, ' ', STR_PAD_LEFT); + $val['method'] = String::pad($val['method'], + 10, ' ', STR_PAD_LEFT); + $val['crc'] = String::pad($val['crc'], + 10, ' ', STR_PAD_LEFT); + $val['ratio'] = String::pad(sprintf("%1.1f%%", $ratio), + 10, ' ', STR_PAD_LEFT); + + $val = array_map(array('Text', 'htmlAllSpaces'), $val); + if (!is_null($callback)) { + $val = call_user_func($callback, $key, $val); + } + + $text .= $val['name'] . $val['attr'] . $val['size'] . $val['date'] + . $val['method'] . $val['crc'] . $val['ratio'] . "\n"; + } + + $text .= str_repeat('-', 69 + $maxlen) . "\n" + . '
'; + + return nl2br($text); + } + + /** + * Return the content-type + * + * @return string The content-type of the output. + */ + public function getType() + { + return 'text/html; charset=' . NLS::getCharset(); + } +} diff --git a/framework/Mime/lib/Horde/Mime/mime.magic.php b/framework/Mime/lib/Horde/Mime/mime.magic.php new file mode 100644 index 000000000..d63efbea0 Binary files /dev/null and b/framework/Mime/lib/Horde/Mime/mime.magic.php differ diff --git a/framework/Mime/lib/Horde/Mime/mime.mapping.php b/framework/Mime/lib/Horde/Mime/mime.mapping.php new file mode 100644 index 000000000..82aebacea --- /dev/null +++ b/framework/Mime/lib/Horde/Mime/mime.mapping.php @@ -0,0 +1,894 @@ +' where is the unknown file extension. + * + * @package Horde_MIME + * + * $Horde: framework/MIME/MIME/mime.mapping.php,v 1.18 2008/11/06 04:33:47 chuck Exp $ + * + * Generated: 11/05/08 23:30:23 by chuck on technest.org + */ +$mime_extension_map = array( + '__MAXPERIOD__' => '1', + 'ez' => 'application/andrew-inset', + 'atom' => 'application/atom+xml', + 'atomcat' => 'application/atomcat+xml', + 'atomsvc' => 'application/atomsvc+xml', + 'ccxml' => 'application/ccxml+xml', + 'davmount' => 'application/davmount+xml', + 'ecma' => 'application/ecmascript', + 'pfr' => 'application/font-tdpfr', + 'stk' => 'application/hyperstudio', + 'js' => 'application/x-javascript', + 'json' => 'application/json', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'mrc' => 'application/marc', + 'ma' => 'application/mathematica', + 'nb' => 'application/mathematica', + 'mb' => 'application/mathematica', + 'mathml' => 'application/mathml+xml', + 'mbox' => 'application/mbox', + 'mscml' => 'application/mediaservercontrol+xml', + 'mp4s' => 'application/mp4', + 'doc' => 'application/msword', + 'dot' => 'application/msword', + 'mxf' => 'application/mxf', + 'bin' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'lha' => 'application/x-lha', + 'lzh' => 'application/x-lha', + 'class' => 'application/x-java', + 'so' => 'application/x-sharedlib', + 'iso' => 'application/x-cd-image', + 'dmg' => 'application/octet-stream', + 'dist' => 'application/octet-stream', + 'distz' => 'application/octet-stream', + 'pkg' => 'application/octet-stream', + 'bpk' => 'application/octet-stream', + 'dump' => 'application/octet-stream', + 'elc' => 'application/octet-stream', + 'oda' => 'application/oda', + 'ogg' => 'application/ogg', + 'pdf' => 'application/pdf', + 'pgp' => 'application/pgp', + 'asc' => 'text/plain', + 'sig' => 'application/pgp-signature', + 'prf' => 'application/pics-rules', + 'p10' => 'application/pkcs10', + 'p7m' => 'application/pkcs7-mime', + 'p7c' => 'application/pkcs7-mime', + 'p7s' => 'application/pkcs7-signature', + 'cer' => 'application/x-x509-ca-cert', + 'crl' => 'application/pkix-crl', + 'pkipath' => 'application/pkix-pkipath', + 'pki' => 'application/pkixcmp', + 'pls' => 'audio/x-scpls', + 'ai' => 'application/illustrator', + 'eps' => 'image/x-eps', + 'ps' => 'application/postscript', + 'cww' => 'application/prs.cww', + 'rdf' => 'text/rdf', + 'rif' => 'application/reginfo+xml', + 'rnc' => 'application/relax-ng-compact-syntax', + 'rl' => 'application/resource-lists+xml', + 'rs' => 'application/rls-services+xml', + 'rsd' => 'application/rsd+xml', + 'rss' => 'text/rss', + 'rtf' => 'application/rtf', + 'sbml' => 'application/sbml+xml', + 'scq' => 'application/scvp-cv-request', + 'scs' => 'application/scvp-cv-response', + 'spq' => 'application/scvp-vp-request', + 'spp' => 'application/scvp-vp-response', + 'sdp' => 'application/vnd.stardivision.impress', + 'setpay' => 'application/set-payment-initiation', + 'setreg' => 'application/set-registration-initiation', + 'shf' => 'application/shf+xml', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'rq' => 'application/sparql-query', + 'srx' => 'application/sparql-results+xml', + 'gram' => 'application/srgs', + 'grxml' => 'application/srgs+xml', + 'ssml' => 'application/ssml+xml', + 'plb' => 'application/vnd.3gpp.pic-bw-large', + 'psb' => 'application/vnd.3gpp.pic-bw-small', + 'pvb' => 'application/vnd.3gpp.pic-bw-var', + 'tcap' => 'application/vnd.3gpp2.tcap', + 'pwn' => 'application/vnd.3m.post-it-notes', + 'aso' => 'application/vnd.accpac.simply.aso', + 'imp' => 'application/vnd.accpac.simply.imp', + 'acu' => 'application/vnd.acucobol', + 'atc' => 'application/vnd.acucorp', + 'acutc' => 'application/vnd.acucorp', + 'xdp' => 'application/vnd.adobe.xdp+xml', + 'xfdf' => 'application/vnd.adobe.xfdf', + 'ami' => 'application/vnd.amiga.ami', + 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', + 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', + 'atx' => 'application/vnd.antix.game-component', + 'mpkg' => 'application/vnd.apple.installer+xml', + 'aep' => 'application/vnd.audiograph', + 'mpm' => 'application/vnd.blueice.multipass', + 'bmi' => 'application/vnd.bmi', + 'rep' => 'application/vnd.businessobjects', + 'cdxml' => 'application/vnd.chemdraw+xml', + 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', + 'cdy' => 'application/vnd.cinderella', + 'cla' => 'application/vnd.claymore', + 'c4g' => 'application/vnd.clonk.c4group', + 'c4d' => 'application/vnd.clonk.c4group', + 'c4f' => 'application/vnd.clonk.c4group', + 'c4p' => 'application/vnd.clonk.c4group', + 'c4u' => 'application/vnd.clonk.c4group', + 'csp' => 'application/vnd.commonspace', + 'cst' => 'application/vnd.commonspace', + 'cdbcmsg' => 'application/vnd.contact.cmsg', + 'cmc' => 'application/vnd.cosmocaller', + 'clkx' => 'application/vnd.crick.clicker', + 'clkk' => 'application/vnd.crick.clicker.keyboard', + 'clkp' => 'application/vnd.crick.clicker.palette', + 'clkt' => 'application/vnd.crick.clicker.template', + 'clkw' => 'application/vnd.crick.clicker.wordbank', + 'wbs' => 'application/vnd.criticaltools.wbs+xml', + 'pml' => 'application/vnd.ctc-posml', + 'ppd' => 'application/vnd.cups-ppd', + 'curl' => 'application/vnd.curl', + 'rdz' => 'application/vnd.data-vision.rdz', + 'fe_launch' => 'application/vnd.denovo.fcselayout-link', + 'dna' => 'application/vnd.dna', + 'mlp' => 'application/vnd.dolby.mlp', + 'dpg' => 'application/vnd.dpgraph', + 'dfac' => 'application/vnd.dreamfactory', + 'mag' => 'application/vnd.ecowin.chart', + 'nml' => 'application/vnd.enliven', + 'esf' => 'application/vnd.epson.esf', + 'msf' => 'application/vnd.epson.msf', + 'qam' => 'application/vnd.epson.quickanime', + 'slt' => 'application/vnd.epson.salt', + 'ssf' => 'application/vnd.epson.ssf', + 'es3' => 'application/vnd.eszigno3+xml', + 'et3' => 'application/vnd.eszigno3+xml', + 'ez2' => 'application/vnd.ezpix-album', + 'ez3' => 'application/vnd.ezpix-package', + 'fdf' => 'application/vnd.fdf', + 'gph' => 'application/vnd.flographit', + 'ftc' => 'application/vnd.fluxtime.clip', + 'fm' => 'application/vnd.framemaker', + 'frame' => 'application/vnd.framemaker', + 'maker' => 'application/vnd.framemaker', + 'fnc' => 'application/vnd.frogans.fnc', + 'ltf' => 'application/vnd.frogans.ltf', + 'fsc' => 'application/vnd.fsc.weblaunch', + 'oas' => 'application/vnd.fujitsu.oasys', + 'oa2' => 'application/vnd.fujitsu.oasys2', + 'oa3' => 'application/vnd.fujitsu.oasys3', + 'fg5' => 'application/vnd.fujitsu.oasysgp', + 'bh2' => 'application/vnd.fujitsu.oasysprs', + 'ddd' => 'application/vnd.fujixerox.ddd', + 'xdw' => 'application/vnd.fujixerox.docuworks', + 'xbd' => 'application/vnd.fujixerox.docuworks.binder', + 'fzs' => 'application/vnd.fuzzysheet', + 'txd' => 'application/vnd.genomatix.tuxedo', + 'kml' => 'application/vnd.google-earth.kml+xml', + 'kmz' => 'application/vnd.google-earth.kmz', + 'gqf' => 'application/vnd.grafeq', + 'gqs' => 'application/vnd.grafeq', + 'gac' => 'application/vnd.groove-account', + 'ghf' => 'application/vnd.groove-help', + 'gim' => 'application/vnd.groove-identity-message', + 'grv' => 'application/vnd.groove-injector', + 'gtm' => 'application/vnd.groove-tool-message', + 'tpl' => 'application/vnd.groove-tool-template', + 'vcg' => 'application/vnd.groove-vcard', + 'zmm' => 'application/vnd.handheld-entertainment+xml', + 'hbci' => 'application/vnd.hbci', + 'les' => 'application/vnd.hhe.lesson-player', + 'hpgl' => 'application/vnd.hp-hpgl', + 'hpid' => 'application/vnd.hp-hpid', + 'hps' => 'application/vnd.hp-hps', + 'jlt' => 'application/vnd.hp-jlyt', + 'pcl' => 'application/vnd.hp-pcl', + 'pclxl' => 'application/vnd.hp-pclxl', + 'x3d' => 'application/vnd.hzn-3d-crossword', + 'mpy' => 'application/vnd.ibm.minipay', + 'afp' => 'application/vnd.ibm.modcap', + 'listafp' => 'application/vnd.ibm.modcap', + 'list3820' => 'application/vnd.ibm.modcap', + 'irm' => 'application/vnd.ibm.rights-management', + 'sc' => 'application/vnd.ibm.secure-container', + 'igl' => 'application/vnd.igloader', + 'ivp' => 'application/vnd.immervision-ivp', + 'ivu' => 'application/vnd.immervision-ivu', + 'xpw' => 'application/vnd.intercon.formnet', + 'xpx' => 'application/vnd.intercon.formnet', + 'qbo' => 'application/vnd.intu.qbo', + 'qfx' => 'application/vnd.intu.qfx', + 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', + 'irp' => 'application/vnd.irepository.package+xml', + 'xpr' => 'application/vnd.is-xpr', + 'jam' => 'application/vnd.jam', + 'rms' => 'application/vnd.jcp.javame.midlet-rms', + 'jisp' => 'application/vnd.jisp', + 'joda' => 'application/vnd.joost.joda-archive', + 'ktz' => 'application/vnd.kahootz', + 'ktr' => 'application/vnd.kahootz', + 'karbon' => 'application/x-karbon', + 'chrt' => 'application/x-kchart', + 'kfo' => 'application/x-kformula', + 'flw' => 'application/x-kivio', + 'kon' => 'application/x-kontour', + 'kpr' => 'application/x-kpresenter', + 'kpt' => 'application/x-kpresenter', + 'ksp' => 'application/x-kspread', + 'kwd' => 'application/x-kword', + 'kwt' => 'application/x-kword', + 'htke' => 'application/vnd.kenameaapp', + 'kia' => 'application/vnd.kidspiration', + 'kne' => 'application/vnd.kinar', + 'knp' => 'application/vnd.kinar', + 'skp' => 'application/vnd.koan', + 'skd' => 'application/vnd.koan', + 'skt' => 'application/vnd.koan', + 'skm' => 'application/vnd.koan', + 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', + 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', + '123' => 'application/vnd.lotus-1-2-3', + 'apr' => 'application/vnd.lotus-approach', + 'pre' => 'application/vnd.lotus-freelance', + 'nsf' => 'application/vnd.lotus-notes', + 'org' => 'application/vnd.lotus-organizer', + 'scm' => 'text/x-scheme', + 'lwp' => 'application/vnd.lotus-wordpro', + 'portpkg' => 'application/vnd.macports.portpkg', + 'mcd' => 'application/vnd.mcd', + 'mc1' => 'application/vnd.medcalcdata', + 'cdkey' => 'application/vnd.mediastation.cdkey', + 'mwf' => 'application/vnd.mfer', + 'mfm' => 'application/vnd.mfmp', + 'flo' => 'application/vnd.micrografx.flo', + 'igx' => 'application/vnd.micrografx.igx', + 'mif' => 'application/x-mif', + 'daf' => 'application/vnd.mobius.daf', + 'dis' => 'application/vnd.mobius.dis', + 'mbk' => 'application/vnd.mobius.mbk', + 'mqy' => 'application/vnd.mobius.mqy', + 'msl' => 'application/vnd.mobius.msl', + 'plc' => 'application/vnd.mobius.plc', + 'txf' => 'application/vnd.mobius.txf', + 'mpn' => 'application/vnd.mophun.application', + 'mpc' => 'application/vnd.mophun.certificate', + 'xul' => 'application/vnd.mozilla.xul+xml', + 'cil' => 'application/vnd.ms-artgalry', + 'asf' => 'video/x-ms-asf', + 'cab' => 'application/vnd.ms-cab-compressed', + 'xls' => 'application/vnd.ms-excel', + 'xlm' => 'application/vnd.ms-excel', + 'xla' => 'application/vnd.ms-excel', + 'xlc' => 'application/vnd.ms-excel', + 'xlt' => 'application/vnd.ms-excel', + 'xlw' => 'application/vnd.ms-excel', + 'eot' => 'application/vnd.ms-fontobject', + 'chm' => 'application/x-chm', + 'ims' => 'application/vnd.ms-ims', + 'lrm' => 'application/vnd.ms-lrm', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pps' => 'application/vnd.ms-powerpoint', + 'pot' => 'text/x-gettext-translation-template', + 'mpp' => 'application/vnd.ms-project', + 'mpt' => 'application/vnd.ms-project', + 'wps' => 'application/vnd.ms-works', + 'wks' => 'application/vnd.lotus-1-2-3', + 'wcm' => 'application/vnd.ms-works', + 'wdb' => 'application/vnd.ms-works', + 'wpl' => 'application/vnd.ms-wpl', + 'xps' => 'application/vnd.ms-xpsdocument', + 'mseq' => 'application/vnd.mseq', + 'mus' => 'application/vnd.musician', + 'msty' => 'application/vnd.muvee.style', + 'nlu' => 'application/vnd.neurolanguage.nlu', + 'nnd' => 'application/vnd.noblenet-directory', + 'nns' => 'application/vnd.noblenet-sealer', + 'nnw' => 'application/vnd.noblenet-web', + 'ngdat' => 'application/vnd.nokia.n-gage.data', + 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', + 'rpst' => 'application/vnd.nokia.radio-preset', + 'rpss' => 'application/vnd.nokia.radio-presets', + 'edm' => 'application/vnd.novadigm.edm', + 'edx' => 'application/vnd.novadigm.edx', + 'ext' => 'application/vnd.novadigm.ext', + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'otc' => 'application/vnd.oasis.opendocument.chart-template', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'otf' => 'application/vnd.oasis.opendocument.formula-template', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'oti' => 'application/vnd.oasis.opendocument.image-template', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'otm' => 'application/vnd.oasis.opendocument.text-master', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web', + 'xo' => 'application/vnd.olpc-sugar', + 'dd2' => 'application/vnd.oma.dd2+xml', + 'oxt' => 'application/vnd.openofficeorg.extension', + 'dp' => 'application/vnd.osgi.dp', + 'prc' => 'application/vnd.palm', + 'pdb' => 'application/vnd.palm', + 'pqa' => 'application/vnd.palm', + 'oprc' => 'application/vnd.palm', + 'str' => 'application/vnd.pg.format', + 'ei6' => 'application/vnd.pg.osasli', + 'efif' => 'application/vnd.picsel', + 'plf' => 'application/vnd.pocketlearn', + 'pbd' => 'application/vnd.powerbuilder6', + 'box' => 'application/vnd.previewsystems.box', + 'mgz' => 'application/vnd.proteus.magazine', + 'qps' => 'application/vnd.publishare-delta-tree', + 'ptid' => 'application/vnd.pvi.ptid1', + 'qxd' => 'application/vnd.quark.quarkxpress', + 'qxt' => 'application/vnd.quark.quarkxpress', + 'qwd' => 'application/vnd.quark.quarkxpress', + 'qwt' => 'application/vnd.quark.quarkxpress', + 'qxl' => 'application/vnd.quark.quarkxpress', + 'qxb' => 'application/vnd.quark.quarkxpress', + 'mxl' => 'application/vnd.recordare.musicxml', + 'rm' => 'audio/x-pn-realaudio', + 'see' => 'application/vnd.seemail', + 'sema' => 'application/vnd.sema', + 'semd' => 'application/vnd.semd', + 'semf' => 'application/vnd.semf', + 'ifm' => 'application/vnd.shana.informed.formdata', + 'itp' => 'application/vnd.shana.informed.formtemplate', + 'iif' => 'application/vnd.shana.informed.interchange', + 'ipk' => 'application/vnd.shana.informed.package', + 'twd' => 'application/vnd.simtech-mindmapper', + 'twds' => 'application/vnd.simtech-mindmapper', + 'mmf' => 'application/vnd.smaf', + 'sdkm' => 'application/vnd.solent.sdkm+xml', + 'sdkd' => 'application/vnd.solent.sdkm+xml', + 'dxp' => 'application/vnd.spotfire.dxp', + 'sfs' => 'application/vnd.spotfire.sfs', + 'sus' => 'application/vnd.sus-calendar', + 'susp' => 'application/vnd.sus-calendar', + 'svd' => 'application/vnd.svd', + 'xsm' => 'application/vnd.syncml+xml', + 'bdm' => 'application/vnd.syncml.dm+wbxml', + 'xdm' => 'application/vnd.syncml.dm+xml', + 'tao' => 'application/vnd.tao.intent-module-archive', + 'tmo' => 'application/vnd.tmobile-livetv', + 'tpt' => 'application/vnd.trid.tpt', + 'mxs' => 'application/vnd.triscape.mxs', + 'tra' => 'application/vnd.trueapp', + 'ufd' => 'application/vnd.ufdl', + 'ufdl' => 'application/vnd.ufdl', + 'utz' => 'application/vnd.uiq.theme', + 'umj' => 'application/vnd.umajin', + 'unityweb' => 'application/vnd.unity', + 'uoml' => 'application/vnd.uoml+xml', + 'vcx' => 'application/vnd.vcx', + 'vsd' => 'application/vnd.visio', + 'vst' => 'application/vnd.visio', + 'vss' => 'application/vnd.visio', + 'vsw' => 'application/vnd.visio', + 'vis' => 'application/vnd.visionary', + 'vsf' => 'application/vnd.vsf', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'wmlsc' => 'application/vnd.wap.wmlscriptc', + 'wtb' => 'application/vnd.webturbo', + 'wpd' => 'application/vnd.wordperfect', + 'wqd' => 'application/vnd.wqd', + 'stf' => 'application/vnd.wt.stf', + 'xar' => 'application/vnd.xara', + 'xfdl' => 'application/vnd.xfdl', + 'hvd' => 'application/vnd.yamaha.hv-dic', + 'hvs' => 'application/vnd.yamaha.hv-script', + 'hvp' => 'application/vnd.yamaha.hv-voice', + 'saf' => 'application/vnd.yamaha.smaf-audio', + 'spf' => 'application/vnd.yamaha.smaf-phrase', + 'cmp' => 'application/vnd.yellowriver-custom-menu', + 'zaz' => 'application/vnd.zzazz.deck+xml', + 'vxml' => 'application/voicexml+xml', + 'hlp' => 'application/winhlp', + 'wsdl' => 'application/wsdl+xml', + 'wspolicy' => 'application/wspolicy+xml', + 'ace' => 'application/x-ace-compressed', + 'bcpio' => 'application/x-bcpio', + 'torrent' => 'application/x-bittorrent', + 'bz' => 'application/x-bzip', + 'bz2' => 'application/x-bzip', + 'boz' => 'application/x-bzip2', + 'vcd' => 'application/x-cdlink', + 'chat' => 'application/x-chat', + 'pgn' => 'application/x-chess-pgn', + 'cpio' => 'application/x-cpio', + 'csh' => 'application/x-csh', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'fgd' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'spl' => 'application/x-futuresplash', + 'gtar' => 'application/x-gtar', + 'hdf' => 'application/x-hdf', + 'latex' => 'application/x-latex', + 'wmd' => 'application/x-ms-wmd', + 'wmz' => 'application/x-ms-wmz', + 'mdb' => 'application/x-msaccess', + 'obd' => 'application/x-msbinder', + 'crd' => 'application/x-mscardfile', + 'clp' => 'application/x-msclip', + 'exe' => 'application/x-ms-dos-executable', + 'dll' => 'application/x-msdownload', + 'com' => 'application/x-msdownload', + 'bat' => 'application/x-msdownload', + 'msi' => 'application/x-msdownload', + 'mvb' => 'application/x-msmediaview', + 'm13' => 'application/x-msmediaview', + 'm14' => 'application/x-msmediaview', + 'wmf' => 'image/x-wmf', + 'mny' => 'application/x-msmoney', + 'pub' => 'application/x-mspublisher', + 'scd' => 'application/x-msschedule', + 'trm' => 'application/x-msterminal', + 'wri' => 'application/x-mswrite', + 'nc' => 'application/x-netcdf', + 'cdf' => 'application/x-netcdf', + 'p12' => 'application/x-pkcs12', + 'pfx' => 'application/x-pkcs12', + 'p7b' => 'application/x-pkcs7-certificates', + 'spc' => 'application/x-pkcs7-certificates', + 'p7r' => 'application/x-pkcs7-certreqresp', + 'rar' => 'application/x-rar', + 'sh' => 'application/x-shellscript', + 'shar' => 'application/x-shar', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/stuffit', + 'sitx' => 'application/x-stuffitx', + 'sv4cpio' => 'application/x-sv4cpio', + 'sv4crc' => 'application/x-sv4crc', + 'tar' => 'application/x-tar', + 'tcl' => 'text/x-tcl', + 'tex' => 'text/x-tex', + 'texinfo' => 'text/x-texinfo', + 'texi' => 'text/x-texinfo', + 'ustar' => 'application/x-ustar', + 'src' => 'application/x-wais-source', + 'der' => 'application/x-x509-ca-cert', + 'crt' => 'application/x-x509-ca-cert', + 'xenc' => 'application/xenc+xml', + 'xhtml' => 'application/xhtml+xml', + 'xht' => 'application/xhtml+xml', + 'xml' => 'text/xml', + 'xsl' => 'text/x-xslt', + 'dtd' => 'text/x-dtd', + 'xop' => 'application/xop+xml', + 'xslt' => 'text/x-xslt', + 'xspf' => 'application/xspf+xml', + 'mxml' => 'application/xv+xml', + 'xhvml' => 'application/xv+xml', + 'xvml' => 'application/xv+xml', + 'xvm' => 'application/xv+xml', + 'zip' => 'application/zip', + 'au' => 'audio/basic', + 'snd' => 'audio/basic', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'kar' => 'audio/midi', + 'rmi' => 'audio/midi', + 'mp4a' => 'audio/mp4', + 'mpga' => 'audio/mpeg', + 'mp2' => 'video/mpeg', + 'mp2a' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'm2a' => 'audio/mpeg', + 'm3a' => 'audio/mpeg', + 'eol' => 'audio/vnd.digital-winds', + 'lvp' => 'audio/vnd.lucent.voice', + 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', + 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', + 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', + 'wav' => 'audio/x-wav', + 'aif' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'm3u' => 'audio/x-mpegurl', + 'wax' => 'audio/x-ms-wax', + 'wma' => 'audio/x-ms-wma', + 'ram' => 'audio/x-pn-realaudio', + 'ra' => 'audio/x-pn-realaudio', + 'rmp' => 'audio/x-pn-realaudio-plugin', + 'cdx' => 'chemical/x-cdx', + 'cif' => 'chemical/x-cif', + 'cmdf' => 'chemical/x-cmdf', + 'cml' => 'chemical/x-cml', + 'csml' => 'chemical/x-csml', + 'xyz' => 'chemical/x-xyz', + 'bmp' => 'image/bmp', + 'cgm' => 'image/cgm', + 'g3' => 'image/fax-g3', + 'gif' => 'image/gif', + 'ief' => 'image/ief', + 'jpg' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'png' => 'image/png', + 'btif' => 'image/prs.btif', + 'svg' => 'image/svg+xml', + 'svgz' => 'image/svg+xml', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'psd' => 'image/x-psd', + 'djvu' => 'image/vnd.djvu', + 'djv' => 'image/vnd.djvu', + 'dwg' => 'image/vnd.dwg', + 'dxf' => 'image/vnd.dxf', + 'fbs' => 'image/vnd.fastbidsheet', + 'fpx' => 'image/vnd.fpx', + 'fst' => 'image/vnd.fst', + 'mmr' => 'image/vnd.fujixerox.edmics-mmr', + 'rlc' => 'image/vnd.fujixerox.edmics-rlc', + 'mdi' => 'image/vnd.ms-modi', + 'npx' => 'image/vnd.net-fpx', + 'wbmp' => 'image/vnd.wap.wbmp', + 'xif' => 'image/vnd.xiff', + 'ras' => 'image/x-cmu-raster', + 'cmx' => 'image/x-cmx', + 'ico' => 'image/x-ico', + 'pcx' => 'image/x-pcx', + 'pic' => 'image/x-pict', + 'pct' => 'image/x-pict', + 'pnm' => 'image/x-portable-anymap', + 'pbm' => 'image/x-portable-bitmap', + 'pgm' => 'image/x-portable-graymap', + 'ppm' => 'image/x-portable-pixmap', + 'rgb' => 'image/x-rgb', + 'xbm' => 'image/x-xbitmap', + 'xpm' => 'image/x-xpixmap', + 'xwd' => 'image/x-xwindowdump', + 'eml' => 'message/rfc822', + 'mime' => 'message/rfc822', + 'igs' => 'model/iges', + 'iges' => 'model/iges', + 'msh' => 'model/mesh', + 'mesh' => 'model/mesh', + 'silo' => 'model/mesh', + 'dwf' => 'model/vnd.dwf', + 'gdl' => 'model/vnd.gdl', + 'gtw' => 'model/vnd.gtw', + 'mts' => 'model/vnd.mts', + 'vtu' => 'model/vnd.vtu', + 'wrl' => 'model/vrml', + 'vrml' => 'model/vrml', + 'ics' => 'text/calendar', + 'ifb' => 'text/calendar', + 'css' => 'text/css', + 'csv' => 'text/x-comma-separated-values', + 'html' => 'text/html', + 'htm' => 'text/html', + 'txt' => 'text/plain', + 'text' => 'text/plain', + 'conf' => 'text/plain', + 'def' => 'text/plain', + 'list' => 'text/plain', + 'log' => 'text/x-log', + 'in' => 'text/plain', + 'dsc' => 'text/prs.lines.tag', + 'rtx' => 'text/richtext', + 'sgml' => 'text/sgml', + 'sgm' => 'text/sgml', + 'tsv' => 'text/tab-separated-values', + 't' => 'application/x-troff', + 'tr' => 'application/x-troff', + 'roff' => 'application/x-troff', + 'man' => 'application/x-troff-man', + 'me' => 'text/x-troff-me', + 'ms' => 'text/x-troff-ms', + 'uri' => 'text/x-uri', + 'uris' => 'text/uri-list', + 'urls' => 'text/uri-list', + 'fly' => 'text/vnd.fly', + 'flx' => 'text/vnd.fmi.flexstor', + '3dml' => 'text/vnd.in3d.3dml', + 'spot' => 'text/vnd.in3d.spot', + 'jad' => 'text/vnd.sun.j2me.app-descriptor', + 'wml' => 'text/vnd.wap.wml', + 'wmls' => 'text/vnd.wap.wmlscript', + 's' => 'text/x-asm', + 'asm' => 'text/x-asm', + 'c' => 'text/x-csrc', + 'cc' => 'text/x-c++src', + 'cxx' => 'text/x-c++src', + 'cpp' => 'text/x-c++src', + 'h' => 'text/x-chdr', + 'hh' => 'text/x-c++hdr', + 'dic' => 'text/x-c', + 'f' => 'text/x-fortran', + 'for' => 'text/x-fortran', + 'f77' => 'text/x-fortran', + 'f90' => 'text/x-fortran', + 'p' => 'text/x-pascal', + 'pas' => 'text/x-pascal', + 'java' => 'text/x-java', + 'etx' => 'text/x-setext', + 'uu' => 'text/x-uuencode', + 'vcs' => 'text/calendar', + 'vcf' => 'text/directory', + '3gp' => 'video/3gpp', + '3g2' => 'video/3gpp2', + 'h261' => 'video/h261', + 'h263' => 'video/h263', + 'h264' => 'video/h264', + 'jpgv' => 'video/jpeg', + 'jpm' => 'video/jpm', + 'jpgm' => 'video/jpm', + 'mj2' => 'video/mj2', + 'mjp2' => 'video/mj2', + 'mp4' => 'video/mp4', + 'mp4v' => 'video/mp4', + 'mpg4' => 'video/mp4', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'm1v' => 'video/mpeg', + 'm2v' => 'video/mpeg', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'fvt' => 'video/vnd.fvt', + 'mxu' => 'video/vnd.mpegurl', + 'm4u' => 'video/vnd.mpegurl', + 'viv' => 'video/vnd.vivo', + 'fli' => 'video/x-flic', + 'asx' => 'video/x-ms-asf', + 'wm' => 'video/x-ms-wm', + 'wmv' => 'video/x-ms-wmv', + 'wmx' => 'video/x-ms-wmx', + 'wvx' => 'video/x-ms-wvx', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie', + 'ice' => 'x-conference/x-cooltalk', + 'odb' => 'application/vnd.oasis.opendocument.database', + 'oot' => 'application/vnd.oasis.opendocument.text', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'sxc' => 'application/vnd.sun.xml.calc', + 'stc' => 'application/vnd.sun.xml.calc.template', + 'sxd' => 'application/vnd.sun.xml.draw', + 'std' => 'application/vnd.sun.xml.draw.template', + 'sxg' => 'application/vnd.sun.xml.writer.global', + 'sxm' => 'application/vnd.sun.xml.math', + 'sxi' => 'application/vnd.sun.xml.impress', + 'sti' => 'application/vnd.sun.xml.impress.template', + 'sxw' => 'application/vnd.sun.xml.writer', + 'stw' => 'application/vnd.sun.xml.writer.template', + 'Z' => 'application/x-compress', + 'gz' => 'application/x-gzip', + 'tgz' => 'application/x-compressed-tar', + 'php' => 'application/x-php', + 'php3' => 'application/x-php', + 'pl' => 'application/x-perl', + 'pm' => 'application/x-perl', + 'gsm' => 'audio/x-gsm', + 'vfb' => 'text/calendar', + 'diff' => 'text/x-patch', + 'patch' => 'text/x-patch', + 'shtml' => 'text/html', + 'po' => 'text/x-gettext-translation', + 'sgl' => 'application/vnd.stardivision.writer', + 'wk4' => 'application/vnd.lotus-1-2-3', + 'pict2' => 'image/x-pict', + 'lhz' => 'application/x-lhz', + 'tar.bz2' => 'application/x-bzip-compressed-tar', + 'rle' => 'image/rle', + 'pcf.Z' => 'application/x-font-type1', + 'm15' => 'audio/x-mod', + 'flac' => 'audio/x-flac', + 'dc' => 'application/x-dc-rom', + 'm' => 'text/x-objcsrc', + 'o' => 'application/x-object', + 'fits' => 'image/x-fits', + 'pfa' => 'application/x-font-type1', + 'jnlp' => 'application/x-java-jnlp-file', + 'pfb' => 'application/x-font-type1', + 'smd' => 'application/vnd.stardivision.mail', + 'it' => 'audio/x-it', + 'bib' => 'text/x-bibtex', + 'moc' => 'text/x-moc', + 'theme' => 'application/x-theme', + 'mod' => 'audio/x-mod', + 'smf' => 'application/vnd.stardivision.math', + 'uni' => 'audio/x-mod', + 'mtm' => 'audio/x-mod', + 'ppz' => 'application/vnd.ms-powerpoint', + 's3m' => 'audio/x-s3m', + 'deb' => 'application/x-deb', + 'tk' => 'text/x-tcl', + 'cdr' => 'application/vnd.corel-draw', + 'lwob' => 'image/x-lwo', + 'sml' => 'application/smil', + 'etheme' => 'application/x-e-theme', + '3ds' => 'image/x-3ds', + 'vob' => 'video/mpeg', + 'voc' => 'audio/x-voc', + 'bdf' => 'application/x-font-bdf', + 'ps.gz' => 'application/x-gzpostscript', + 'uil' => 'text/x-uil', + 'ts' => 'application/x-linguist', + 'asp' => 'application/x-asp', + 'nes' => 'application/x-nes-rom', + 'sms' => 'application/x-sms-rom', + 'BLEND' => 'application/x-blender', + 'kil' => 'application/x-killustrator', + 'icb' => 'image/x-icb', + 'lyx' => 'application/x-lyx', + 'jng' => 'image/x-jng', + 'vor' => 'application/vnd.stardivision.writer', + 'adb' => 'text/x-adasrc', + 'flc' => 'video/x-flic', + 'wpg' => 'application/x-wpg', + 'wb1' => 'application/x-quattropro', + 'gra' => 'application/x-graphite', + 'wb2' => 'application/x-quattropro', + 'ltx' => 'text/x-tex', + 'xac' => 'application/x-gnucash', + 'wb3' => 'application/x-quattropro', + 'epsf' => 'image/x-eps', + 'el' => 'text/x-emacs-lisp', + 'jp2' => 'image/jpeg2000', + 'tar.gz' => 'application/x-compressed-tar', + 'epsi' => 'image/x-eps', + 'ui' => 'application/x-designer', + 'old' => 'application/x-trash', + 'tar.Z' => 'application/x-tarz', + 'ttf' => 'application/x-font-ttf', + 'siag' => 'application/x-siag', + 'sid' => 'audio/prs.sid', + 'msod' => 'image/x-msod', + 'h++' => 'text/x-chdr', + 'tar.lzo' => 'application/x-tzo', + 'tar.bz' => 'application/x-bzip-compressed-tar', + 'ads' => 'text/x-adasrc', + 'sda' => 'application/vnd.stardivision.draw', + 'lzo' => 'application/x-lzop', + 'cur' => 'image/x-win-bitmap', + 'sdc' => 'application/vnd.stardivision.calc', + 'sik' => 'application/x-trash', + 'sdd' => 'application/vnd.stardivision.impress', + 'xld' => 'application/vnd.ms-excel', + 'gmo' => 'application/x-gettext-translation', + 'xll' => 'application/vnd.ms-excel', + 'blend' => 'application/x-blender', + 'pw' => 'application/x-pw', + 'kud' => 'application/x-kugar', + 'mkv' => 'application/x-matroska', + 'obj' => 'application/x-tgif', + 'py' => 'text/x-python', + 'sds' => 'application/vnd.stardivision.chart', + 'idl' => 'text/x-idl', + 'dat' => 'video/mpeg', + 'stm' => 'audio/x-stm', + 'PAR2' => 'application/x-par2', + 'xcf.bz2' => 'image/x-compressed-xcf', + 'psid' => 'audio/prs.sid', + 'pict' => 'image/x-pict', + 'ag' => 'image/x-applix-graphics', + 'fo' => 'text/x-xslfo', + 'sdw' => 'application/vnd.stardivision.writer', + 'abw.CRASHED' => 'application/x-abiword', + 'gsf' => 'application/x-font-type1', + 'xcf.gz' => 'image/x-compressed-xcf', + 'pcd' => 'image/x-photo-cd', + 'egon' => 'application/x-egon', + 'pcf' => 'application/x-font-pcf', + 'al' => 'application/x-perl', + 'gnc' => 'application/x-gnucash', + 'tzo' => 'application/x-tzo', + 'la' => 'application/x-shared-library-la', + 'kpm' => 'application/x-kpovmodeler', + 'qif' => 'application/x-qw', + 'sty' => 'text/x-tex', + 'psf' => 'application/x-font-linux-psf', + 'as' => 'application/x-applix-spreadsheet', + 'dbf' => 'application/x-dbase', + 'ilbm' => 'image/x-ilbm', + 'aw' => 'application/x-applix-word', + 'gb' => 'application/x-gameboy-rom', + 'xmi' => 'text/x-xmi', + 'abw.gz' => 'application/x-abiword', + 'XM' => 'audio/x-mod', + 'gnumeric' => 'application/x-gnumeric', + 'bak' => 'application/x-trash', + 'xslfo' => 'text/x-xslfo', + 'gg' => 'application/x-sms-rom', + 'cgi' => 'application/x-cgi', + 'mgp' => 'application/x-magicpoint', + 'spd' => 'application/x-font-speedo', + 'gnucash' => 'application/x-gnucash', + 'cls' => 'text/x-tex', + 'php4' => 'application/x-php', + 'sun' => 'image/x-sun-raster', + 'pyc' => 'application/x-python-bytecode', + 'xcf' => 'image/x-xcf', + 'xbel' => 'application/x-xbel', + 'jpr' => 'application/x-jbuilder-project', + 'afm' => 'application/x-font-afm', + 'fig' => 'image/x-xfig', + 'perl' => 'application/x-perl', + 'rej' => 'application/x-reject', + 'qtvr' => 'video/quicktime', + 'jpx' => 'application/x-jbuilder-project', + '669' => 'audio/x-mod', + 'kdelnk' => 'application/x-desktop', + 'md' => 'application/x-genesis-rom', + 'pyo' => 'application/x-python-bytecode', + 'oleo' => 'application/x-oleo', + 'ac3' => 'audio/ac3', + 'mml' => 'text/mathml', + 'par2' => 'application/x-par2', + 'sylk' => 'text/spreadsheet', + 'C' => 'text/x-c++src', + 'cert' => 'application/x-x509-ca-cert', + 'ult' => 'audio/x-mod', + 'lwo' => 'image/x-lwo', + 'dcl' => 'text/x-dcl', + 'zoo' => 'application/x-zoo', + 'dcm' => 'application/dicom', + 'mm' => 'text/x-troff-mm', + 'iff' => 'image/x-iff', + 'lws' => 'image/x-lws', + 'zabw' => 'application/x-abiword', + 'blender' => 'application/x-blender', + 'glade' => 'application/x-glade', + 'rpm' => 'application/x-rpm', + 'tga' => 'image/x-tga', + 'jar' => 'application/x-jar', + 'cpio.gz' => 'application/x-cpio-compressed', + 'dsl' => 'text/x-dsl', + 'kra' => 'application/x-krita', + 'n64' => 'application/x-n64-rom', + 'm4a' => 'audio/x-m4a', + 'c++' => 'text/x-c++src', + 'moov' => 'video/quicktime', + 'sam' => 'application/x-amipro', + 'nsv' => 'video/x-nsv', + 'dia' => 'application/x-dia-diagram', + 'xi' => 'audio/x-xi', + 'hp' => 'text/x-chdr', + 'gen' => 'application/x-genesis-rom', + 'url' => 'text/x-uri', + 'hs' => 'text/x-haskell', + 'xm' => 'audio/x-xm', + 'sql' => 'text/x-sql', + 'NSV' => 'video/x-nsv', + 'desktop' => 'application/x-desktop', + 'mng' => 'video/x-mng', + 'pem' => 'application/x-x509-ca-cert', + 'slk' => 'text/spreadsheet', + 'cs' => 'text/x-csharp', + 'arj' => 'application/x-arj', + 'a' => 'application/x-archive', + 'lhs' => 'text/x-literate-haskell', + 'gcrd' => 'text/directory', + 'vct' => 'text/directory', + 'wk1' => 'application/vnd.lotus-1-2-3', + 'msx' => 'application/x-msx-rom', + 'sgi' => 'image/x-sgi', + 'd' => 'text/x-dsrc', + 'CSSL' => 'text/css', + 'wk3' => 'application/vnd.lotus-1-2-3', + 'abw' => 'application/x-abiword', + 'pict1' => 'image/x-pict' +); \ No newline at end of file diff --git a/framework/mime_tmp/Horde/Mime.php b/framework/mime_tmp/Horde/Mime.php deleted file mode 100644 index 9569c78f3..000000000 --- a/framework/mime_tmp/Horde/Mime.php +++ /dev/null @@ -1,443 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME -{ - /** - * Determines if a string contains 8-bit (non US-ASCII) characters. - * - * @param string $string The string to check. - * @param string $charset The charset of the string. Defaults to - * US-ASCII. - * - * @return boolean True if string contains non US-ASCII characters. - */ - static public function is8bit($string, $charset = null) - { - /* ISO-2022-JP is a 7bit charset, but it is an 8bit representation so - * it needs to be entirely encoded. */ - return is_string($string) && - ((stristr('iso-2022-jp', $charset) && - (strstr($string, "\x1b\$B"))) || - preg_match('/[\x80-\xff]/', $string)); - } - - /** - * Encodes a string containing non-ASCII characters according to RFC 2047. - * - * @param string $text The text to encode. - * @param string $charset The character set of the text. - * - * @return string The text, encoded only if it contains non-ASCII - * characters. - */ - static public function encode($text, $charset = null) - { - if (is_null($charset)) { - require_once 'Horde/NLS.php'; - $charset = NLS::getCharset(); - } - $charset = String::lower($charset); - - if (($charset == 'us-ascii') || !self::is8bit($text, $charset)) { - return $text; - } - - /* Get the list of elements in the string. */ - $size = preg_match_all('/([^\s]+)([\s]*)/', $text, $matches, PREG_SET_ORDER); - - $line = ''; - - /* Return if nothing needs to be encoded. */ - foreach ($matches as $key => $val) { - if (self::is8bit($val[1], $charset)) { - if ((($key + 1) < $size) && - self::is8bit($matches[$key + 1][1], $charset)) { - $line .= self::_encode($val[1] . $val[2], $charset) . ' '; - } else { - $line .= self::_encode($val[1], $charset) . $val[2]; - } - } else { - $line .= $val[1] . $val[2]; - } - } - - return rtrim($line); - } - - /** - * Internal recursive function to RFC 2047 encode a string. - * - * @param string $text The text to encode. - * @param string $charset The character set of the text. - * - * @return string The text, encoded only if it contains non-ASCII - * characters. - */ - static protected function _encode($text, $charset) - { - $encoded = trim(base64_encode($text)); - $c_size = strlen($charset) + 7; - - if ((strlen($encoded) + $c_size) > 75) { - $parts = explode("\r\n", rtrim(chunk_split($encoded, intval((75 - $c_size) / 4) * 4))); - } else { - $parts[] = $encoded; - } - - $p_size = count($parts); - $out = ''; - - foreach ($parts as $key => $val) { - $out .= '=?' . $charset . '?b?' . $val . '?='; - if ($p_size > $key + 1) { - /* RFC 2047 [2]: no encoded word can be more than 75 - * characters long. If longer, you must split the word with - * CRLF SPACE. */ - $out .= "\r\n "; - } - } - - return $out; - } - - /** - * Encodes a line via quoted-printable encoding. - * - * @param string $text The text to encode. - * @param string $eol The EOL sequence to use. - * @param integer $wrap Wrap a line at this many characters. - * - * @return string The quoted-printable encoded string. - */ - static public function quotedPrintableEncode($text, $eol, $wrap = 76) - { - $line = $output = ''; - $curr_length = 0; - - /* We need to go character by character through the data. */ - for ($i = 0, $length = strlen($text); $i < $length; ++$i) { - $char = $text[$i]; - - /* If we have reached the end of the line, reset counters. */ - if ($char == "\n") { - $output .= $eol; - $curr_length = 0; - continue; - } elseif ($char == "\r") { - continue; - } - - /* Spaces or tabs at the end of the line are NOT allowed. Also, - * ASCII characters below 32 or above 126 AND 61 must be - * encoded. */ - $ascii = ord($char); - if ((($ascii === 32) && - ($i + 1 != $length) && - (($text[$i + 1] == "\n") || ($text[$i + 1] == "\r"))) || - (($ascii < 32) || ($ascii > 126) || ($ascii === 61))) { - $char_len = 3; - $char = '=' . String::upper(sprintf('%02s', dechex($ascii))); - } else { - $char_len = 1; - } - - /* Lines must be $wrap characters or less. */ - $curr_length += $char_len; - if ($curr_length > $wrap) { - $output .= '=' . $eol; - $curr_length = $char_len; - } - $output .= $char; - } - - return $output; - } - - /** - * Encodes a string containing email addresses according to RFC 2047. - * - * This differs from encode() because it keeps email addresses legal, only - * encoding the personal information. - * - * @param mixed $addresses The email addresses to encode (either a - * string or an array of addresses). - * @param string $charset The character set of the text. - * @param string $defserver The default domain to append to mailboxes. - * - * @return string The text, encoded only if it contains non-ASCII - * characters, or PEAR_Error on error. - */ - static public function encodeAddress($addresses, $charset = null, - $defserver = null) - { - if (!is_array($addresses)) { - /* parseAddressList() does not process the null entry - * 'undisclosed-recipients:;' correctly. */ - $addresses = trim($addresses); - if (preg_match('/undisclosed-recipients:\s*;/i', $addresses)) { - return $addresses; - } - - $addresses = Horde_MIME_Address::parseAddressList($addresses, array('defserver' => $defserver, 'nestgroups' => true)); - if (is_a($addresses, 'PEAR_Error')) { - return $addresses; - } - } - - $text = ''; - foreach ($addresses as $addr) { - // Check for groups. - if (empty($addr['groupname'])) { - if (empty($addr['personal'])) { - $personal = ''; - } else { - if (($addr['personal'][0] == '"') && - (substr($addr['personal'], -1) == '"')) { - $addr['personal'] = stripslashes(substr($addr['personal'], 1, -1)); - } - $personal = self::encode($addr['personal'], $charset); - } - $text .= Horde_MIME_Address::writeAddress($addr['mailbox'], $addr['host'], $personal) . ', '; - } else { - $text .= Horde_MIME_Address::writeGroupAddress($addr['groupname'], $addr['addresses']) . ' '; - } - } - - return rtrim($text, ' ,'); - } - - /** - * Decodes an RFC 2047-encoded string. - * - * @param string $string The text to decode. - * @param string $to_charset The charset that the text should be decoded - * to. - * - * @return string The decoded text. - */ - static public function decode($string, $to_charset = null) - { - if (($pos = strpos($string, '=?')) === false) { - return $string; - } - - /* Take out any spaces between multiple encoded words. */ - $string = preg_replace('|\?=\s+=\?|', '?==?', $string); - - /* Save any preceding text. */ - $preceding = substr($string, 0, $pos); - - $search = substr($string, $pos + 2); - $d1 = strpos($search, '?'); - if ($d1 === false) { - return $string; - } - - $charset = substr($string, $pos + 2, $d1); - $search = substr($search, $d1 + 1); - - $d2 = strpos($search, '?'); - if ($d2 === false) { - return $string; - } - - $encoding = substr($search, 0, $d2); - $search = substr($search, $d2 + 1); - - $end = strpos($search, '?='); - if ($end === false) { - $end = strlen($search); - } - - $encoded_text = substr($search, 0, $end); - $rest = substr($string, (strlen($preceding . $charset . $encoding . $encoded_text) + 6)); - - if (is_null($to_charset)) { - require_once 'Horde/NLS.php'; - $to_charset = NLS::getCharset(); - } - - switch ($encoding) { - case 'Q': - case 'q': - $decoded = preg_replace('/=([0-9a-f]{2})/ie', 'chr(0x\1)', str_replace('_', ' ', $encoded_text)); - $decoded = String::convertCharset($decoded, $charset, $to_charset); - break; - - case 'B': - case 'b': - $decoded = String::convertCharset(base64_decode($encoded_text), $charset, $to_charset); - break; - - default: - $decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?='; - break; - } - - return $preceding . $decoded . self::decode($rest, $to_charset); - } - - /** - * Decodes an RFC 2047-encoded address string. - * - * @param string $string The text to decode. - * @param string $to_charset The charset that the text should be decoded - * to. - * - * @return string The decoded text. - */ - static public function decodeAddrString($string, $to_charset = null) - { - $addr_list = array(); - foreach (Horde_MIME_Address::parseAddressList($string) as $ob) { - $ob['personal'] = isset($ob['personal']) - ? self::decode($ob['personal'], $to_charset) - : ''; - $addr_list[] = $ob; - } - - return Horde_MIME_Address::addrArray2String($addr_list); - } - - /** - * Encodes a parameter string pursuant to RFC 2231. - * - * @param string $name The parameter name. - * @param string $string The string to encode. - * @param string $charset The charset the text should be encoded with. - * @param string $lang The language to use when encoding. - * - * @return array The encoded parameter string. - */ - static public function encodeParamString($name, $string, $charset, - $lang = null) - { - $encode = $wrap = false; - $output = array(); - - if (self::is8bit($string, $charset)) { - $string = String::lower($charset) . '\'' . (is_null($lang) ? '' : String::lower($lang)) . '\'' . rawurlencode($string); - $encode = true; - } - - // 4 = '*', 2x '"', ';' - $pre_len = strlen($name) + 4 + (($encode) ? 1 : 0); - if (($pre_len + strlen($string)) > 76) { - while ($string) { - $chunk = 76 - $pre_len; - $pos = min($chunk, strlen($string) - 1); - if (($chunk == $pos) && ($pos > 2)) { - for ($i = 0; $i <= 2; $i++) { - if ($string[$pos-$i] == '%') { - $pos -= $i + 1; - break; - } - } - } - $lines[] = substr($string, 0, $pos + 1); - $string = substr($string, $pos + 1); - } - $wrap = true; - } else { - $lines = array($string); - } - - $i = 0; - foreach ($lines as $val) { - $output[] = - $name . - (($wrap) ? ('*' . $i++) : '') . - (($encode) ? '*' : '') . - '="' . $val . '"'; - } - - return implode('; ', $output); - } - - /** - * Decodes a parameter string encoded pursuant to RFC 2231. - * - * @param string $string The entire string to decode, including the - * parameter name. - * @param string $to_charset The charset the text should be decoded to. - * - * @return array The decoded text, or the original string if it was not - * encoded. - */ - static public function decodeParamString($string, $to_charset = null) - { - if (($pos = strpos($string, '*')) === false) { - return false; - } - - if (!isset($to_charset)) { - require_once 'Horde/NLS.php'; - $to_charset = NLS::getCharset(); - } - - $attribute = substr($string, 0, $pos); - $charset = $lang = null; - $output = ''; - - /* Get the character set and language used in the encoding, if - * any. */ - if (preg_match("/^[^=]+\*\=([^']*)'([^']*)'/", $string, $matches)) { - $charset = $matches[1]; - $lang = $matches[2]; - $string = str_replace($charset . "'" . $lang . "'", '', $string); - } - - $lines = preg_split('/\s*' . preg_quote($attribute) . '(?:\*\d)*/', $string); - foreach ($lines as $line) { - if (strpos($line, '*=') === 0) { - $output .= urldecode(str_replace(array('_', '='), array('%20', '%'), substr($line, 2))); - } else { - $output .= substr($line, 1); - } - } - - /* RFC 2231 uses quoted printable encoding. */ - if (!is_null($charset)) { - $output = String::convertCharset($output, $charset, $to_charset); - } - - return array( - 'attribute' => $attribute, - 'value' => $output - ); - } - - /** - * Generates a Message-ID string conforming to RFC 2822 [3.6.4] and the - * standards outlined in 'draft-ietf-usefor-message-id-01.txt'. - * - * @param string A message ID string. - */ - static public function generateMessageID() - { - return '<' . date('YmdHis') . '.' . self::generateRandomID() . '@' . $_SERVER['SERVER_NAME'] . '>'; - } - - /** - * Generates a Random-ID string suitable for use with MIME features that - * require a random string. - * - * @return string A random string. - */ - static public function generateRandomID() - { - return base_convert(dechex(strtr(microtime(), array('0.' => '', ' ' => ''))) . uniqid(), 16, 36); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Address.php b/framework/mime_tmp/Horde/Mime/Address.php deleted file mode 100644 index 1ca31fdc0..000000000 --- a/framework/mime_tmp/Horde/Mime/Address.php +++ /dev/null @@ -1,401 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME_Address -{ - /** - * Builds an RFC compliant email address. - * - * @param string $mailbox Mailbox name. - * @param string $host Domain name of mailbox's host. - * @param string $personal Personal name phrase. - * - * @return string The correctly escaped and quoted - * "$personal <$mailbox@$host>" string. - */ - static public function writeAddress($mailbox, $host, $personal = '') - { - $address = ''; - - if (strlen($personal)) { - $address .= self::encode($personal, 'personal') . ' <'; - } - - $address .= self::encode($mailbox, 'address') . '@' . ltrim($host, '@'); - - if (strlen($personal)) { - $address .= '>'; - } - - return $address; - } - - /** - * Write an RFC compliant group address, given the group name and a list - * of email addresses. - * - * @param string $groupname The name of the group. - * @param array $addresses The component email addresses. These e-mail - * addresses must be in RFC format. - * - * @return string The correctly quoted group string. - */ - static public function writeGroupAddress($groupname, $addresses = array()) - { - return self::encode($groupname, 'address') . ':' . (empty($addresses) ? '' : implode(', ', $addresses)) . ';'; - } - - /** - * If an email address has no personal information, get rid of any angle - * brackets (<>) around it. - * - * @param string $address The address to trim. - * - * @return string The trimmed address. - */ - static public function trimAddress($address) - { - $address = trim($address); - - if (($address[0] == '<') && (substr($address, -1) == '>')) { - $address = substr($address, 1, -1); - } - - return $address; - } - - /** - * Explodes an RFC string, ignoring a delimiter if preceded by a "\" - * character, or if the delimiter is inside single or double quotes. - * - * @param string $string The RFC compliant string. - * @param string $delimiters A string containing valid delimiters. - * Defaults to ','. - * - * @return array The exploded string in an array. - */ - static public function explode($string, $delimiters = ',') - { - if (!strlen($string)) { - return array($string); - } - - $emails = array(); - $pos = 0; - $in_group = $in_quote = false; - - for ($i = 0, $iMax = strlen($string); $i < $iMax; ++$i) { - $char = $string[$i]; - if ($char == '"') { - if (!$i || ($prev !== '\\')) { - $in_quote = !$in_quote; - } - } elseif ($in_group) { - if ($char == ';') { - $emails[] = substr($string, $pos, $i - $pos + 1); - $pos = $i + 1; - $in_group = false; - } - } elseif (!$in_quote) { - if ($char == ':') { - $in_group = true; - } elseif ((strpos($delimiters, $char) !== false) && - (!$i || ($prev !== '\\'))) { - $emails[] = $i ? substr($string, $pos, $i - $pos) : ''; - $pos = $i + 1; - } - } - $prev = $char; - } - - if ($pos != $i) { - /* The string ended without a delimiter. */ - $emails[] = substr($string, $pos, $i - $pos); - } - - return $emails; - } - - /** - * Takes an address object array and formats it as a string. - * - * Object array format for the address "John Doe " - * is: - *
-     * 'personal' = Personal name ("John Doe")
-     * 'mailbox' = The user's mailbox ("john_doe")
-     * 'host' = The host the mailbox is on ("example.com")
-     * 
- * - * @param array $ob The address object to be turned into a string. - * @param mixed $filter A user@example.com style bare address to ignore. - * Either single string or an array of strings. If - * the address matches $filter, an empty string will - * be returned. - * - * @return string The formatted address. - */ - static public function addrObject2String($ob, $filter = '') - { - /* If the personal name is set, decode it. */ - $ob['personal'] = isset($ob['personal']) - ? Horde_MIME::decode($ob['personal']) - : ''; - - /* If both the mailbox and the host are empty, return an empty string. - * If we just let this case fall through, the call to writeAddress() - * will end up return just a '@', which is undesirable. */ - if (empty($ob['mailbox']) && empty($ob['host'])) { - return ''; - } - - /* Make sure these two variables have some sort of value. */ - if (!isset($ob['mailbox'])) { - $ob['mailbox'] = ''; - } elseif ($ob['mailbox'] == 'undisclosed-recipients') { - return ''; - } - if (!isset($ob['host'])) { - $ob['host'] = ''; - } - - /* Filter out unwanted addresses based on the $filter string. */ - if ($filter) { - if (!is_array($filter)) { - $filter = array($filter); - } - foreach ($filter as $f) { - if (strcasecmp($f, $ob['mailbox'] . '@' . $ob['host']) == 0) { - return ''; - } - } - } - - /* Return the formatted email address. */ - return self::writeAddress($ob['mailbox'], $ob['host'], $ob['personal']); - } - - /** - * Takes an array of address object arrays and passes each of them through - * addrObject2String(). - * - * @param array $addresses The array of address objects. - * @param mixed $filter A user@example.com style bare address to - * ignore. If any address matches $filter, it - * will not be included in the final string. - * - * @return string All of the addresses in a comma-delimited string. - * Returns the empty string on error/no addresses found. - */ - static public function addrArray2String($addresses, $filter = '') - { - if (!is_array($addresses)) { - return ''; - } - - $addrList = array(); - - foreach ($addresses as $addr) { - $val = self::addrObject2String($addr, $filter); - if (!empty($val)) { - $addrList[String::lower(self::bareAddress($val))] = $val; - } - } - - return implode(', ', $addrList); - } - - /** - * Return the list of addresses for a header object. - * - * @param array $obs An array of header objects. - * - * @return array An array of address information. Array elements: - *
-     * 'address' - (string) Full address
-     * 'display' - (string) A displayable version of the address
-     * 'groupname' - (string) The group name.
-     * 'host' - (string) Hostname
-     * 'inner' - (string) Trimmed, bare address
-     * 'personal' - (string) Personal string
-     * 
- */ - static public function getAddressesFromObject($obs) - { - $ret = array(); - - if (!is_array($obs) || empty($obs)) { - return $ret; - } - - foreach ($obs as $ob) { - if (isset($ob['groupname'])) { - $ret[] = array( - 'addresses' => self::getAddressesFromObject($ob['addresses']), - 'groupname' => $ob['groupname'] - ); - continue; - } - - $ob = array_merge(array( - 'host' => '', - 'mailbox' => '', - 'personal' => '' - ), $ob); - - /* Ensure we're working with initialized values. */ - if (!empty($ob['personal'])) { - $ob['personal'] = stripslashes(trim(Horde_MIME::decode($ob['personal']), '"')); - } - - $inner = self::writeAddress($ob['mailbox'], $ob['host']); - - /* Generate the new object. */ - $ret[] = array( - 'address' => self::addrObject2String($ob), - 'display' => (empty($ob['personal']) ? '' : $ob['personal'] . ' <') . $inner . (empty($ob['personal']) ? '' : '>'), - 'host' => $ob['host'], - 'inner' => $inner, - 'personal' => $ob['personal'] - ); - } - - return $ret; - } - - /** - * Returns the bare address. - * - * @param string $address The address string. - * @param string $defserver The default domain to append to mailboxes. - * @param boolean $multiple Should we return multiple results? - * - * @return mixed If $multiple is false, returns the mailbox@host e-mail - * address. If $multiple is true, returns an array of - * these addresses. - */ - static public function bareAddress($address, $defserver = null, - $multiple = false) - { - $addressList = array(); - - $from = self::parseAddressList($address, array('defserver' => $defserver)); - if (is_a($from, 'PEAR_Error')) { - return $multiple ? array() : ''; - } - - foreach ($from as $entry) { - if (!empty($entry['mailbox'])) { - $addressList[] = $entry['mailbox'] . (isset($entry['host']) ? '@' . $entry['host'] : ''); - } - } - - return $multiple ? $addressList : array_pop($addressList); - } - - /** - * Parses a list of email addresses into its parts. Handles distribution - * lists. - * - * @param string $address The address string. - * @param array $options Additional options: - *
-     * 'defserver' - (string) The default domain to append to mailboxes.
-     *               DEFAULT: No domain appended.
-     * 'nestgroups' - (boolean) Nest the groups? (Will appear under the
-     *                'groupname' key)
-     *                DEFAULT: No.
-     * 'reterror' - (boolean) Return a PEAR_Error object on error?
-     *              DEFAULT: Returns an empty array on error.
-     * 'validate' - (boolean) Validate the address(es)?
-     *              DEFAULT: No.
-     * 
- * - * @return mixed If 'reterror' is true, returns a PEAR_Error object on - * error. Otherwise, a list of arrays with the possible - * keys: 'mailbox', 'host', 'personal', 'adl', 'groupname', - * and 'comment'. - */ - static public function parseAddressList($address, $options = array()) - { - if (preg_match('/undisclosed-recipients:\s*;/i', trim($address))) { - return array(); - } - - $options = array_merge(array( - 'defserver' => null, - 'nestgroups' => false, - 'reterror' => false, - 'validate' => false - ), $options); - - static $parser; - if (!isset($parser)) { - require_once 'Mail/RFC822.php'; - $parser = new Mail_RFC822(); - } - - $ret = $parser->parseAddressList($address, $options['defserver'], $options['nestgroups'], $options['validate']); - if (is_a($ret, 'PEAR_Error')) { - return empty($options['reterror']) ? array() : $ret; - } - - /* Convert objects to arrays. */ - foreach (array_keys($ret) as $key) { - $ret[$key] = (array) $ret[$key]; - } - - return $ret; - } - - /** - * Quotes and escapes the given string if necessary using rules contained - * in RFC 2822 [3.2.5]. - * - * @param string $str The string to be quoted and escaped. - * @param string $type Either 'address' or 'personal'. - * - * @return string The correctly quoted and escaped string. - */ - static public function encode($str, $type = 'address') - { - // Excluded (in ASCII): 0-8, 10-31, 34, 40-41, 44, 58-60, 62, 64, - // 91-93, 127 - $filter = "\0\1\2\3\4\5\6\7\10\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\"(),:;<>@[\\]\177"; - - switch ($type) { - case 'address': - // RFC 2822 [3.4.1]: (HTAB, SPACE) not allowed in address - $filter .= "\11\40"; - break; - - case 'personal': - // RFC 2822 [3.4]: Period not allowed in display name - $filter .= '.'; - break; - } - - // Strip double quotes if they are around the string already. - // If quoted, we know that the contents are already escaped, so - // unescape now. - $str = trim($str); - if ($str && ($str[0] == '"') && (substr($str, -1) == '"')) { - $str = stripslashes(substr($str, 1, -1)); - } - - return (strcspn($str, $filter) != strlen($str)) - ? '"' . addcslashes($str, '\\"') . '"' - : $str; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Headers.php b/framework/mime_tmp/Horde/Mime/Headers.php deleted file mode 100644 index 164f7de10..000000000 --- a/framework/mime_tmp/Horde/Mime/Headers.php +++ /dev/null @@ -1,543 +0,0 @@ - - * @package Horde_MIME - */ -class Horde_MIME_Headers -{ - /** - * The internal headers array. - * - * @var array - */ - protected $_headers = array(); - - /** - * The sequence to use as EOL for the headers. - * The default is currently to output the EOL sequence internally as - * just "\n" instead of the canonical "\r\n" required in RFC 822 & 2045. - * To be RFC complaint, the full EOL combination should be used - * when sending a message. - * - * @var string - */ - protected $_eol = "\n"; - - /** - * The User-Agent string to use. - * - * @var string - */ - protected $_agent = null; - - /** - * Returns the internal header array in array format. - * - * @param array $options Optional parameters: - *
-     * 'charset' => (string) Encodes the headers using this charset.
-     *              DEFAULT: No encoding.
-     * 'defserver' => (string) TODO
-     *              DEFAULT: NO
-     * 'nowrap' => (integer) Don't wrap the headers.
-     *             DEFAULT: Headers are wrapped.
-     * 
- * - * @return array The headers in array format. - */ - public function toArray($options = array()) - { - $ret = array(); - $address_keys = empty($options['charset']) - ? array() - : $this->addressFields(); - - foreach ($this->_headers as $header => $ob) { - $val = is_array($ob['value']) ? $ob['value'] : array($ob['value']); - - foreach (array_keys($val) as $key) { - if (!empty($address_keys)) { - if (in_array($header, $address_keys)) { - $text = Horde_MIME::encodeAddress($val[$key], $charset, empty($options['defserver']) ? null : $options['defserver']); - if (is_a($text, 'PEAR_Error')) { - $text = $val[$key]; - } - } else { - $text = Horde_MIME::encode($val[$key], $options['charset']); - } - } else { - $text = $val[$key]; - } - - if (empty($options['nowrap'])) { - $text = $this->wrapHeaders($header, $text); - } - - $val[$key] = $text; - } - - $ret[$ob['header']] = (count($val) == 1) ? reset($val) : $val; - } - - return $ret; - } - - /** - * Returns the internal header array in string format. - * - * @param array $options Optional parameters: - *
-     * 'charset' => (string) Encodes the headers using this charset.
-     *              DEFAULT: No encoding.
-     * 'defserver' => (string) TODO
-     *              DEFAULT: NO
-     * 'nowrap' => (integer) Don't wrap the headers.
-     *             DEFAULT: Headers are wrapped.
-     * 
- * - * @return string The headers in string format. - */ - public function toString($options = array()) - { - $text = ''; - - foreach ($this->toArray($options) as $key => $val) { - if (!is_array($val)) { - $val = array($val); - } - foreach ($val as $entry) { - $text .= $key . ': ' . $entry . $this->_eol; - } - } - - return $text . $this->_eol; - } - - /** - * Generate the 'Received' header for the Web browser->Horde hop - * (attempts to conform to guidelines in RFC 5321 [4.4]). - */ - public function addReceivedHeader() - { - $old_error = error_reporting(0); - if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { - /* This indicates the user is connecting through a proxy. */ - $remote_path = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); - $remote_addr = $remote_path[0]; - $remote = gethostbyaddr($remote_addr); - } else { - $remote_addr = $_SERVER['REMOTE_ADDR']; - $remote = empty($_SERVER['REMOTE_HOST']) - ? gethostbyaddr($remote_addr) - : $_SERVER['REMOTE_HOST']; - } - error_reporting($old_error); - - if (!empty($_SERVER['REMOTE_IDENT'])) { - $remote_ident = $_SERVER['REMOTE_IDENT'] . '@' . $remote . ' '; - } elseif ($remote != $_SERVER['REMOTE_ADDR']) { - $remote_ident = $remote . ' '; - } else { - $remote_ident = ''; - } - - if (!empty($GLOBALS['conf']['server']['name'])) { - $server_name = $GLOBALS['conf']['server']['name']; - } elseif (!empty($_SERVER['SERVER_NAME'])) { - $server_name = $_SERVER['SERVER_NAME']; - } elseif (!empty($_SERVER['HTTP_HOST'])) { - $server_name = $_SERVER['HTTP_HOST']; - } else { - $server_name = 'unknown'; - } - - $received = 'from ' . $remote . ' (' . $remote_ident . - '[' . $remote_addr . ']) ' . - 'by ' . $server_name . ' (Horde Framework) with HTTP; ' . - date('r'); - - $this->addHeader('Received', $received); - } - - /** - * Generate the 'Message-ID' header. - */ - public function addMessageIdHeader() - { - require_once dirname(__FILE__) . '/../MIME.php'; - $this->addHeader('Message-ID', Horde_MIME::generateMessageID()); - } - - /** - * Generate the 'Resent' headers (conforms to guidelines in - * RFC 2822 [3.6.6]). - * - * @param string $from The address to use for 'Resent-From'. - * @param string $to The address to use for 'Resent-To'. - */ - public function addResentHeaders($from, $to) - { - require_once dirname(__FILE__) . '/../MIME.php'; - - /* We don't set Resent-Sender, Resent-Cc, or Resent-Bcc. */ - $this->addHeader('Resent-Date', date('r')); - $this->addHeader('Resent-From', $from); - $this->addHeader('Resent-To', $to); - $this->addHeader('Resent-Message-ID', Horde_MIME::generateMessageID()); - } - - /** - * Generate the user agent description header. - */ - public function addUserAgentHeader() - { - $this->addHeader('User-Agent', $this->getUserAgent()); - } - - /** - * Returns the user agent description header. - * - * @return string The user agent header. - */ - public function getUserAgent() - { - if (is_null($this->_agent)) { - $this->_agent = 'Horde Application Framework 4.0'; - } - return $this->_agent; - } - - /** - * Explicitly sets the User-Agent string. - * - * @param string $agent The User-Agent string to use. - */ - public function setUserAgent($agent) - { - $this->_agent = $agent; - } - - /** - * Add a header to the header array. - * - * @param string $header The header name. - * @param string $value The header value. - * @param boolean $decode MIME decode the value? - */ - public function addHeader($header, $value, $decode = false) - { - require_once 'Horde/String.php'; - - $header = trim($header); - $lcHeader = String::lower($header); - - if (!isset($this->_headers[$lcHeader])) { - $this->_headers[$lcHeader] = array(); - $this->_headers[$lcHeader]['header'] = $header; - } - $ptr = &$this->_headers[$lcHeader]; - - if ($decode) { - require_once dirname(__FILE__) . '/../MIME.php'; - - // Fields defined in RFC 2822 that contain address information - if (in_array($lcHeader, $this->addressFields())) { - $value = Horde_MIME::decodeAddrString($value); - } else { - $value = Horde_MIME::decode($value); - } - } - - if (isset($ptr['value'])) { - if (!is_array($ptr['value'])) { - $ptr['value'] = array($ptr['value']); - } - $ptr['value'][] = $value; - } else { - $ptr['value'] = $value; - } - } - - /** - * Remove a header from the header array. - * - * @param string $header The header name. - */ - public function removeHeader($header) - { - require_once 'Horde/String.php'; - unset($this->_headers[String::lower(trim($header))]); - } - - /** - * Set a value for a particular header ONLY if that header is set. - * - * @param string $header The header name. - * @param string $value The header value. - * @param boolean $decode MIME decode the value? - * - * @return boolean True if value was set. - */ - public function setValue($header, $value, $decode = false) - { - require_once 'Horde/String.php'; - - if (isset($this->_headers[String::lower($header)])) { - $this->addHeader($header, $value, $decode); - return true; - } - - return false; - } - - /** - * Attempts to return the header in the correct case. - * - * @param string $header The header to search for. - * - * @return string The value for the given header. - * If the header is not found, returns null. - */ - public function getString($header) - { - require_once 'Horde/String.php'; - - $lcHeader = String::lower($header); - return (isset($this->_headers[$lcHeader])) - ? $this->_headers[$lcHeader]['header'] - : null; - } - - /** - * Attempt to return the value for a given header. - * The following header fields can only have 1 entry, so if duplicate - * entries exist, the first value will be used: - * * To, From, Cc, Bcc, Date, Sender, Reply-to, Message-ID, In-Reply-To, - * References, Subject (RFC 2822 [3.6]) - * * All List Headers (RFC 2369 [3]) - * - * @param string $header The header to search for. - * - * @return mixed The value for the given header. - * If the header is not found, returns null. - */ - public function getValue($header) - { - require_once 'Horde/String.php'; - - $header = String::lower($header); - - if (isset($this->_headers[$header])) { - return (is_array($this->_headers[$header]['value']) && in_array($header, $this->singleFields(true))) - ? $this->_headers[$header]['value'][0] - : $this->_headers[$header]['value']; - } - - return null; - } - - /** - * Returns the list of RFC defined header fields that contain address - * info. - * - * @return array The list of headers, in lowercase. - */ - public function addressFields() - { - return array( - 'from', 'to', 'cc', 'bcc', 'reply-to', 'resent-to', 'resent-cc', - 'resent-bcc', 'resent-from', 'sender' - ); - } - - /** - * Returns the list of RFC defined header fields that can only contain - * a single value. - * - * @param boolean $list Return list-related headers also? - * - * @return array The list of headers, in lowercase. - */ - public function singleFields($list = true) - { - $single = array( - 'to', 'from', 'cc', 'bcc', 'date', 'sender', 'reply-to', - 'message-id', 'in-reply-to', 'references', 'subject', 'x-priority' - ); - - if ($list) { - $single = array_merge($single, array_keys($this->listHeaders())); - } - - return $single; - } - - /** - * Returns the list of valid mailing list headers. - * - * @return array The list of valid mailing list headers. - */ - public function listHeaders() - { - return array( - /* RFC 2369 */ - 'list-help' => _("List-Help"), - 'list-unsubscribe' => _("List-Unsubscribe"), - 'list-subscribe' => _("List-Subscribe"), - 'list-owner' => _("List-Owner"), - 'list-post' => _("List-Post"), - 'list-archive' => _("List-Archive"), - /* RFC 2919 */ - 'list-id' => _("List-Id") - ); - } - - /** - * Do any mailing list headers exist? - * - * @return boolean True if any mailing list headers exist. - */ - public function listHeadersExist() - { - return (bool) count(array_intersect(array_keys($this->listHeaders()), array_keys($this->_headers))); - } - - /** - * Sets a new string to use for EOLs. - * - * @param string $eol The string to use for EOLs. - */ - public function setEOL($eol) - { - $this->_eol = $eol; - } - - /** - * Get the string to use for EOLs. - * - * @return string The string to use for EOLs. - */ - public function getEOL() - { - return $this->_eol; - } - - /** - * Returns a header from the header object. - * - * @param string $field The header to return as an object. - * - * @return array The object for the field requested. - */ - public function getOb($field) - { - $val = $this->getValue($field); - return is_null($val) - ? array() - : Horde_MIME_Address::parseAddressList($val); - } - - /** - * Adds proper linebreaks to a header string. - * RFC 2822 says headers SHOULD only be 78 characters a line, but also - * says that a header line MUST not be more than 998 characters. - * - * @param string $header The header name. - * @param string $text The text of the header field. - * - * @return string The header value, with linebreaks inserted. - */ - public function wrapHeaders($header, $text) - { - $eol = $this->_eol; - $header_text = rtrim($header) . ': '; - - /* Remove any existing linebreaks. */ - $text = $header_text . preg_replace("/\r?\n\s?/", ' ', rtrim($text)); - - if (!in_array(strtolower($header), array('content-type', 'content-disposition'))) { - /* Wrap the line. */ - $line = wordwrap($text, 75, $eol . ' '); - - /* Make sure there are no empty lines. */ - $line = preg_replace('/' . $eol . ' ' . $eol . ' /', '/' . $eol . ' /', $line); - - return substr($line, strlen($header_text)); - } - - /* Split the line by the RFC parameter separator ';'. */ - $params = preg_split("/\s*;\s*/", $text); - - $line = ''; - $eollength = strlen($eol); - $length = 1000 - $eollength; - $paramcount = count($params); - - reset($params); - while (list($count, $val) = each($params)) { - /* If longer than RFC allows, then simply chop off the excess. */ - $moreparams = (($count + 1) != $paramcount); - $maxlength = $length - (!empty($line) ? 1 : 0) - (($moreparams) ? 1 : 0); - if (strlen($val) > $maxlength) { - $val = substr($val, 0, $maxlength); - - /* If we have an opening quote, add a closing quote after - * chopping the rest of the text. */ - if (strpos($val, '"') !== false) { - $val = substr($val, 0, -1) . '"'; - } - } - - if (!empty($line)) { - $line .= ' '; - } - $line .= $val . (($moreparams) ? ';' : '') . $eol; - } - - return substr($line, strlen($header_text), ($eollength * -1)); - } - - /** - * Builds a Horde_MIME_Headers object from header text. - * This function can be called statically: - * $headers = Horde_MIME_Headers::parseHeaders(). - * - * @param string $text A text string containing the headers. - * - * @return Horde_MIME_Headers A new Horde_MIME_Headers object. - */ - static public function parseHeaders($text) - { - $headers = new Horde_MIME_Headers(); - $currheader = $currtext = null; - - foreach (explode("\n", $text) as $val) { - $val = rtrim($val); - if (empty($val)) { - break; - } - - if (($val[0] == ' ') || ($val[0] == "\t")) { - $currtext .= ' ' . ltrim($val); - } else { - if (!is_null($currheader)) { - $headers->addHeader($currheader, $currtext, true); - } - $pos = strpos($val, ':'); - $currheader = substr($val, 0, $pos); - $currtext = ltrim(substr($val, $pos + 1)); - } - } - $headers->addHeader($currheader, $currtext, true); - - return $headers; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Magic.php b/framework/mime_tmp/Horde/Mime/Magic.php deleted file mode 100644 index ef93b459d..000000000 --- a/framework/mime_tmp/Horde/Mime/Magic.php +++ /dev/null @@ -1,260 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME_Magic -{ - /** - * Returns a copy of the MIME extension map. - * - * @return array The MIME extension map. - */ - static protected function _getMimeExtensionMap() - { - static $mime_extension_map; - - if (!isset($mime_extension_map)) { - require dirname(__FILE__) . '/mime.mapping.php'; - } - - return $mime_extension_map; - } - - /** - * Returns a copy of the MIME magic file. - * - * @return array The MIME magic file. - */ - static protected function _getMimeMagicFile() - { - static $mime_magic; - - if (!isset($mime_magic)) { - require dirname(__FILE__) . '/mime.magic.php'; - } - - return $mime_magic; - } - - /** - * Attempt to convert a file extension to a MIME type, based - * on the global Horde and application specific config files. - * - * If we cannot map the file extension to a specific type, then - * we fall back to a custom MIME handler 'x-extension/$ext', which - * can be used as a normal MIME type internally throughout Horde. - * - * @param string $ext The file extension to be mapped to a MIME type. - * - * @return string The MIME type of the file extension. - */ - static public function extToMIME($ext) - { - if (empty($ext)) { - return 'application/octet-stream'; - } - - $ext = String::lower($ext); - $map = self::_getMimeExtensionMap(); - $pos = 0; - - while (!isset($map[$ext])) { - if (($pos = strpos($ext, '.')) === false) { - break; - } - $ext = substr($ext, $pos + 1); - } - - return isset($map[$ext]) - ? $map[$ext] - : 'x-extension/' . $ext; - } - - /** - * Attempt to convert a filename to a MIME type, based on the global Horde - * and application specific config files. - * - * @param string $filename The filename to be mapped to a MIME type. - * @param boolean $unknown How should unknown extensions be handled? If - * true, will return 'x-extension/*' types. If - * false, will return 'application/octet-stream'. - * - * @return string The MIME type of the filename. - */ - static public function filenameToMIME($filename, $unknown = true) - { - $pos = strlen($filename) + 1; - $type = ''; - - $map = self::_getMimeExtensionMap(); - for ($i = 0; $i <= $map['__MAXPERIOD__']; ++$i) { - $pos = strrpos(substr($filename, 0, $pos - 1), '.') + 1; - if ($pos === false) { - break; - } - } - $type = self::extToMIME(substr($filename, $pos)); - - return (empty($type) || (!$unknown && (strpos($type, 'x-extension') !== false))) - ? 'application/octet-stream' - : $type; - } - - /** - * Attempt to convert a MIME type to a file extension, based - * on the global Horde and application specific config files. - * - * If we cannot map the type to a file extension, we return false. - * - * @param string $type The MIME type to be mapped to a file extension. - * - * @return string The file extension of the MIME type. - */ - static public function MIMEToExt($type) - { - if (empty($type)) { - return false; - } - - if (($key = array_search($type, self::_getMimeExtensionMap())) === false) { - list($major, $minor) = explode('/', $type); - if ($major == 'x-extension') { - return $minor; - } - if (strpos($minor, 'x-') === 0) { - return substr($minor, 2); - } - return false; - } - - return $key; - } - - /** - * Uses variants of the UNIX "file" command to attempt to determine the - * MIME type of an unknown file. - * - * @param string $path The path to the file to analyze. - * @param string $magic_db Path to the mime magic database. - * - * @return string The MIME type of the file. Returns false if the file - * type isn't recognized or an error happened. - */ - static public function analyzeFile($path, $magic_db = null) - { - /* If the PHP Mimetype extension is available, use that. */ - if (Util::extensionExists('fileinfo')) { - $res = empty($magic_db) - ? @finfo_open(FILEINFO_MIME) - : @finfo_open(FILEINFO_MIME, $magic_db); - - if ($res) { - $type = finfo_file($res, $path); - finfo_close($res); - - /* Remove any additional information. */ - foreach (array(';', ',', '\\0') as $separator) { - if (($pos = strpos($type, $separator)) !== false) { - $type = rtrim(substr($type, 0, $pos)); - } - } - - if (preg_match('|^[a-z0-9]+/[.-a-z0-9]+$|i', $type)) { - return $type; - } - } - } - - if (Util::extensionExists('mime_magic')) { - return trim(mime_content_type($path)); - } - - /* Use a built-in magic file. */ - $mime_magic = self::_getMimeMagicFile(); - if (!($fp = @fopen($path, 'rb'))) { - return false; - } - - reset($mime_magic); - while (list($offset, $odata) = each($mime_magic)) { - reset($odata); - while (list($length, $ldata) = each($odata)) { - @fseek($fp, $offset, SEEK_SET); - $lookup = @fread($fp, $length); - if (!empty($ldata[$lookup])) { - fclose($fp); - return $ldata[$lookup]; - } - } - } - fclose($fp); - - return false; - } - - /** - * Uses variants of the UNIX "file" command to attempt to determine the - * MIME type of an unknown byte stream. - * - * @param string $data The file data to analyze. - * @param string $magic_db Path to the mime magic database. - * - * @return string The MIME type of the file. Returns false if the file - * type isn't recognized or an error happened. - */ - static public function analyzeData($data, $magic_db = null) - { - /* If the PHP Mimetype extension is available, use that. */ - if (Util::extensionExists('fileinfo')) { - $res = empty($magic_db) - ? @finfo_open(FILEINFO_MIME) - : @finfo_open(FILEINFO_MIME, $magic_db); - - if (!$res) { - return false; - } - - $type = finfo_buffer($res, $data); - finfo_close($res); - - /* Remove any additional information. */ - if (($pos = strpos($type, ';')) !== false) { - $type = rtrim(substr($type, 0, $pos)); - } - - if (($pos = strpos($type, ',')) !== false) { - $type = rtrim(substr($type, 0, $pos)); - } - - return $type; - } - - /* Use a built-in magic file. */ - $mime_magic = self::_getMimeMagicFile(); - reset($mime_magic); - while (list($offset, $odate) = each($mime_magic)) { - reset($odata); - while (list($length, $ldata) = each($odata)) { - $lookup = substr($data, $offset, $length); - if (!empty($ldata[$lookup])) { - return $ldata[$lookup]; - } - } - } - - return false; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Mail.php b/framework/mime_tmp/Horde/Mime/Mail.php deleted file mode 100644 index 289fc9a6c..000000000 --- a/framework/mime_tmp/Horde/Mime/Mail.php +++ /dev/null @@ -1,507 +0,0 @@ - - * @package Horde_MIME - */ -class Horde_MIME_Mail -{ - /** - * The message headers. - * - * @var Horde_MIME_Headers - */ - protected $_headers; - - /** - * The main body part. - * - * @var Horde_MIME_Part - */ - protected $_body; - - /** - * The main HTML body part. - * - * @var Horde_MIME_Part - */ - protected $_htmlBody; - - /** - * The message recipients. - * - * @var array - */ - protected $_recipients = array(); - - /** - * All MIME parts except the main body part. - * - * @var array - */ - protected $_parts = array(); - - /** - * The Mail driver name. - * - * @link http://pear.php.net/Mail - * @var string - */ - protected $_mailer_driver = 'smtp'; - - /** - * The Mail driver parameters. - * - * @link http://pear.php.net/Mail - * @var array - */ - protected $_mailer_params = array(); - - /** - * Constructor. - * - * @param string $subject The message subject. - * @param string $body The message body. - * @param string $to The message recipient(s). - * @param string $from The message sender. - * @param string $charset The character set of the message. - */ - function __construct($subject = null, $body = null, $to = null, - $from = null, $charset = 'iso-8859-1') - { - /* Set SERVER_NAME. */ - if (!isset($_SERVER['SERVER_NAME'])) { - $_SERVER['SERVER_NAME'] = php_uname('n'); - } - - $this->_headers = new Horde_MIME_Headers(); - - if ($subject) { - $this->addHeader('Subject', $subject, $charset); - } - if ($to) { - $this->addHeader('To', $to, $charset); - } - if ($from) { - $this->addHeader('From', $from, $charset); - } - if ($body) { - $this->setBody($body, $charset); - } - } - - /** - * Adds several message headers at once. - * - * @param array $header Hash with header names as keys and header - * contents as values. - * @param string $charset The header value's charset. - */ - public function addHeaders($headers = array(), $charset = 'iso-8859-1') - { - foreach ($headers as $header => $value) { - if (is_a($added = $this->addHeader($header, $value, $charset), 'PEAR_Error')) { - return $added; - } - } - } - - /** - * Adds a message header. - * - * @param string $header The header name. - * @param string $value The header value. - * @param string $charset The header value's charset. - * @param boolean $overwrite If true, an existing header of the same name - * is being overwritten; if false, multiple - * headers are added; if null, the correct - * behaviour is automatically chosen depending - * on the header name. - */ - public function addHeader($header, $value, $charset = 'iso-8859-1', - $overwrite = null) - { - $lc_header = String::lower($header); - - /* Only encode value if charset is explicitly specified, otherwise - * the message's charset will be used when building the message. */ - if (!empty($charset)) { - if (in_array($lc_header, $this->_headers->addressFields())) { - $value = Horde_MIME::encodeAddress($value, $charset); - } else { - $value = Horde_MIME::encode($value, $charset); - } - } - - if (is_null($overwrite)) { - if (in_array($lc_header, $this->_headers->singleFields(true))) { - $overwrite = true; - } - } - - if ($overwrite) { - $this->_headers->removeHeader($header); - } - - if ($lc_header !== 'bcc') { - $this->_headers->addHeader($header, $value); - } - - if (in_array($lc_header, array('to', 'cc', 'bcc'))) { - return $this->addRecipients($value); - } - } - - /** - * Removes a message header. - * - * @param string $header The header name. - */ - public function removeHeader($header) - { - $value = $this->_headers->getValue($header); - $this->_headers->removeHeader($header); - if (in_array(String::lower($header), array('to', 'cc', 'bcc'))) { - $this->removeRecipients($value); - } - } - - /** - * Sets the message body text. - * - * @param string $body The message content. - * @param string $charset The character set of the message. - * @param boolean|integer $wrap If true, wrap the message at column 76; - * If an integer wrap the message at that - * column. Don't use wrapping if sending - * flowed messages. - */ - public function setBody($body, $charset = 'iso-8859-1', $wrap = false) - { - if ($wrap) { - $body = String::wrap($body, $wrap === true ? 76 : $wrap, "\n"); - } - $this->_body = new Horde_MIME_Part('text/plain', $body, $charset); - } - - /** - * 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 = 'iso-8859-1', - $alternative = true) - { - $this->_htmlBody = new Horde_MIME_Part('text/html', $body, $charset); - if ($alternative) { - require_once 'Horde/Text/Filter.php'; - $body = Text_Filter::filter($body, 'html2text', array('wrap' => false)); - $this->_body = new Horde_MIME_Part('text/plain', $body, $charset); - } - } - - /** - * Adds a message part. - * - * @param string $mime_type The content type of the part. - * @param string $content The content of the part. - * @param string $charset The character set of the part. - * @param string $disposition The content disposition of the part. - * - * @return integer The part number. - */ - public function addPart($mime_type, $content, $charset = 'us-ascii', - $disposition = null) - { - $part = new Horde_MIME_Part($mime_type, $content, $charset, $disposition); - $part->transferEncodeContents(); - $this->_parts[] = $part; - return count($this->_parts) - 1; - } - - /** - * Adds a MIME message part. - * - * @param Horde_MIME_Part $part A Horde_MIME_Part object. - * - * @return integer The part number. - */ - public function addMIMEPart($part) - { - $part->transferEncodeContents(); - $this->_parts[] = $part; - return count($this->_parts) - 1; - } - - /** - * Adds an attachment. - * - * @param string $file The path to the file. - * @param string $name The file name to use for the attachment. - * @param string $type The content type of the file. - * @param string $charset The character set of the part (only relevant for - * text parts. - * - * @return integer The part number. - */ - public function addAttachment($file, $name = null, $type = null, - $charset = 'us-ascii') - { - if (empty($name)) { - $name = basename($file); - } - if (empty($type)) { - require_once dirname(__FILE__) . '/Magic.php'; - $type = Horde_MIME_Magic::filenameToMIME($file, false); - } - - $part = new Horde_MIME_Part($type, file_get_contents($file), $charset, 'attachment'); - $part->setName($name); - $part->transferEncodeContents(); - $this->_parts[] = $part; - - return count($this->_parts) - 1; - } - - /** - * Removes a message part. - * - * @param integer $part The part number. - */ - public function removePart($part) - { - if (isset($this->_parts[$part])) { - unset($this->_parts[$part]); - } - } - - /** - * Adds message recipients. - * - * Recipients specified by To:, Cc:, or Bcc: headers are added - * automatically. - * - * @param string|array List of recipients, either as a comma separated - * list or as an array of email addresses. - */ - public function addRecipients($recipients) - { - $recipients = $this->_buildRecipients($recipients); - if (is_a($recipients, 'PEAR_Error')) { - return $recipients; - } - $this->_recipients = array_merge($this->_recipients, $recipients); - } - - /** - * Removes message recipients. - * - * @param string|array List of recipients, either as a comma separated - * list or as an array of email addresses. - */ - public function removeRecipients($recipients) - { - $recipients = $this->_buildRecipients($recipients); - if (is_a($recipients, 'PEAR_Error')) { - return $recipients; - } - $this->_recipients = array_diff($this->_recipients, $recipients); - } - - /** - * Removes all message recipients. - */ - public function clearRecipients() - { - $this->_recipients = array(); - } - - /** - * Builds a recipients list. - * - * @param string|array List of recipients, either as a comma separated - * list or as an array of email addresses. - * - * @return array Normalized list of recipients or PEAR_Error on failure. - */ - protected function _buildRecipients($recipients) - { - if (is_string($recipients)) { - $recipients = Horde_MIME::explode($recipients, ','); - } - $recipients = array_filter(array_map('trim', $recipients)); - - $addrlist = array(); - foreach ($recipients as $email) { - if (!empty($email)) { - $unique = Horde_MIME::bareAddress($email); - if ($unique) { - $addrlist[$unique] = $email; - } else { - $addrlist[$email] = $email; - } - } - } - - foreach (Horde_MIME::bareAddress(implode(', ', $addrlist), null, true) as $val) { - if (Horde_MIME::is8bit($val)) { - return PEAR::raiseError(sprintf(_("Invalid character in e-mail address: %s."), $val)); - } - } - - return $addrlist; - } - - /** - * Sends this message. - * - * For the possible Mail drivers and parameters see the PEAR Mail - * documentation. - * @link http://pear.php.net/Mail - * - * @param string $driver The Mail driver to use. - * @param array $params Any parameters necessary for the Mail driver. - * @param boolean $resend If true, the message id and date are re-used; - * If false, they will be updated. - * @param boolean $flowed Send message in flowed text format. @since - * Horde 3.2.1 - * - * @return mixed True on success, PEAR_Error on error. - */ - public function send($driver = null, $params = array(), $resend = false, - $flowed = true) - { - /* Add mandatory headers if missing. */ - if (!$resend || !$this->_headers->getString('Message-ID')) { - $this->_headers->addMessageIdHeader(); - } - if (!$this->_headers->getString('User-Agent')) { - $this->_headers->addAgentHeader(); - } - if (!$resend || !$this->_headers->getString('Date')) { - $this->_headers->addHeader('Date', date('r')); - } - - /* Send in flowed format. */ - if ($flowed && !empty($this->_body)) { - require_once 'Text/Flowed.php'; - $flowed = new Text_Flowed($this->_body->getContents(), - $this->_body->getCharset()); - $flowed->setDelSp(true); - $this->_body->setContentTypeParameter('DelSp', 'Yes'); - $this->_body->setContents($flowed->toFlowed()); - $this->_body->setContentTypeParameter('format', 'flowed'); - } - - /* Build mime message. */ - $mime = new Horde_MIME_Message(); - if (!empty($this->_body) && !empty($this->_htmlBody)) { - $basepart = new Horde_MIME_Part('multipart/alternative'); - $this->_body->setDescription(_("Plaintext Version of Message")); - $basepart->addPart($this->_body); - $this->_htmlBody->setDescription(_("HTML Version of Message")); - $basepart->addPart($this->_htmlBody); - $mime->addPart($basepart); - } elseif (!empty($this->_htmlBody)) { - $mime->addPart($this->_htmlBody); - } elseif (!empty($this->_body)) { - $mime->addPart($this->_body); - } - foreach ($this->_parts as $mime_part) { - $mime->addPart($mime_part); - } - - /* Check mailer configuration. */ - if (!empty($driver)) { - $this->_mailer_driver = $driver; - } - if (!empty($params)) { - $this->_mailer_params = $params; - } - - /* Send message. */ - return $mime->send(implode(', ', $this->_recipients), $this->_headers, - $this->_mailer_driver, $this->_mailer_params); - } - - /** - * Return error string corresponding to a sendmail error code. - * - * @param integer $code The error code. - * - * @return string The error string, or null if the code is unknown. - */ - static public function sendmailError($code) - { - switch ($code) { - case 64: // EX_USAGE - return 'sendmail: ' . _("command line usage error") . ' (64)'; - - case 65: // EX_DATAERR - return 'sendmail: ' . _("data format error") . ' (65)'; - - case 66: // EX_NOINPUT - return 'sendmail: ' . _("cannot open input") . ' (66)'; - - case 67: // EX_NOUSER - return 'sendmail: ' . _("addressee unknown") . ' (67)'; - - case 68: // EX_NOHOST - return 'sendmail: ' . _("host name unknown") . ' (68)'; - - case 69: // EX_UNAVAILABLE - return 'sendmail: ' . _("service unavailable") . ' (69)'; - - case 70: // EX_SOFTWARE - return 'sendmail: ' . _("internal software error") . ' (70)'; - - case 71: // EX_OSERR - return 'sendmail: ' . _("system error") . ' (71)'; - - case 72: // EX_OSFILE - return 'sendmail: ' . _("critical system file missing") . ' (72)'; - - case 73: // EX_CANTCREAT - return 'sendmail: ' . _("cannot create output file") . ' (73)'; - - case 74: // EX_IOERR - return 'sendmail: ' . _("input/output error") . ' (74)'; - - case 75: // EX_TEMPFAIL - return 'sendmail: ' . _("temporary failure") . ' (75)'; - - case 76: // EX_PROTOCOL - return 'sendmail: ' . _("remote error in protocol") . ' (76)'; - - case 77: // EX_NOPERM - return 'sendmail: ' . _("permission denied") . ' (77)'; - - case 78: // EX_CONFIG - return 'sendmail: ' . _("configuration error") . ' (78)'; - - case 79: // EX_NOTFOUND - return 'sendmail: ' . _("entry not found") . ' (79)'; - } - - return null; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Mdn.php b/framework/mime_tmp/Horde/Mime/Mdn.php deleted file mode 100644 index d567c88ac..000000000 --- a/framework/mime_tmp/Horde/Mime/Mdn.php +++ /dev/null @@ -1,238 +0,0 @@ - - * @package Horde_MIME - */ -class Horde_MIME_MDN -{ - /** - * The Horde_MIME_Headers object. - * - * @var Horde_MIME_Headers - */ - protected $_headers; - - /** - * The text of the original message. - * - * @var string - */ - protected $_msgtext = false; - - /** - * Constructor. - * - * @param Horde_MIME_Headers $mime_headers A Horde_MIME_Headers object. - */ - function __construct($headers = null) - { - $this->_headers = $headers; - } - - /** - * Returns the address to return the MDN to. - * - * @return string The address to send the MDN to. Returns null if no - * MDN is requested. - */ - public function getMDNReturnAddr() - { - /* RFC 3798 [2.1] requires the Disposition-Notificaion-To header - * for an MDN to be created. */ - return $this->_headers->getValue('Disposition-Notification-To'); - } - - /** - * Is user input required to send the MDN? - * Explicit confirmation is needed in some cases to prevent mail loops - * and the use of MDNs for mail bombing. - * - * @return boolean Is explicit user input required to send the MDN? - */ - public function userConfirmationNeeded() - { - $return_path = $this->_headers->getValue('Return-Path'); - - /* RFC 3798 [2.1]: Explicit confirmation is needed if there is no - * Return-Path in the header. Also, "if the message contains more - * than one Return-Path header, the implementation may [] treat the - * situation as a failure of the comparison." */ - if (empty($return_path) || is_array($return_path)) { - return true; - } - - require_once dirname(__FILE__) . '/Address.php'; - - /* RFC 3798 [2.1]: Explicit confirmation is needed if there is more - * than one distinct address in the Disposition-Notification-To - * header. */ - $addr_arr = Horde_MIME_Address::parseAddressList($this->getMDNReturnAddr()); - if (count($addr_arr) > 1) { - return true; - } - - /* RFC 3798 [2.1] states that "MDNs SHOULD NOT be sent automatically - * if the address in the Disposition-Notification-To header differs - * from the address in the Return-Path header." This comparison is - * case-sensitive for the mailbox part and case-insensitive for the - * host part. */ - $ret_arr = Horde_MIME_Address::parseAddressList($return_path); - return ($addr_arr[0]['mailbox'] == $ret_arr[0]['mailbox']) && - (String::lower($addr_arr[0]['host']) == String::lower($ret_arr[0]['host'])); - } - - /** - * When generating the MDN, should we return the enitre text of the - * original message? The default is no - we only return the headers of - * the original message. If the text is passed in via this method, we - * will return the entire message. - * - * @param string $text The text of the original message. - */ - public function originalMessageText($text) - { - $this->_msgtext = $text; - } - - /** - * Generate the MDN according to the specifications listed in RFC - * 3798 [3]. - * - * @param boolean $action Was this MDN type a result of a manual action - * on part of the user? - * @param boolean $sending Was this MDN sent as a result of a manual - * action on part of the user? - * @param string $type The type of action performed by the user. - *
-     * Per RFC 3798 [3.2.6.2] the following types are valid:
-     * =====================================================
-     * 'displayed'
-     * 'deleted'
-     * 
- * @param array $mod The list of modifications. - *
-     * Per RFC 3798 [3.2.6.3] the following modifications are valid:
-     * =============================================================
-     * 'error'
-     * 
- * @param array $err If $mod is 'error', the additional information - * to provide. Key is the type of modification, - * value is the text. - * - * @return mixed True on success, PEAR_Error object on error. - */ - public function generate($action, $sending, $type, $mod = array(), - $err = array()) - { - require_once dirname(__FILE__) . '/Headers.php'; - require_once dirname(__FILE__) . '/Message.php'; - require_once 'Horde/Identity.php'; - require_once 'Horde/Text.php'; - - /* Set up some variables we use later. */ - $identity = &Identity::singleton(); - $from_addr = $identity->getDefaultFromAddress(); - - $to = $this->getMDNReturnAddr(); - $ua = $this->_headers->getAgentHeader(); - - $orig_recip = $this->_headers->getValue('Original-Recipient'); - if (!empty($orig_recip) && is_array($orig_recip)) { - $orig_recip = $orig_recip[0]; - } - - $msg_id = $this->_headers->getValue('Message-ID'); - - /* Create the Disposition field now (RFC 3798 [3.2.6]). */ - $dispo = 'Disposition: ' . - (($action) ? 'manual-action' : 'automatic-action') . - '/' . - (($sending) ? 'MDN-sent-manually' : 'MDN-sent-automatically') . - '; ' . - $type; - if (!empty($mod)) { - $dispo .= '/' . implode(', ', $mod); - } - - /* Set up the mail headers. */ - $msg_headers = new Horde_MIME_Headers(); - $msg_headers->addMessageIdHeader(); - $msg_headers->addAgentHeader($ua); - $msg_headers->addHeader('Date', date('r')); - $msg_headers->addHeader('From', $from_addr); - $msg_headers->addHeader('To', $this->getMDNReturnAddr()); - $msg_headers->addHeader('Subject', _("Disposition Notification")); - - /* MDNs are a subtype of 'multipart/report'. */ - $msg = new Horde_MIME_Message(); - $msg->setType('multipart/report'); - $msg->setContentTypeParameter('report-type', 'disposition-notification'); - - $charset = NLS::getCharset(); - - /* The first part is a human readable message. */ - $part_one = new Horde_MIME_Part('text/plain'); - $part_one->setCharset($charset); - if ($type == 'displayed') { - $contents = sprintf(_("The message sent on %s to %s with subject \"%s\" has been displayed.\n\nThis is no guarantee that the message has been read or understood."), $this->_headers->getValue('Date'), $this->_headers->getValue('To'), $this->_headers->getValue('Subject')); - require_once 'Text/Flowed.php'; - $flowed = new Text_Flowed($contents, $charset); - $flowed->setDelSp(true); - $part_one->setContentTypeParameter('format', 'flowed'); - $part_one->setContentTypeParameter('DelSp', 'Yes'); - $part_one->setContents($flowed->toFlowed()); - } - // TODO: Messages for other notification types. - $msg->addPart($part_one); - - /* The second part is a machine-parseable description. */ - $part_two = new Horde_MIME_Part('message/disposition-notification'); - $part_two->setContents('Reporting-UA: ' . $GLOBALS['conf']['server']['name'] . '; ' . $ua . "\n"); - if (!empty($orig_recip)) { - $part_two->appendContents('Original-Recipient: rfc822;' . $orig_recip . "\n"); - } - $part_two->appendContents('Final-Recipient: rfc822;' . $from_addr . "\n"); - if (!empty($msg_id)) { - $part_two->appendContents('Original-Message-ID: rfc822;' . $msg_id . "\n"); - } - $part_two->appendContents($dispo . "\n"); - if (in_array('error', $mod) && isset($err['error'])) { - $part_two->appendContents('Error: ' . $err['error'] . "\n"); - } - $msg->addPart($part_two); - - /* The third part is the text of the original message. RFC 3798 [3] - * allows us to return only a portion of the entire message - this - * is left up to the user. */ - $part_three = new Horde_MIME_Part('message/rfc822'); - $part_three->setContents($this->_headers->toString()); - if (!empty($this->_msgtext)) { - $part_three->appendContents($part_three->getEOL() . $this->_msgtext); - } - $msg->addPart($part_three); - - return $msg->send($to, $msg_headers); - } - - /** - * Add a MDN (read receipt) request headers to the Horde_MIME_Headers:: - * object. - * - * @param Horde_MIME_Headers &$ob The object to add the headers to. - * @param string $to The address the receipt should be - * mailed to. - */ - public function addMDNRequestHeaders(&$ob, $to) - { - /* This is the RFC 3798 way of requesting a receipt. */ - $ob->addHeader('Disposition-Notification-To', $to); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Message.php b/framework/mime_tmp/Horde/Mime/Message.php deleted file mode 100644 index 6844080f2..000000000 --- a/framework/mime_tmp/Horde/Mime/Message.php +++ /dev/null @@ -1,384 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME_Message extends Horde_MIME_Part -{ - /** - * Create a Horde_MIME_Message object from a Horde_MIME_Part object. - * This function can be called statically via: - * $mime_message = Horde_MIME_Message::convertMIMEPart(); - * - * @todo Is this needed? - * - * @param Horde_MIME_Part $mime_part The Horde_MIME_Part object. - * - * @return Horde_MIME_Message The new Horde_MIME_Message object. - */ - static public function convertMIMEPart($mime_part) - { - if (!$mime_part->getMIMEId()) { - $mime_part->setMIMEId(1); - } - - $mime_message = new Horde_MIME_Message(); - $mime_message->addPart($mime_part); - - return $mime_message; - } - - /** - * Sends this message. - * - * @param string $email The address list to send to. - * @param Horde_MIME_Headers $headers The Horde_MIME_Headers object - * holding this message's headers. - * @param string $driver The Mail:: driver to use. - * @param array $params Any parameters necessary for the - * Mail driver. - * - * @return mixed True on success, PEAR_Error on error. - */ - public function send($email, $headers, $driver = null, $params = array()) - { - if (!isset($driver)) { - $driver = $GLOBALS['conf']['mailer']['type']; - $params = $GLOBALS['conf']['mailer']['params']; - } - - require_once 'Mail.php'; - $mailer = Mail::factory($driver, $params); - - /* Add MIME Headers if they don't already exist. */ - if (!$headers->getValue('MIME-Version')) { - $headers = $this->addMIMEHeaders($headers); - } - $headerArray = $headers->toArray($this->getCharset()); - - /* Does the SMTP backend support 8BITMIME (RFC 1652) or - * BINARYMIME (RFC 3030) extensions? Requires PEAR's Mail package - * version 1.2+ and Net_SMTP version 1.3+. */ - if (($driver == 'smtp') && method_exists($mailer, 'getSMTPObject')) { - $net_smtp = $mailer->getSMTPObject(); - if (!is_a($net_smtp, 'PEAR_Error') && - method_exists($net_smtp, 'getServiceExtensions')) { - $smtp_ext = $net_smtp->getServiceExtensions(); - $message->strict7bit(false); - $encoding = $message->getTransferEncoding(); - if (($encoding == '8bit') && - isset($smtp_ext['8BITMIME'])) { - $mailer->addServiceExtensionParameter('BODY', '8BITMIME'); - } elseif (($encoding == 'binary') && - isset($smtp_ext['BINARYMIME'])) { - $mailer->addServiceExtensionParameter('BODY', 'BINARYMIME'); - } else { - $message->strict7bit(true); - $encoding = $message->getTransferEncoding(); - } - $headers->addHeader('Content-Transfer-Encoding', $encoding); - } - } - - /* Make sure the message has a trailing newline. */ - $msg = $this->toString(); - if (substr($msg, -1) != "\n") { - $msg .= "\n"; - } - - $result = $mailer->send(Horde_MIME::encodeAddress($email), $headerArray, $msg); - - if (is_a($result, 'PEAR_Error') && ($driver == 'sendmail')) { - $error = Horde_MIME_Mail::sendmailError($result->getCode()); - if (is_null($error)) { - $error = $result; - $userinfo = null; - } else { - $userinfo = $result->toString(); - } - return PEAR::raiseError($error, null, null, null, $userinfo); - } - - return $result; - } - - /** - * Get the list of MIME headers for this part in an array. - * - * @return array The full set of MIME headers. - */ - public function getHeaderArray() - { - /* Per RFC 2045 [4], this MUST appear in the message headers. */ - return parent::header(array('MIME-Version' => '1.0')); - } - - /** - * Parse an array of MIME structure information into a Horde_MIME_Message - * object. - * This function can be called statically via: - * $mime_message = Horde_MIME_Message::parseStructure(); - * - * @param array $structure An array of structure information in the - * following format: - *
-     * MANDATORY:
-     *   'type' - (string) The MIME type
-     *   'subtype' - (string) The MIME subtype
-     *
-     * The array MAY contain the following information:
-     *   'disposition' - (string) The disposition type of the part (e.g.
-     *                   'attachment', 'inline').
-     *   'dparameters' - (array) Attribute/value pairs from the part's
-     *                   Content-Disposition header.
-     *   'language' - (array) A list of body language values.
-     *   'location' - (string) The body content URI.
-     *
-     * Depending on the MIME type of the part, the array will also contain
-     * further information. If labeled as [OPTIONAL], the array MAY
-     * contain this information, but only if 'noext' is false and the
-     * server returned the requested information. Else, the value is not
-     * set.
-     *
-     * multipart/* parts:
-     * ==================
-     * 'parts' - (array) An array of subparts (follows the same format as
-     *           the base structure array).
-     * 'parameters' - [OPTIONAL] (array) Attribute/value pairs from the
-     *                part's Content-Type header.
-     *
-     * All other parts:
-     * ================
-     * 'parameters' - (array) Attribute/value pairs from the part's
-     *                Content-Type header.
-     * 'id' - (string) The part's Content-ID value.
-     * 'description' - (string) The part's Content-Description value.
-     * 'encoding' - (string) The part's Content-Transfer-Encoding value.
-     * 'size' - (integer) - The part's size in bytes.
-     * 'envelope' - [ONLY message/rfc822] (array) See 'envelope' response.
-     * 'structure' - [ONLY message/rfc822] (array) See 'structure'
-     *               response.
-     * 'lines' - [ONLY message/rfc822 and text/*] (integer) The size of
-     *           the body in text lines.
-     * 'md5' - [OPTIONAL] (string) The part's MD5 value.
-     * 
- * - * @return object A Horde_MIME_Message object. - */ - static public function parseStructure($structure) - { - $ob = self::_parseStructure($structure, true); - $ob->buildMIMEIds(); - return $ob; - } - - /** - * Parse a subpart of a MIME message into a - * Horde_MIME_Message/Horde_MIME_Part object. - * - * @param array $data Structure information in the format described - * in parseStructure(). - * @param boolean $rfc822 Force the part to be treated as a - * message/rfc822 part. - * - * @return mixed Returns either a Horde_MIME_Message or a Horde_MIME_Part - * object, depending on the part's MIME type. - */ - static protected function _parseStructure($data, $rfc822 = false) - { - $type = $data['type'] . '/' . $data['subtype']; - - if ($rfc822 || ($type == 'message/rfc822')) { - $ob = new Horde_MIME_Message(); - } else { - $ob = new Horde_MIME_Part(); - } - - $ob->setType($type); - - if (isset($data['encoding'])) { - $ob->setTransferEncoding($data['encoding']); - } - - if (isset($data['disposition'])) { - $ob->setDisposition($data['disposition']); - if (!empty($data['dparameters'])) { - foreach ($data['dparameters'] as $key => $val) { - $ob->setDispositionParameter($key, $val); - } - } - } - - if (isset($data['size'])) { - $ob->setBytes($data['size']); - } - - if (isset($data['id'])) { - $ob->setContentID($data['id']); - } - - if (!empty($data['parameters'])) { - foreach ($data['parameters'] as $key => $val) { - $ob->setContentTypeParameter($key, $val); - } - } - - /* Set the default character set. */ - if (($data['subtype'] == 'text') && - (String::lower($ob->getCharset()) == 'us-ascii') && - isset($GLOBALS['mime_structure']['default_charset'])) { - /* @todo - switch to using static variable for this. */ - //$ob->setCharset($GLOBALS['mime_structure']['default_charset']); - } - - if (isset($data['description'])) { - $ob->setDescription($data['description']); - } - - /* Set the name. */ - if (!$ob->getName()) { - $ob->setName($ob->getDispositionParameter('filename')); - } - - // @todo Handle language, location, md5, lines, envelope - - /* Add multipart parts. */ - if (!empty($data['parts'])) { - reset($data['parts']); - while (list(,$val) = each($data['parts'])) { - $ob->addPart(self::_parseStructure($val)); - } - } elseif (!empty($data['structure'])) { - $ob->addPart(self::_parseStructure($data['structure'])); - } - - return $ob; - } - - /** - * Attempts to build a Horde_MIME_Message object from message text. - * This function can be called statically via: - * $mime_message = Horde_MIME_Message::parseMessage(); - * - * @param string $text The text of the MIME message. - * - * @return Horde_MIME_Message A Horde_MIME_Message object, or false on - * error. - */ - static public function parseMessage($text) - { - /* Set up the options for the mimeDecode class. */ - $decode_args = array( - 'include_bodies' => true, - 'decode_bodies' => false, - 'decode_headers' => false - ); - - require_once 'Mail/mimeDecode.php'; - $mimeDecode = new Mail_mimeDecode($text, Horde_MIME_Part::EOL); - if (!($ob = $mimeDecode->decode($decode_args))) { - return false; - } - - return self::parseStructure(self::_convertMimeDecodeData($ob)); - } - - /** - * Convert the output from Mail_mimeDecode::decode() into a structure that - * parse() can handle. - * - * @param stdClass $ob The output from Mail_mimeDecode::decode(). - * - * @return array An array of structure information. - */ - static protected function _convertMimeDecodeData($ob) - { - /* Primary content-type. */ - if (isset($ob->ctype_primary)) { - $part = array( - 'type' => strtolower($ob->ctype_primary), - 'subtype' => isset($ob->ctype_secondary) ? strtolower($ob->ctype_secondary) : 'x-unknown' - ); - } else { - $part = array( - 'type' => 'application', - 'subtype' => 'octet-stream' - ); - } - - /* Content transfer encoding. */ - if (isset($ob->headers['content-transfer-encoding'])) { - $part['encoding'] = strtolower($ob->headers['content-transfer-encoding']); - } - - /* Content-type and Disposition parameters. */ - $param_types = array( - 'ctype_parameters' => 'parameters', - 'd_parameters' => 'dparameters' - ); - - foreach ($param_types as $param_key => $param_value) { - if (isset($ob->$param_key)) { - $part[$param_value] = array(); - foreach ($ob->$param_key as $key => $val) { - $part[$param_value][strtolower($key)] = $val; - } - } - } - - /* Content-Description. */ - if (isset($ob->headers['content-description'])) { - $part['description'] = $ob->headers['content-description']; - } - - /* Content-Disposition. */ - if (isset($ob->headers['content-disposition'])) { - $hdr = $ob->headers['content-disposition']; - $pos = strpos($hdr, ';'); - if ($pos !== false) { - $hdr = substr($hdr, 0, $pos); - } - $part['disposition'] = strtolower($hdr); - } - - /* Content-ID. */ - if (isset($ob->headers['content-id'])) { - $part['id'] = $ob->headers['content-id']; - } - - /* Get file size (if 'body' text is set). */ - if (isset($ob->body) && - ($part['type'] != 'message') && - ($part['subtype'] != 'rfc822')) { - /* Mail_mimeDecode puts an extra linebreak at the end of body - * text. */ - $size = strlen(str_replace(array("\r\n", "\n"), array("\n", "\r\n"), $ob->body)) - 2; - $part['size'] = ($size < 0) ? 0 : $size; - } - - /* Process parts also. */ - if (isset($ob->parts)) { - $part['parts'] = array(); - reset($ob->parts); - while (list($key,) = each($ob->parts)) { - $part['parts'][] = self::_convertMimeDecodeData($ob->parts[$key]); - } - } - - return $part; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Part.php b/framework/mime_tmp/Horde/Mime/Part.php deleted file mode 100644 index 6af6251b6..000000000 --- a/framework/mime_tmp/Horde/Mime/Part.php +++ /dev/null @@ -1,1324 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME_Part -{ - /* The character(s) used internally for EOLs. */ - const EOL = "\n"; - - /* The character string designated by RFC 2045 to designate EOLs in MIME - * messages. */ - const RFC_EOL = "\r\n"; - - /* The default MIME character set. */ - const DEFAULT_CHARSET = 'us-ascii'; - - /* The default MIME disposition. */ - const DEFAULT_DISPOSITION = 'inline'; - - /* The default MIME encoding. */ - const DEFAULT_ENCODING = '7bit'; - - /** - * The type (ex.: text) of this part. - * Per RFC 2045, the default is 'application'. - * - * @var string - */ - protected $_type = 'application'; - - /** - * The subtype (ex.: plain) of this part. - * Per RFC 2045, the default is 'octet-stream'. - * - * @var string - */ - protected $_subtype = 'octet-stream'; - - /** - * The body of the part. - * - * @var string - */ - protected $_contents = ''; - - /** - * The desired transfer encoding of this part. - * - * @var string - */ - protected $_transferEncoding = self::DEFAULT_ENCODING; - - /** - * Should the message be encoded via 7-bit? - * - * @var boolean - */ - protected $_encode7bit = true; - - /** - * The description of this part. - * - * @var string - */ - protected $_description = ''; - - /** - * The disposition of this part (inline or attachment). - * - * @var string - */ - protected $_disposition = self::DEFAULT_DISPOSITION; - - /** - * The disposition parameters of this part. - * - * @var array - */ - protected $_dispParams = array(); - - /** - * The content type parameters of this part. - * - * @var array - */ - protected $_contentTypeParams = array(); - - /** - * The subparts of this part. - * - * @var array - */ - protected $_parts = array(); - - /** - * Information/Statistics on the subpart. - * - * @var array - */ - protected $_information = array(); - - /** - * The list of CIDs for this part. - * - * @var array - */ - protected $_cids = array(); - - /** - * The MIME ID of this part. - * - * @var string - */ - protected $_mimeid = null; - - /** - * The sequence to use as EOL for this part. - * The default is currently to output the EOL sequence internally as - * just "\n" instead of the canonical "\r\n" required in RFC 822 & 2045. - * To be RFC complaint, the full EOL combination should be used - * when sending a message. - * It is not crucial here since the PHP/PEAR mailing functions will handle - * the EOL details. - * - * @var string - */ - protected $_eol = self::EOL; - - /** - * Internal class flags. - * - * @var array - */ - protected $_flags = array(); - - /** - * Unique Horde_MIME_Part boundary string. - * - * @var string - */ - protected $_boundary = null; - - /** - * Default value for this Part's size. - * - * @var integer - */ - protected $_bytes = 0; - - /** - * The content-ID for this part. - * - * @var string - */ - protected $_contentid = null; - - /** - * Do we need to reindex the current part. - * - * @var boolean - */ - protected $_reindex = false; - - /** - * TODO - */ - protected $_headers; - - /** - * Set the content-disposition of this part. - * - * @param string $disposition The content-disposition to set (inline or - * attachment). - */ - public function setDisposition($disposition) - { - $disposition = String::lower($disposition); - - if (in_array($disposition, array('inline', 'attachment'))) { - $this->_disposition = $disposition; - } - } - - /** - * Get the content-disposition of this part. - * - * @return string The part's content-disposition. - */ - public function getDisposition() - { - return $this->_disposition; - } - - /** - * Add a disposition parameter to this part. - * - * @param string $label The disposition parameter label. - * @param string $data The disposition parameter data. - */ - public function setDispositionParameter($label, $data) - { - $this->_dispParams[$label] = Horde_MIME::decode($data); - } - - /** - * Get a disposition parameter from this part. - * - * @param string $label The disposition parameter label. - * - * @return string The data requested. - * Returns null if $label is not set. - */ - public function getDispositionParameter($label) - { - return (isset($this->_dispParams[$label])) - ? $this->_dispParams[$label] - : null; - } - - /** - * Get all parameters from the Content-Disposition header. - * - * @return array An array of all the parameters - * Returns the empty array if no parameters set. - */ - public function getAllDispositionParameters() - { - return $this->_dispParams; - } - - /** - * Set the name of this part. - * - * @param string $name The name to set. - */ - public function setName($name) - { - $this->setContentTypeParameter('name', $name); - } - - /** - * Get the name of this part. - * - * @param boolean $default If the name parameter doesn't exist, should we - * use the default name from the description - * parameter? - * - * @return string The name of the part. - */ - public function getName($default = false) - { - $name = $this->getContentTypeParameter('name'); - - if ($default && empty($name)) { - $name = preg_replace('|\W|', '_', $this->getDescription(false)); - } - - return $name; - } - - /** - * Set the body contents of this part. - * - * @param string $contents The part body. - * @param string $encoding The current encoding of the contents. - */ - public function setContents($contents, $encoding = null) - { - $this->_contents = $contents; - $this->_flags['contentsSet'] = true; - $this->_flags['currentEncoding'] = is_null($encoding) ? $this->getCurrentEncoding() : $encoding; - } - - /** - * Add to the body contents of this part. - * - * @param string $contents The contents to append to the current part - * body. - * @param string $encoding The current encoding of the contents. If not - * specified, will try to auto determine the - * encoding. - */ - public function appendContents($contents, $encoding = null) - { - if (empty($this->_flags['contentsSet'])) { - $this->setContents($contents, $encoding); - } else { - if (!is_null($encoding) && - ($encoding != $this->getCurrentEncoding())) { - $this->setTransferEncoding($encoding); - $this->transferDecodeContents(); - } - $this->setContents($this->_contents . $contents, $encoding); - } - } - - /** - * Clears the body contents of this part. - */ - public function clearContents() - { - $this->_contents = ''; - unset($this->_flags['contentsSet'], $this->_flags['currentEncoding']); - } - - /** - * Return the body of the part. - * - * @return string The raw body of the part. - */ - public function getContents() - { - return $this->_contents; - } - - /** - * Returns the contents in strict RFC 822 & 2045 output - namely, all - * newlines end with the canonical sequence. - * - * @return string The raw body of the part, with EOL.. - */ - public function getCanonicalContents() - { - return $this->replaceEOL($this->_contents, self::RFC_EOL); - } - - /** - * Transfer encode the contents (to the transfer encoding identified via - * getTransferEncoding()) and set as the part's new contents. - */ - public function transferEncodeContents() - { - $contents = $this->transferEncode(); - $encode = $this->_flags['currentEncoding'] = $this->_flags['lastTransferEncode']; - $this->setContents($contents, $encode); - $this->setTransferEncoding($encode); - } - - /** - * Transfer decode the contents and set them as the new contents. - */ - public function transferDecodeContents() - { - $contents = $this->transferDecode(); - $encode = $this->_flags['currentEncoding'] = $this->_flags['lastTransferDecode']; - $this->setTransferEncoding($encode); - - /* Don't set contents if they are empty, because this will do stuff - like reset the internal bytes field, even though we shouldn't do - that (the user has their reasons to set the bytes field to a - non-zero value without putting the contents into this part). */ - if (strlen($contents)) { - $this->setContents($contents, $encode); - } - } - - /** - * Set the MIME type of this part. - * - * @param string $mimetype The MIME type to set (ex.: text/plain). - */ - public function setType($mimetype) - { - /* RFC 2045: Any entity with unrecognized encoding must be treated - as if it has a Content-Type of "application/octet-stream" - regardless of what the Content-Type field actually says. */ - if ($this->_transferEncoding == 'x-unknown') { - return; - } - - list($this->_type, $this->_subtype) = explode('/', String::lower($mimetype)); - - /* Known types. */ - $known = array( - 'text', 'multipart', 'message', 'application', 'audio', 'image', - 'video', 'model' - ); - - if (in_array($this->_type, $known)) { - /* Set the boundary string for 'multipart/*' parts. */ - if ($this->_type == 'multipart') { - if (!$this->getContentTypeParameter('boundary')) { - $this->setContentTypeParameter('boundary', $this->_generateBoundary()); - } - } else { - $this->clearContentTypeParameter('boundary'); - } - } else { - $this->_type = 'x-unknown'; - $this->clearContentTypeParameter('boundary'); - } - } - - /** - * Get the full MIME Content-Type of this part. - * - * @param boolean $charset Append character set information to the end - * of the content type if this is a text/* part? - * - * @return string The mimetype of this part - * (ex.: text/plain; charset=us-ascii). - */ - public function getType($charset = false) - { - if (!isset($this->_type) || !isset($this->_subtype)) { - return false; - } - - $ptype = $this->getPrimaryType(); - $type = $ptype . '/' . $this->getSubType(); - if ($charset && ($ptype == 'text')) { - $type .= '; charset=' . $this->getCharset(); - } - - return $type; - } - - /** - * If the subtype of a MIME part is unrecognized by an application, the - * default type should be used instead (See RFC 2046). This method - * returns the default subtype for a particular primary MIME type. - * - * @return string The default MIME type of this part (ex.: text/plain). - */ - public function getDefaultType() - { - switch ($this->getPrimaryType()) { - case 'text': - /* RFC 2046 (4.1.4): text parts default to text/plain. */ - return 'text/plain'; - - case 'multipart': - /* RFC 2046 (5.1.3): multipart parts default to multipart/mixed. */ - return 'multipart/mixed'; - - default: - /* RFC 2046 (4.2, 4.3, 4.4, 4.5.3, 5.2.4): all others default to - application/octet-stream. */ - return 'application/octet-stream'; - } - } - - /** - * Get the primary type of this part. - * - * @return string The primary MIME type of this part. - */ - public function getPrimaryType() - { - return $this->_type; - } - - /** - * Get the subtype of this part. - * - * @return string The MIME subtype of this part. - */ - public function getSubType() - { - return $this->_subtype; - } - - /** - * Set the character set of this part. - * - * @param string $charset The character set of this part. - */ - public function setCharset($charset) - { - $this->setContentTypeParameter('charset', $charset); - } - - /** - * Get the character set to use for of this part. Returns a charset for - * all types (not just 'text/*') since we use this charset to determine - * how to encode text in MIME headers. - * - * @return string The character set of this part. Returns null if there - * is no character set. - */ - public function getCharset() - { - $charset = $this->getContentTypeParameter('charset'); - return empty($charset) ? null : $charset; - } - - /** - * Set the description of this part. - * - * @param string $description The description of this part. - */ - public function setDescription($description) - { - $this->_description = Horde_MIME::decode($description); - } - - /** - * Get the description of this part. - * - * @param boolean $default If the name parameter doesn't exist, should we - * use the default name from the description - * parameter? - * - * @return string The description of this part. - */ - public function getDescription($default = false) - { - $desc = $this->_description; - - if ($default && empty($desc)) { - $desc = $this->getName(); - } - - return $desc; - } - - /** - * Set the transfer encoding to use for this part. - * - * @param string $encoding The transfer encoding to use. - */ - public function setTransferEncoding($encoding) - { - $known = array('7bit', '8bit', 'binary', 'base64', 'quoted-printable'); - $encoding = String::lower($encoding); - - if (in_array($encoding, $known)) { - $this->_transferEncoding = $encoding; - } else { - /* RFC 2045: Any entity with unrecognized encoding must be treated - as if it has a Content-Type of "application/octet-stream" - regardless of what the Content-Type field actually says. */ - $this->setType('application/octet-stream'); - $this->_transferEncoding = 'x-unknown'; - } - } - - /** - * Add a MIME subpart. - * - * @param Horde_MIME_Part $mime_part Add a subpart to the current object. - */ - public function addPart($mime_part) - { - $this->_parts[] = $mime_part; - $this->_reindex = true; - } - - /** - * Get a list of all MIME subparts. - * - * @return array An array of the Horde_MIME_Part subparts. - */ - public function getParts() - { - return $this->_parts; - } - - /** - * Retrieve a specific MIME part. - * - * @param string $id The MIME ID. - * - * @return Horde_MIME_Part A pointer to the part requested, or null if - * the part doesn't exist. - */ - public function &getPart($id) - { - $this_id = $this->getMIMEId(); - if ($id == $this_id) { - return $this; - } - - if ($this->_reindex) { - $this->buildMIMEIds(is_null($this_id) ? '1' : $this_id); - } - - return $this->_partFind($id, $this->_parts); - } - - /** - * Remove a subpart. - * - * @param string $id The MIME part to delete. - */ - public function removePart($id) - { - $ob = &$this->getPart($id); - if ($ob !== null) { - unset($ob); - } - } - - /** - * Alter a current MIME subpart. - * - * @param string $id The MIME part ID to alter. - * @param Horde_MIME_Part $mime_part The MIME part to store. - */ - public function alterPart($id, $mime_part) - { - $ob = &$this->getPart($id); - if ($ob !== null) { - $ob = $mime_part; - } - } - - /** - * Function used to find a specific MIME part by ID. - * - * @param string $id The MIME ID. - * @param array &$parts A list of Horde_MIME_Part objects. - */ - protected function &_partFind($id, &$parts) - { - foreach (array_keys($parts) as $val) { - $ret = $parts[$val]->getPart($id); - if ($ret !== null) { - return $ret; - } - } - - $ret = null; - return $ret; - } - - /** - * Add a content type parameter to this part. - * - * @param string $label The disposition parameter label. - * @param string $data The disposition parameter data. - */ - public function setContentTypeParameter($label, $data) - { - $this->_contentTypeParams[$label] = $data; - } - - /** - * Clears a content type parameter from this part. - * - * @param string $label The disposition parameter label. - * @param string $data The disposition parameter data. - */ - public function clearContentTypeParameter($label) - { - unset($this->_contentTypeParams[$label]); - } - - /** - * Get a content type parameter from this part. - * - * @param string $label The content type parameter label. - * - * @return string The data requested. - * Returns null if $label is not set. - */ - public function getContentTypeParameter($label) - { - return isset($this->_contentTypeParams[$label]) - ? $this->_contentTypeParams[$label] - : null; - } - - /** - * Get all parameters from the Content-Type header. - * - * @return array An array of all the parameters - * Returns the empty array if no parameters set. - */ - public function getAllContentTypeParameters() - { - return $this->_contentTypeParameters; - } - - /** - * Sets a new string to use for EOLs. - * - * @param string $eol The string to use for EOLs. - */ - public function setEOL($eol) - { - $this->_eol = $eol; - } - - /** - * Get the string to use for EOLs. - * - * @return string The string to use for EOLs. - */ - public function getEOL() - { - return $this->_eol; - } - - /** - * Returns a Horde_MIME_Header object containing all MIME headers needed - * for the part. - * - * @param Horde_MIME_Headers $headers The Horde_MIME_Headers object to - * add the MIME headers to. If not - * specified, adds the headers to a - * new object. - * - * @return Horde_MIME_Headers A Horde_MIME_Headers object. - */ - public function addMIMEHeaders($headers = null) - { - if (is_null($headers)) { - $headers = new Horde_MIME_Headers(); - } - - foreach ($this->getHeaderArray() as $key => $val) { - $headers->addHeader($key, $val); - } - - return $headers; - } - - /** - * Get the list of MIME headers for this part in an array. - * - * @return array The full set of MIME headers. - */ - public function getHeaderArray() - { - $ptype = $this->getPrimaryType(); - $stype = $this->getSubType(); - - /* Get the character set for this part. */ - $charset = $this->getCharset(); - - /* Get the Content-Type - this is ALWAYS required. */ - $ctype = $this->getType(true); - - /* Manually encode Content-Type and Disposition parameters in here, - * rather than in Horde_MIME_Headers, since it is easier to do when - * the paramters are broken down. Encoding in the headers object will - * ignore these headers Since they will already be in 7bit. */ - foreach ($this->getAllContentTypeParameters() as $key => $value) { - /* Skip the charset key since that would have already been - * added to $ctype by getType(). */ - if ($key == 'charset') { - continue; - } - - $encode_2231 = Horde_MIME::encodeParamString($key, $value, $charset); - /* Try to work around non RFC 2231-compliant MUAs by sending both - * a RFC 2047-like parameter name and then the correct RFC 2231 - * parameter. See: - * http://lists.horde.org/archives/dev/Week-of-Mon-20040426/014240.html */ - if (!empty($GLOBALS['conf']['mailformat']['brokenrfc2231']) && - (strpos($encode_2231, '*=') !== false)) { - $ctype .= '; ' . $key . '="' . Horde_MIME::encode($value, $charset) . '"'; - } - $ctype .= '; ' . $encode_2231; - } - $headers['Content-Type'] = $ctype; - - /* Get the description, if any. */ - if (($descrip = $this->getDescription())) { - $headers['Content-Description'] = $descrip; - } - - /* RFC 2045 [4] - message/rfc822 and message/partial require the - MIME-Version header only if they themselves claim to be MIME - compliant. */ - if (($ptype == 'message') && - (($stype == 'rfc822') || ($stype == 'partial'))) { - // TODO - Check for "MIME-Version" in message/rfc822 part. - $headers['MIME-Version'] = '1.0'; - } - - /* message/* parts require no additional header information. */ - if ($ptype == 'message') { - return $headers; - } - - /* Don't show Content-Disposition for multipart messages unless - there is a name parameter. */ - $name = $this->getName(); - if (($ptype != 'multipart') || !empty($name)) { - $disp = $this->getDisposition(); - - /* Add any disposition parameter information, if available. */ - if (!empty($name)) { - $encode_2231 = Horde_MIME::encodeParamString('filename', $name, $charset); - /* Same broken RFC 2231 workaround as above. */ - if (!empty($GLOBALS['conf']['mailformat']['brokenrfc2231']) && - (strpos($encode_2231, '*=') !== false)) { - $disp .= '; filename="' . Horde_MIME::encode($name, $charset) . '"'; - } - $disp .= '; ' . $encode_2231; - } - - $headers['Content-Disposition'] = $disp; - } - - /* Add transfer encoding information. */ - $headers['Content-Transfer-Encoding'] = $this->getTransferEncoding(); - - /* Add content ID information. */ - if (!is_null($this->_contentid)) { - $headers['Content-ID'] = $this->_contentid; - } - - return $headers; - } - - /** - * Return the entire part in MIME format. Includes headers on request. - * - * @param boolean $headers Include the MIME headers? - * - * @return string The MIME string. - */ - public function toString($headers = true) - { - $eol = $this->getEOL(); - $ptype = $this->getPrimaryType(); - $text = ''; - - if ($headers) { - $hdr_ob = $this->addMIMEHeaders(); - $hdr_ob->setEOL($eol); - $text = $hdr_ob->toString(array('charset' => $this->getCharset())); - } - - /* Any information about a message/* is embedded in the message - contents themself. Simply output the contents of the part - directly and return. */ - if ($ptype == 'message') { - return $text . $this->_contents; - } - - $text .= $this->transferEncode(); - - /* Deal with multipart messages. */ - if ($ptype == 'multipart') { - $this->_generateBoundary(); - $boundary = trim($this->getContentTypeParameter('boundary'), '"'); - if (!strlen($this->_contents)) { - $text .= 'This message is in MIME format.' . $eol; - } - reset($this->_parts); - while (list(,$part) = each($this->_parts)) { - $text .= $eol . '--' . $boundary . $eol; - $oldEOL = $part->getEOL(); - $part->setEOL($eol); - $text .= $part->toString(true); - $part->setEOL($oldEOL); - } - $text .= $eol . '--' . $boundary . '--' . $eol; - } - - return $text; - } - - /** - * Returns the encoded part in strict RFC 822 & 2045 output - namely, all - * newlines end with the canonical sequence. - * - * @param boolean $headers Include the MIME headers? - * - * @return string The entire MIME part. - */ - public function toCanonicalString($headers = true) - { - $string = $this->toString($headers); - return $this->replaceEOL($string, self::RFC_EOL); - } - - /** - * Should we make sure the message is encoded via 7-bit (e.g. to adhere - * to mail delivery standards such as RFC 2821)? - * - * @param boolean $use7bit Use 7-bit encoding? - */ - public function strict7bit($use7bit) - { - $this->_encode7bit = $use7bit; - } - - /** - * Get the transfer encoding for the part based on the user requested - * transfer encoding and the current contents of the part. - * - * @return string The transfer-encoding of this part. - */ - public function getTransferEncoding() - { - /* If there are no contents, return whatever the current value of - $_transferEncoding is. */ - if (empty($this->_contents)) { - return $encoding; - } - - $encoding = $this->_transferEncoding; - $ptype = $this->getPrimaryType(); - - switch ($ptype) { - case 'message': - /* RFC 2046 [5.2.1] - message/rfc822 messages only allow 7bit, - 8bit, and binary encodings. If the current encoding is either - base64 or q-p, switch it to 8bit instead. - RFC 2046 [5.2.2, 5.2.3, 5.2.4] - All other message/* messages - only allow 7bit encodings. */ - $encoding = ($this->getSubType() == 'rfc822') ? '8bit' : '7bit'; - break; - - case 'text': - if (Horde_MIME::is8bit($this->_contents)) { - $encoding = ($this->_encode7bit) ? 'quoted-printable' : '8bit'; - } elseif (preg_match("/(?:\n|^)[^\n]{999,}(?:\n|$)/", $this->_contents)) { - /* If the text is longer than 998 characters between - * linebreaks, use quoted-printable encoding to ensure the - * text will not be chopped (i.e. by sendmail if being sent - * as mail text). */ - $encoding = 'quoted-printable'; - } - break; - - default: - if (Horde_MIME::is8bit($this->_contents)) { - $encoding = ($this->_encode7bit) ? 'base64' : '8bit'; - } - break; - } - - /* Need to do one last check for binary data if encoding is 7bit or - * 8bit. If the message contains a NULL character at all, the message - * MUST be in binary format. RFC 2046 [2.7, 2.8, 2.9]. Q-P and base64 - * can handle binary data fine so no need to switch those encodings. */ - if (in_array($encoding, array('8bit', '7bit')) && - preg_match('/\x00/', $this->_encoding)) { - $encoding = ($this->_encode7bit) ? 'base64' : 'binary'; - } - - return $encoding; - } - - /** - * Retrieves the current encoding of the contents in the object. - * - * @return string The current encoding. - */ - public function getCurrentEncoding() - { - return empty($this->_flags['currentEncoding']) - ? $this->_transferEncoding - : $this->_flags['currentEncoding']; - } - - /** - * Encodes the contents with the part's transfer encoding. - * - * @return string The encoded text. - */ - public function transferEncode() - { - $encoding = $this->getTransferEncoding(); - $eol = $this->getEOL(); - - /* Set the 'lastTransferEncode' flag so that transferEncodeContents() - can save a call to getTransferEncoding(). */ - $this->_flags['lastTransferEncode'] = $encoding; - - /* If contents are empty, or contents are already encoded to the - correct encoding, return now. */ - if (!strlen($this->_contents) || - ($encoding == $this->_flags['currentEncoding'])) { - return $this->_contents; - } - - switch ($encoding) { - /* Base64 Encoding: See RFC 2045, section 6.8 */ - case 'base64': - /* Keeping these two lines separate seems to use much less - memory than combining them (as of PHP 4.3). */ - $encoded_contents = base64_encode($this->_contents); - return chunk_split($encoded_contents, 76, $eol); - - /* Quoted-Printable Encoding: See RFC 2045, section 6.7 */ - case 'quoted-printable': - $output = Horde_MIME::quotedPrintableEncode($this->_contents, $eol); - if (($eollength = String::length($eol)) && - (substr($output, $eollength * -1) == $eol)) { - return substr($output, 0, $eollength * -1); - } - return $output; - - default: - return $this->replaceEOL($this->_contents); - } - } - - /** - * Decodes the contents of the part to either a 7bit or 8bit encoding. - * - * @return string The decoded text. - * Returns the empty string if there is no text to decode. - */ - public function transferDecode() - { - $encoding = $this->getCurrentEncoding(); - - /* If the contents are empty, return now. */ - if (!strlen($this->_contents)) { - $this->_flags['lastTransferDecode'] = $encoding; - return $this->_contents; - } - - switch ($encoding) { - case 'base64': - $this->_flags['lastTransferDecode'] = '8bit'; - return base64_decode($this->_contents); - - case 'quoted-printable': - $message = preg_replace("/=\r?\n/", '', $this->_contents); - $message = quoted_printable_decode($this->replaceEOL($message)); - $this->_flags['lastTransferDecode'] = (Horde_MIME::is8bit($message)) ? '8bit' : '7bit'; - return $message; - - /* Support for uuencoded encoding - although not required by RFCs, - some mailers may still encode this way. */ - case 'uuencode': - case 'x-uuencode': - case 'x-uue': - $this->_flags['lastTransferDecode'] = '8bit'; - return convert_uuencode($this->_contents); - - default: - if (isset($this->_flags['lastTransferDecode']) && - ($this->_flags['lastTransferDecode'] != $encoding)) { - $message = $this->replaceEOL($this->_contents); - } else { - $message = $this->_contents; - } - $this->_flags['lastTransferDecode'] = $encoding; - return $message; - } - } - - /** - * Split the contents of the current Part into its respective subparts, - * if it is multipart MIME encoding. - * - * The boundary Content-Type parameter must be set for this function to - * work correctly. - * - * @return boolean True if the contents were successfully split. - * False if any error occurred. - */ - public function splitContents() - { - if ((!($boundary = $this->getContentTypeParameter('boundary'))) || - !strlen($this->_contents)) { - return false; - } - - $eol = $this->getEOL(); - $retvalue = false; - - $boundary = '--' . $boundary; - if (substr($this->_contents, 0, strlen($boundary)) == $boundary) { - $pos1 = 0; - } else { - $pos1 = strpos($this->_contents, $eol . $boundary); - if ($pos1 === false) { - return false; - } - } - - $pos1 = strpos($this->_contents, $eol, $pos1 + 1); - if ($pos1 === false) { - return false; - } - $pos1 += strlen($eol); - - reset($this->_parts); - $part_ptr = key($this->_parts); - - while ($pos2 = strpos($this->_contents, $eol . $boundary, $pos1)) { - $this->_parts[$part_ptr]->setContents(substr($this->_contents, $pos1, $pos2 - $pos1)); - $this->_parts[$part_ptr]->splitContents(); - next($this->_parts); - $part_ptr = key($this->_parts); - if (is_null($part_ptr)) { - return false; - } - $pos1 = strpos($this->_contents, $eol, $pos2 + 1); - if ($pos1 === false) { - return true; - } - $pos1 += strlen($eol); - } - - return true; - } - - /** - * Replace newlines in this part's contents with those specified by either - * the given newline sequence or the part's current EOL setting. - * - * @param string $text The text to replace. - * @param string $eol The EOL sequence to use. If not present, uses the - * part's current EOL setting. - * - * @return string The text with the newlines replaced by the desired - * newline sequence. - */ - public function replaceEOL($text, $eol = null) - { - if (is_null($eol)) { - $eol = $this->getEOL(); - } - return preg_replace("/\r?\n/", $eol, $text); - } - - /** - * Determine the size of this MIME part and its child members. - * - * @return integer Size of the part, in bytes. - */ - public function getBytes() - { - $bytes = 0; - - if (empty($this->_flags['contentsSet']) && $this->_bytes) { - $bytes = $this->_bytes; - } elseif ($this->getPrimaryType() == 'multipart') { - reset($this->_parts); - while (list(,$part) = each($this->_parts)) { - /* Skip multipart entries (since this may result in double - counting). */ - if ($part->getPrimaryType() != 'multipart') { - $bytes += $part->getBytes(); - } - } - } else { - $bytes = ($this->getPrimaryType() == 'text') - ? String::length($this->_contents, $this->getCharset()) - : strlen($this->_contents); - } - - return $bytes; - } - - /** - * Explicitly set the size (in bytes) of this part. This value will only - * be returned (via getBytes()) if there are no contents currently set. - * This function is useful for setting the size of the part when the - * contents of the part are not fully loaded (i.e. creating a - * Horde_MIME_Part object from IMAP header information without loading the - * data of the part). - * - * @param integer $bytes The size of this part in bytes. - */ - public function setBytes($bytes) - { - $this->_bytes = $bytes; - } - - /** - * Output the size of this MIME part in KB. - * - * @return string Size of the part, in string format. - */ - public function getSize() - { - $bytes = $this->getBytes(); - if (empty($bytes)) { - return $bytes; - } - - $localeinfo = NLS::getLocaleInfo(); - return number_format($bytes / 1024, 2, $localeinfo['decimal_point'], $localeinfo['thousands_sep']); - } - - /** - * Add to the list of CIDs for this part. - * - * @param array $cids A list of MIME IDs of the part. - * Key - MIME ID - * Value - CID for the part - */ - public function addCID($cids = array()) - { - $this->_cids += $cids; - asort($this->_cids, SORT_STRING); - } - - /** - * Returns the list of CIDs for this part. - * - * @return array The list of CIDs for this part. - */ - public function getCIDList() - { - return $this->_cids; - } - - /** - * Sets the Content-ID header for this part. - * - * @param string $cid Use this CID (if not already set). Else, generate - * a random CID. - */ - public function setContentID($cid = null) - { - if (is_null($this->_contentid)) { - $this->_contentid = (is_null($cid)) ? (Horde_MIME::generateRandomID() . '@' . $_SERVER['SERVER_NAME']) : $cid; - } - return $this->_contentid; - } - - /** - * Returns the Content-ID for this part. - * - * @return string The Content-ID for this part. - */ - public function getContentID() - { - return $this->_contentid; - } - - /** - * Alter the MIME ID of this part. - * - * @param string $mimeid The MIME ID. - */ - public function setMIMEId($mimeid) - { - $this->_mimeid = $mimeid; - } - - /** - * Returns the MIME ID of this part. - * - * @return string The MIME ID. - */ - public function getMIMEId() - { - return $this->_mimeid; - } - - /** - * Build the MIME IDs for this part and all subparts. - * - * @param string $id The ID of this part. - */ - public function buildMIMEIds($id = null) - { - if (is_null($id)) { - if (empty($this->_parts)) { - $this->setMIMEId('1'); - } else { - $this->setMIMEId('0'); - $i = 1; - foreach (array_keys($this->_parts) as $val) { - $this->_parts[$val]->buildMIMEIds($i++); - } - } - } else { - $this->setMIMEId($id . (($this->getType() == 'message/rfc822') ? '.0' : '')); - - if (!empty($this->_parts)) { - $i = 1; - foreach (array_keys($this->_parts) as $val) { - $this->_parts[$val]->buildMIMEIds($id . '.' . $i++); - } - } - } - - $this->_reindex = false; - } - - /** - * Generate the unique boundary string (if not already done). - * - * @return string The boundary string. - */ - protected function _generateBoundary() - { - if (is_null($this->_boundary)) { - $this->_boundary = '=_' . Horde_MIME::generateRandomID(); - } - return $this->_boundary; - } - - /** - * Returns a mapping of all MIME IDs to their content-types. - * - * @param boolean $sort Sort by MIME ID? - * - * @return array Keys: MIME ID; values: content type. - */ - public function contentTypeMap($sort = true) - { - $map = array($this->getMIMEId() => $this->getType()); - foreach ($this->_parts as $val) { - $map += $val->contentTypeMap(false); - } - - if ($sort) { - uksort($map, 'strnatcasecmp'); - } - - return $map; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer.php b/framework/mime_tmp/Horde/Mime/Viewer.php deleted file mode 100644 index cfc47fc87..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer.php +++ /dev/null @@ -1,332 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME_Viewer -{ - /** - * The config array. This array is shared between all instances of - * Horde_MIME_Viewer. - * - * @var array - */ - static protected $_config = array(); - - /** - * The driver cache array. - * - * @var array - */ - static protected $_drivercache = array(); - - /** - * Attempts to return a concrete Horde_MIME_Viewer_* object based on the - * MIME type. - * - * @param string $mime_type The MIME type. - * - * @return Horde_MIME_Viewer The Horde_MIME_Viewer object, or false on - * error. - */ - static final public function factory($mime_type) - { - /* Spawn the relevant driver, and return it (or false on failure). */ - if (($ob = self::_getDriver($mime_type, $GLOBALS['registry']->getApp())) && - self::_resolveDriver($ob['driver'], $ob['app']) && - class_exists($ob['class'])) { - return new $ob['class'](self::$_config['mime_drivers'][$ob['app']][$ob['driver']]); - } - - return false; - } - - /** - * Given a MIME type and an app name, determine which driver can best - * handle the data. - * - * @param string $mime_type MIME type to resolve. - * @param string $app App in which to search for the driver. - * - * @return mixed Returns false if driver could not be found. Otherwise, - * an array with the following elements: - *
-     * 'app' - (string) The app containing the driver (e.g. 'horde')
-     * 'driver' - (string) Name of driver (e.g. 'enscript')
-     * 'exact' - (boolean) Was the driver and exact match?
-     * 
- */ - static final protected function _getDriver($mime_type, $app = 'horde') - { - $sig = $mime_type . '|' . $app; - if (isset(self::$_drivercache[$sig])) { - return self::$_drivercache[$sig]; - } - - /* Make sure 'horde' mime_drivers config is loaded. */ - if (empty(self::$_config['mime_drivers']['horde'])) { - $res = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), 'horde'); - if (is_a($res, 'PEAR_Error')) { - return false; - } - self::$_config = $res; - } - - /* Make sure app's' mime_drivers config is loaded. */ - if (($app != 'horde') && empty(self::$_config['mime_drivers'][$app])) { - $res = Horde::loadConfiguration('mime_drivers.php', array('mime_drivers', 'mime_drivers_map'), $app); - if (is_a($res, 'PEAR_Error')) { - return false; - } - - require_once 'Horde/Array.php'; - self::$_config = Horde_Array::array_merge_recursive_overwrite(self::$_config, $res); - } - - $driver = ''; - $exact = false; - - list($primary_type,) = explode('/', $mime_type, 2); - $allSub = $primary_type . '/*'; - - /* If the app doesn't exist in $mime_drivers_map, check for Horde-wide - * viewers. */ - if (!isset(self::$_config['mime_drivers_map'][$app]) && - ($app != 'horde')) { - return self::_getDriver($mime_type, 'horde'); - } - - $dr = self::$_config['mime_drivers'][$app]; - $map = self::$_config['mime_drivers_map'][$app]; - - /* If an override exists for this MIME type, then use that */ - if (isset($map['overrides'][$mime_type])) { - $driver = $map['overrides'][$mime_type]; - $exact = true; - } elseif (isset($map['overrides'][$allSub])) { - $driver = $map['overrides'][$allSub]; - $exact = true; - } elseif (isset($map['registered'])) { - /* Iterate through the list of registered drivers, and see if - * this MIME type exists in the MIME types that they claim to - * handle. If the driver handles it, then assign it as the - * rendering driver. If we find a generic handler, keep iterating - * to see if we can find a specific handler. */ - foreach ($map['registered'] as $val) { - if (in_array($mime_type, $dr[$val]['handles'])) { - $driver = $val; - $exact = true; - break; - } elseif (in_array($allSub, $dr[$val]['handles'])) { - $driver = $val; - } - } - } - - /* If this is an application specific app, and an exact match was - not found, search for a Horde-wide specific driver. Only use the - Horde-specific driver if it is NOT the 'default' driver AND the - Horde driver is an exact match. */ - if (!$exact && ($app != 'horde')) { - $ob = self::_getDriver($mime_type, 'horde'); - if (empty($driver) || - (($ob['driver'] != 'default') && $ob['exact'])) { - $driver = $ob['driver']; - $app = 'horde'; - } - } - - /* If the 'default' driver exists in this app, fall back to that. */ - if (empty($driver) && self::_resolveDriver('default', $app)) { - $driver = 'default'; - } - - if (empty($driver)) { - return false; - } - - self::$_drivercache[$sig] = array( - 'app' => $app, - 'class' => (($app == 'horde') ? '' : $app . '_') . 'Horde_MIME_Viewer_' . $driver, - 'driver' => $driver, - 'exact' => $exact, - ); - - return self::$_drivercache[$sig]; - } - - /** - * Given a driver and an application, attempts to load the library file. - * - * @param string $driver Driver name. - * @param string $app Application name. - * - * @return boolean True if library file was loaded. - */ - static final protected function _resolveDriver($driver = 'default', - $app = 'horde') - { - $file = ($app == 'horde') - ? dirname(__FILE__) . '/Viewer/' . $driver . '.php' - : $GLOBALS['registry']->applications[$app]['fileroot'] . '/lib/MIME/Viewer/' . $driver . '.php'; - - require_once dirname(__FILE__) . '/Viewer/Driver.php'; - - $old_error = error_reporting(0); - $ret = require_once $file; - error_reporting($old_error); - - return $ret; - } - - /** - * Prints out the status message for a given MIME Part. - * - * @param string $msg The message to output. - * @param string $img An image link to add to the beginning of the - * message. - * @param string $class An optional style for the status box. - * - * @return string The formatted status message string. - */ - static public function formatStatusMsg($msg, $img = null, $class = null) - { - if (empty($msg)) { - return ''; - } - - if (!is_array($msg)) { - $msg = array($msg); - } - - /* If we are viewing as an attachment, don't print HTML code. */ - if (self::viewAsAttachment()) { - return implode("\n", $msg); - } - - if (is_null($class)) { - $class = 'mimeStatusMessage'; - } - $text = ''; - - /* If no image, simply print out the message. */ - if (is_null($img)) { - foreach ($msg as $val) { - $text .= '' . "\n"; - } - } else { - $text .= '' . "\n"; - } - - return $text . '
' . $val . '
' . $img . ''; - if (count($msg) == 1) { - $text .= $msg[0]; - } else { - $text .= ''; - foreach ($msg as $val) { - $text .= '' . "\n"; - } - $text .= '
' . $val . '
'; - } - $text .= '
'; - } - - /** - * Given a MIME type, this function will return an appropriate icon. - * - * @param string $mime_type The MIME type that we need an icon for. - * - * @return string The URL to the appropriate icon. - */ - static final public function getIcon($mime_type) - { - $app = $GLOBALS['registry']->getApp(); - $ob = self::_getIcon($mime_type, $app); - - if (is_null($ob)) { - if ($app == 'horde') { - return null; - } - - $obHorde = self::_getIcon($mime_type, 'horde'); - return is_null($obHorde) ? null : $obHorde['url']; - } elseif (($ob['match'] !== 0) && ($app != 'horde')) { - $obHorde = self::_getIcon($mime_type, 'horde'); - if (!is_null($ob['match']) && - ($obHorde['match'] <= $ob['match'])) { - return $obHorde['url']; - } - } - - return $ob['url']; - } - - /** - * Given an input MIME type and app, this function returns the URL of an - * icon that can be associated with it - * - * @param string $mime_type MIME type to get the icon for. - * - * @return mixed Null if not found, or an array with the following keys: - *
-     * 'exact' - (integer) How exact the match is.
-     *           0 => 'exact', 1 => 'primary', 2 => 'driver',
-     *           3 => 'default', or null.
-     * 'url' - (string) URL to an icon, or null if none could be found.
-     * 
- */ - static final protected function _getIcon($mime_type, $app = 'horde') - { - if (!($ob = self::_getDriver($mime_type, $app))) { - return null; - } - $driver = $ob['driver']; - - list($primary_type,) = explode('/', $mime_type, 2); - $allSub = $primary_type . '/*'; - $ret = null; - - /* If the app doesn't exist in $mime_drivers, return now. */ - if (!isset(self::$_config['mime_drivers'][$app])) { - return null; - } - - $dr = self::$_config['mime_drivers'][$app]; - - /* If a specific icon for this driver and mimetype is defined, - then use that. */ - if (isset($dr[$driver]['icons'])) { - $icondr = $dr[$driver]['icons']; - $iconList = array($mime_type => 0, $allSub => 1, 'default' => 2); - foreach ($iconList as $key => $val) { - if (isset($icondr[$key])) { - $ret = array('match' => $val, 'url' => $icondr[$key]); - break; - } - } - } - - /* Try to use a default icon if none already obtained. */ - if (is_null($ret['url']) && - isset($dr['default']['icons']['default'])) { - $ret = array('match' => 3, 'url' => $dr['default']['icons']['default']); - } - - if (!is_null($ret)) { - $ret['url'] = $GLOBALS['registry']->getImageDir($app) . '/mime/' . $ret['url']; - } - - return $ret; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/Driver.php b/framework/mime_tmp/Horde/Mime/Viewer/Driver.php deleted file mode 100644 index e441e2713..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/Driver.php +++ /dev/null @@ -1,186 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME - */ -class Horde_MIME_Viewer_Driver -{ - /** - * Viewer configuration. - * - * @var array - */ - protected $_conf = array(); - - /** - * The Horde_MIME_Part object to render. - * - * @var Horde_MIME_Part - */ - protected $_mimepart = null; - - /** - * Viewer parameters. - * - * @var array - */ - protected $_params = array(); - - /** - * Can this driver render various views? - * - * @var boolean - */ - protected $_canrender = array( - 'full' => false, - 'info' => false, - 'inline' => false, - ); - - /** - * Constructor. - * - * @param array $conf Configuration specific to the driver. - */ - function __construct($conf = array()) - { - $this->_conf = $conf; - } - - /** - * Sets the Horde_MIME_Part object for the class. - * - * @param Horde_MIME_Part &$mime_part Reference to an object with the - * information to be rendered. - */ - public function setMIMEPart(&$mime_part) - { - $this->_mimepart = $mime_part; - } - - /** - * Set parameters for use with this object. - * - * @param array $params An array of params to add to the internal - * params list. - */ - public function setParams($params = array()) - { - $this->_params = array_merge($this->_params, $params); - } - - /** - * Return the rendered version of the Horde_MIME_Part object. - * - * @return array TODO - */ - public function render() - { - return (is_null($this->_mimepart) || !$this->canDisplay()) - ? array('data' => '', 'type' => 'text/plain') - : $this->_render(); - } - - /** - * Return the rendered version of the Horde_MIME_Part object. - * - * @return string Rendered version of the Horde_MIME_Part object. - */ - protected function _render() - { - } - - /** - * Return the rendered inline version of the Horde_MIME_Part object. - * - * @return string Rendered version of the Horde_MIME_Part object. - */ - public function renderInline() - { - return (is_null($this->_mimepart) || !$this->canDisplayInline()) - ? '' - : $this->_renderInline(); - } - - /** - * Return the rendered inline version of the Horde_MIME_Part object. - * - * @return string Rendered version of the Horde_MIME_Part object. - */ - protected function _renderInline() - { - } - - /** - * Return the rendered information about the Horde_MIME_Part object. - * - * @return string Rendered information on the Horde_MIME_Part object. - */ - public function renderInfo() - { - return (is_null($this->_mimepart) || !$this->canDisplayInfo()) - ? '' - : $this->_renderInfo(); - } - - /** - * Return the rendered information about the Horde_MIME_Part object. - * - * @return string Rendered information on the Horde_MIME_Part object. - */ - protected function _renderInfo() - { - } - - /** - * Can this driver render the the data? - * - * @return boolean True if the driver can render data. - */ - public function canDisplay() - { - return $this->_canrender['full']; - } - - /** - * Can this driver render the the data inline? - * - * @return boolean True if the driver can display inline. - */ - public function canDisplayInline() - { - return $this->getConfigParam('inline') && $this->_canrender['inline']; - } - - /** - * Can this driver render the the data inline? - * - * @return boolean True if the driver can display inline. - */ - public function canDisplayInfo() - { - return $this->_canrender['info']; - } - - /** - * Return a configuration parameter for the current viewer. - * - * @param string $param The parameter name. - * - * @return mixed The value of the parameter; returns null if the - * parameter doesn't exist. - */ - public function getConfigParam($param) - { - return isset($this->_conf[$param]) ? $this->_conf[$param] : null; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/audio.php b/framework/mime_tmp/Horde/Mime/Viewer/audio.php deleted file mode 100644 index df83fbeb6..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/audio.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_audio extends Horde_MIME_Viewer_Driver -{ - /** - * Return the content-type. - * - * @return string The content-type of the output. - */ - public function getType() - { - return $this->mime_part->getType(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/css.php b/framework/mime_tmp/Horde/Mime/Viewer/css.php deleted file mode 100644 index d11ebed79..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/css.php +++ /dev/null @@ -1,109 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_css extends Horde_MIME_Viewer_source -{ - /** - * Render out the currently set contents. - * - * @param array $params Any parameters the viewer may need. - * - * @return string The rendered text. - */ - public function render($params = null) - { - $css = htmlspecialchars($this->mime_part->getContents(), ENT_NOQUOTES); - $css = preg_replace_callback('!(}|\*/).*?({|/\*)!s', array($this, '_handles'), $css); - $css = preg_replace_callback('!{[^}]*}!s', array($this, '_attributes'), $css); - $css = preg_replace_callback('!/\*.*?\*/!s', array($this, '_comments'), $css); - $css = trim($css); - - // Educated Guess at whether we are inline or not. - if (headers_sent() || ob_get_length()) { - return $this->lineNumber($css); - } else { - return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') . - $this->lineNumber($css) . - Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); - } - } - - /** - */ - protected function _comments($matches) - { - $patterns[] = '!(http://[/\w-.]+)!s'; - $replaces[] = '\\1'; - - $comments = preg_replace($patterns, $replaces, $matches[0]); - - return '' . $comments . ''; - } - - /** - */ - protected function _attributes($matches) - { - // Attributes. - $patterns[] = '!([-\w]+\s*):!s'; - $replaces[] = '\\1:'; - - // Values. - $patterns[] = '!:(\s*)(.+?)(\s*;)!s'; - $replaces[] = ':\\1\\2\\3'; - - // URLs. - $patterns[] = '!(url\([\'"]?)(.*?)([\'"]?\))!s'; - $replaces[] = '\\1\\2\\3'; - - // Colors. - $patterns[] = '!(#[[:xdigit:]]{3,6})!s'; - $replaces[] = '\\1'; - - // Parentheses. - $patterns[] = '!({|})!s'; - $replaces[] = '\\1'; - - // Unity. - $patterns[] = '!(em|px|%)\b!s'; - $replaces[] = '\\1'; - - return preg_replace($patterns, $replaces, $matches[0]); - } - - /** - */ - protected function _handles($matches) - { - // HTML Tags. - $patterns[] = '!\b(body|h\d|a|span|div|acronym|small|strong|em|pre|ul|ol|li|p)\b!s'; - $replaces[] = '\\1\\2'; - - // IDs. - $patterns[] = '!(#[-\w]+)!s'; - $replaces[] = '\\1'; - - // Class. - $patterns[] = '!(\.[-\w]+)\b!s'; - $replaces[] = '\\1'; - - // METAs. - $patterns[] = '!(:link|:visited|:hover|:active|:first-letter)!s'; - $replaces[] = '\\1'; - - return preg_replace($patterns, $replaces, $matches[0]); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/deb.php b/framework/mime_tmp/Horde/Mime/Viewer/deb.php deleted file mode 100644 index 7afdc97d9..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/deb.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_deb extends Horde_MIME_Viewer_Driver -{ - /** - * Render the data. - * - * @param array $params Any parameters the viewer may need. - * - * @return string The rendered data. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['deb']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['deb']['location']) . '
'; - } - - $tmp_deb = Horde::getTempFile('horde_deb'); - - $fh = fopen($tmp_deb, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - $fh = popen($GLOBALS['mime_drivers']['horde']['deb']['location'] . " -f $tmp_deb 2>&1", 'r'); - while (($rc = fgets($fh, 8192))) { - $data .= $rc; - } - pclose($fh); - - return '
' . htmlspecialchars($data) . '
'; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/default.php b/framework/mime_tmp/Horde/Mime/Viewer/default.php deleted file mode 100644 index 4872f75f2..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/default.php +++ /dev/null @@ -1,17 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_default extends Horde_MIME_Viewer_Driver -{ -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/enriched.php b/framework/mime_tmp/Horde/Mime/Viewer/enriched.php deleted file mode 100644 index a46db587f..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/enriched.php +++ /dev/null @@ -1,158 +0,0 @@ - command and the next balancing - * removes all other formatting commands (all text enclosed - * in angle brackets), and outside of environments converts - * any series of n CRLFs to n-1 CRLFs, and converts any lone CRLF - * pairs to SPACE. - * - * We don't qualify as we don't currently track the - * environment, that is we do CRLF conversion even if is - * specified in the text, but we're close at least. - * - * Copyright 2001-2008 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. - * - * @author Eric Rostetter - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_enriched extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the currently set contents in HTML format. The - * $mime_part class variable has the information to render out, - * encapsulated in a MIME_Part object. - */ - public function render() - { - if (($text = $this->mime_part->getContents()) === false) { - return false; - } - - if (trim($text) == '') { - return $text; - } - - // We add space at the beginning and end of the string as it will - // make some regular expression checks later much easier (so we - // don't have to worry about start/end of line characters) - $text = ' ' . $text . ' '; - - // We need to preserve << tags, so map them to ascii 1 or ascii 255 - // We make the assumption here that there would never be an ascii - // 1 in an email, which may not be valid, but seems reasonable... - // ascii 255 would work if for some reason you don't like ascii 1 - // ascii 0 does NOT seem to work for this, though I'm not sure why - $text = str_replace('<<', chr(1), $text); - - // Remove any unrecognized tags in the text (via RFC minimal specs) - // any tags we just don't want to implement can also be removed here - // Note that this will remove any html links, but this is intended - $implementedTags = '' . - '
' . - ''; - // $unImplementedTags = ''; - $text = strip_tags($text, $implementedTags); - - // restore the << tags as < tags now... - $text = str_replace(chr(1), '<<', $text); - // $text = str_replace(chr(255), '<', $text); - - // Get color parameters into a more useable format. - $text = preg_replace('/([\da-fA-F]+),([\da-fA-F]+),([\da-fA-F]+)<\/param>/Uis', '', $text); - $text = preg_replace('/(red|blue|green|yellow|cyan|magenta|black|white)<\/param>/Uis', '', $text); - - // Get font family parameters into a more useable format. - $text = preg_replace('/(\w+)<\/param>/Uis', '', $text); - - // Just remove any remaining parameters -- we won't use - // them. Any tags with parameters that we want to implement - // will have to come before this Someday we hope to use these - // tags (e.g. for tags) - $text = preg_replace('/.*<\/param>/Uis', '', $text); - - // Single line breaks become spaces, double line breaks are a - // real break. This needs to do tracking to be - // compliant but we don't want to deal with state at this - // time, so we fake it some day we should rewrite this to - // handle correctly. - $text = preg_replace('/([^\n])\r\n([^\r])/', '\1 \2', $text); - $text = preg_replace('/(\r\n)\r\n/', '\1', $text); - - // We try to protect against bad stuff here. - $text = @htmlspecialchars($text, ENT_QUOTES, $this->mime_part->getCharset()); - - // Now convert the known tags to html. Try to remove any tag - // parameters to stop people from trying to pull a fast one - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace_callback('/(?\2', $text); - $text = preg_replace('/(?\2', $text); - $text = preg_replace('/(?', $text); - $text = preg_replace('/(?', $text); - $text = preg_replace('/(?', $text); - $text = preg_replace('/(?', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - $text = preg_replace('/(?\1', $text); - - // Replace << with < now (from translated HTML form). - $text = str_replace('<<', '<', $text); - - // Now we remove the leading/trailing space we added at the - // start. - $text = preg_replace('/^ (.*) $/s', '\1', $text); - - // Make URLs clickable. - require_once 'Horde/Text/Filter.php'; - $text = Text_Filter::filter($text, 'linkurls', array('callback' => 'Horde::externalUrl')); - - // Wordwrap -- note this could impact on our above RFC - // compliance *IF* we honored nofill tags (which we don't - // yet). - $text = str_replace("\t", ' ', $text); - $text = str_replace(' ', '  ', $text); - $text = str_replace("\n ", "\n ", $text); - if ($text[0] == ' ') { - $text = ' ' . substr($text, 1); - } - $text = nl2br($text); - $text = '

' . $text . '

'; - - return $text; - } - - /** - */ - public function colorize($colors) - { - for ($i = 1; $i < 4; $i++) { - $colors[$i] = sprintf('%02X', round(hexdec($colors[$i]) / 255)); - } - return '' . $colors[4] . ''; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/enscript.php b/framework/mime_tmp/Horde/Mime/Viewer/enscript.php deleted file mode 100644 index 7d3edb18b..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/enscript.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_enscript extends Horde_MIME_Viewer_source -{ - /** - * Render out the data using Enscript. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered data. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['enscript']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['enscript']['location']) . '
'; - } - - /* Create temporary files for input to Enscript. Note that we - cannot use a pipe, since enscript must have access to the - whole file to determine its type for coloured syntax - highlighting. */ - $tmpin = Horde::getTempFile('EnscriptIn'); - - /* Write the contents of our buffer to the temporary input file. */ - $contents = $this->mime_part->getContents(); - $fh = fopen($tmpin, 'wb'); - fwrite($fh, $contents, strlen($contents)); - fclose($fh); - - /* Execute the enscript command. */ - $lang = escapeshellarg($this->_typeToLang($this->mime_part->getType())); - $results = shell_exec($GLOBALS['mime_drivers']['horde']['enscript']['location'] . " -E$lang --language=html --color --output=- < $tmpin"); - - /* Strip out the extraneous HTML from Enscript, and output it. */ - $res_arr = preg_split('/\<\/?pre\>/i', $results); - if (count($res_arr) == 3) { - $results = trim($res_arr[1]); - } - - /* Educated Guess at whether we are inline or not. */ - if (headers_sent() || ob_get_length()) { - return $this->lineNumber($results); - } else { - return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') . - $this->lineNumber($results) . - Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); - } - } - - /** - * Attempts to determine what language to use for the enscript program - * from a MIME type. - * - * @param string $type The MIME type. - * - * @return string The enscript 'language' parameter string. - */ - protected function _typeToLang($type) - { - include_once dirname(__FILE__) . '/../Magic.php'; - - $ext = Horde_MIME_Magic::MIMEToExt($type); - - switch ($ext) { - case 'cs': - return 'java'; - - case 'el': - return 'elisp'; - - case 'h': - return 'c'; - - case 'C': - case 'H': - case 'cc': - case 'hh': - case 'c++': - case 'cxx': - case 'cpp': - return 'cpp'; - - case 'htm': - case 'shtml': - case 'xml': - return 'html'; - - case 'js': - return 'javascript'; - - case 'pas': - return 'pascal'; - - case 'al': - case 'cgi': - case 'pl': - case 'pm': - return 'perl'; - - case 'ps': - return 'postscript'; - - case 'vb': - return 'vba'; - - case 'vhd': - return 'vhdl'; - - case 'patch': - case 'diff': - return 'diffu'; - - default: - return $ext; - } - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/html.php b/framework/mime_tmp/Horde/Mime/Viewer/html.php deleted file mode 100644 index b8317b7c8..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/html.php +++ /dev/null @@ -1,166 +0,0 @@ - - * @author Jon Parise - * @author Michael Slusarz - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_html extends Horde_MIME_Viewer_Driver -{ - /** - * Can this driver render various views? - * - * @var boolean - */ - protected $_canrender = array( - 'full' => true, - 'info' => false, - 'inline' => true, - ); - - /** - * Render out the currently set contents. - * - * @return string The rendered text. - */ - public function _render() - { - return array('data' => $this->_cleanHTML($this->_mimepart->getContents(), false), 'type' => $this->_mimepart->getType(true)); - } - - /** - * TODO - */ - public function _renderInline() - { - return String::convertCharset($this->_cleanHTML($this->_mimepart->getContents(), true), $this->_mimepart->getCharset()); - } - - /** - * Filters active content, dereferences external links, detects phishing, - * etc. - * - * @todo Use IP checks from - * http://lxr.mozilla.org/mailnews/source/mail/base/content/phishingDetector.js. - * - * @param string $data The HTML data. - * @param boolean $inline Are we viewing inline? - * - * @return string The cleaned HTML data. - */ - protected function _cleanHTML($data, $inline) - { - global $browser, $prefs; - - $phish_warn = false; - - /* Deal with tags in the HTML, since they will screw up our own - * relative paths. */ - if (preg_match('/ ]*)"? ?\/?>/i', $data, $matches)) { - $base = $matches[1]; - if (substr($base, -1) != '/') { - $base .= '/'; - } - - /* Recursively call _cleanHTML() to prevent clever fiends from - * sneaking nasty things into the page via $base. */ - $base = $this->_cleanHTML($base, $inline); - - /* Attempt to fix paths that were relying on a tag. */ - if (!empty($base)) { - $pattern = array('|src=(["\'])([^:"\']+)\1|i', - '|src=([^: >"\']+)|i', - '|href= *(["\'])([^:"\']+)\1|i', - '|href=([^: >"\']+)|i'); - $replace = array('src=\1' . $base . '\2\1', - 'src=' . $base . '\1', - 'href=\1' . $base . '\2\1', - 'href=' . $base . '\1'); - $data = preg_replace($pattern, $replace, $data); - } - } - - require_once 'Horde/Text/Filter.php'; - $strip_style_attributes = (($browser->isBrowser('mozilla') && - $browser->getMajor() == 4) || - $browser->isBrowser('msie')); - $strip_styles = $inline || $strip_style_attributes; - $data = Text_Filter::filter($data, 'xss', - array('body_only' => $inline, - 'strip_styles' => $strip_styles, - 'strip_style_attributes' => $strip_style_attributes)); - - /* Check for phishing exploits. */ - if ($this->getConfigParam('phishing_check')) { - if (preg_match('/href\s*=\s*["\']?\s*(http|https|ftp):\/\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:[^>]*>\s*(?:\\1:\/\/)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})[^<]*<\/a)?/i', $data, $m)) { - /* Check 1: Check for IP address links, but ignore if the link - * text has the same IP address. */ - if (!isset($m[3]) || ($m[2] != $m[3])) { - if (isset($m[3])) { - $data = preg_replace('/href\s*=\s*["\']?\s*(http|https|ftp):\/\/' . preg_quote($m[2], '/') . '(?:[^>]*>\s*(?:$1:\/\/)?' . preg_quote($m[3], '/') . '[^<]*<\/a)?/i', 'class="mimeStatusWarning" $0', $data); - } - $phish_warn = true; - } - } elseif (preg_match_all('/href\s*=\s*["\']?\s*(?:http|https|ftp):\/\/([^\s"\'>]+)["\']?[^>]*>\s*(?:(?:http|https|ftp):\/\/)?(.*?)<\/a/is', $data, $m)) { - /* $m[1] = Link; $m[2] = Target - * Check 2: Check for links that point to a different host than - * the target url; if target looks like a domain name, check it - * against the link. */ - for ($i = 0, $links = count($m[0]); $i < $links; ++$i) { - $link = strtolower(urldecode($m[1][$i])); - $target = strtolower(preg_replace('/^(http|https|ftp):\/\//', '', strip_tags($m[2][$i]))); - if (preg_match('/^[-._\da-z]+\.[a-z]{2,}/i', $target) && - (strpos($link, $target) !== 0) && - (strpos($target, $link) !== 0)) { - /* Don't consider the link a phishing link if the - * domain is the same on both links (e.g. - * adtracking.example.com & www.example.com). */ - preg_match('/\.?([^\.\/]+\.[^\.\/]+)[\/?]/', $link, $host1); - preg_match('/\.?([^\.\/]+\.[^\.\/ ]+)([\/ ].*)?$/', $target, $host2); - if (!(count($host1) && count($host2)) || - (strcasecmp($host1[1], $host2[1]) !== 0)) { - $data = preg_replace('/href\s*=\s*["\']?\s*(?:http|https|ftp):\/\/' . preg_quote($m[1][$i], '/') . '["\']?[^>]*>\s*(?:(?:http|https|ftp):\/\/)?' . preg_quote($m[2][$i], '/') . '<\/a/is', 'class="mimeStatusWarning" $0', $data); - $phish_warn = true; - } - } - } - } - } - - /* Try to derefer all external references. */ - $data = preg_replace_callback('/href\s*=\s*(["\'])?((?(1)[^\1]*?|[^\s>]+))(?(1)\1|)/i', - array($this, '_dereferExternalReferencesCallback'), - $data); - - /* Prepend phishing warning. */ - if ($phish_warn) { - $phish_warning = sprintf(_("%s: This message may not be from whom it claims to be. Beware of following any links in it or of providing the sender with any personal information.") . ' ' . _("The links that caused this warning have the same background color as this message."), _("Warning")); - if (!$inline) { - $phish_warning = '' . String::convertCharset($phish_warning, NLS::getCharset(), $this->_mimepart->getCharset()) . '
'; - } - $phish_warning = $this->formatStatusMsg($phish_warning, null, 'mimeStatusWarning'); - - $data = (stristr($data, ')(.*)/i', '$1' . $phish_warning . '$2', $data); - } - - return $data; - } - - /** - * TODO - */ - protected function _dereferExternalReferencesCallback($m) - { - return 'href="' . Horde::externalUrl($m[2]) . '"'; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/images.php b/framework/mime_tmp/Horde/Mime/Viewer/images.php deleted file mode 100644 index ced92d7b1..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/images.php +++ /dev/null @@ -1,95 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_images extends Horde_MIME_Viewer_Driver -{ - /** - * Return the content-type. - * - * @return string The content-type of the output. - */ - public function getType() - { - $type = $this->mime_part->getType(); - if ($GLOBALS['browser']->isBrowser('mozilla') && - ($type == 'image/pjpeg')) { - /* image/jpeg and image/pjpeg *appear* to be the same - * entity, but Mozilla don't seem to want to accept the - * latter. For our purposes, we will treat them the - * same. */ - return 'image/jpeg'; - } elseif ($type == 'image/x-png') { - /* image/x-png is equivalent to image/png. */ - return 'image/png'; - } else { - return $type; - } - } - - /** - * Generate HTML output for a javascript auto-resize view window. - * - * @param string $url The URL which contains the actual image data. - * @param string $title The title to use for the page. - * - * @return string The HTML output. - */ - protected function _popupImageWindow($url, $title) - { - global $browser; - - $str = << - -$title - -EOD; - - /* Only use javascript if we are using a DOM capable browser. */ - if ($browser->getFeature('dom')) { - /* Translate '&' entities to '&' for JS URL links. */ - $url = str_replace('&', '&', $url); - - /* Javascript display. */ - $loading = _("Loading..."); - $str .= << -function resizeWindow() -{ - - var h, img = document.getElementById('disp_image'), w; - document.getElementById('splash').style.display = 'none'; - img.style.display = 'block'; - window.moveTo(0, 0); - h = img.height - (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight)); - w = img.width - (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth)); - window.resizeBy(w, h); - self.focus(); -} - -$loading -EOD; - } else { - /* Non-javascript display. */ - $img_txt = _("Image"); - $str .= << - -$img_txt - - -EOD; - } - - return $str; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/msexcel.php b/framework/mime_tmp/Horde/Mime/Viewer/msexcel.php deleted file mode 100644 index 7b82a6417..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/msexcel.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_msexcel extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the currently data using xlhtml. - * - * @param array $params Any params this Viewer may need. - * - * @return string The rendered data. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['msexcel']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['msexcel']['location']) . '
'; - } - - $data = ''; - $tmp_xls = Horde::getTempFile('horde_msexcel'); - - $fh = fopen($tmp_xls, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - $fh = popen($GLOBALS['mime_drivers']['horde']['msexcel']['location'] . " -nh $tmp_xls 2>&1", 'r'); - while (($rc = fgets($fh, 8192))) { - $data .= $rc; - } - pclose($fh); - - return $data; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/mspowerpoint.php b/framework/mime_tmp/Horde/Mime/Viewer/mspowerpoint.php deleted file mode 100644 index 6bef4dec6..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/mspowerpoint.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_mspowerpoint extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current data using ppthtml. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['mspowerpoint']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['mspowerpoint']['location']) . '
'; - } - - $data = ''; - $tmp_ppt = Horde::getTempFile('horde_mspowerpoint'); - - $fh = fopen($tmp_ppt, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - $fh = popen($GLOBALS['mime_drivers']['horde']['mspowerpoint']['location'] . " $tmp_ppt 2>&1", 'r'); - while (($rc = fgets($fh, 8192))) { - $data .= $rc; - } - pclose($fh); - - return $data; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/msword.php b/framework/mime_tmp/Horde/Mime/Viewer/msword.php deleted file mode 100644 index 7892fb2dd..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/msword.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_msword extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current data using wvWare. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['msword']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['msword']['location']) . '
'; - } - - $data = ''; - $tmp_word = Horde::getTempFile('msword'); - $tmp_output = Horde::getTempFile('msword'); - $tmp_dir = Horde::getTempDir(); - $tmp_file = str_replace($tmp_dir . '/', '', $tmp_output); - - if (OS_WINDOWS) { - $args = ' -x ' . dirname($GLOBALS['mime_drivers']['horde']['msword']['location']) . "\\wvHtml.xml -d $tmp_dir -1 $tmp_word > $tmp_output"; - } else { - $version = exec($GLOBALS['mime_drivers']['horde']['msword']['location'] . ' --version'); - if (version_compare($version, '0.7.0') >= 0) { - $args = " --charset=" . NLS::getCharset() . " --targetdir=$tmp_dir $tmp_word $tmp_file"; - } else { - $args = " $tmp_word $tmp_output"; - } - } - - $fh = fopen($tmp_word, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - exec($GLOBALS['mime_drivers']['horde']['msword']['location'] . $args); - - if (!file_exists($tmp_output)) { - return _("Unable to translate this Word document"); - } - - return file_get_contents($tmp_output); - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo.php b/framework/mime_tmp/Horde/Mime/Viewer/ooo.php deleted file mode 100644 index 4c82e2de4..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo.php +++ /dev/null @@ -1,88 +0,0 @@ - - * @author Jan Schneider - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_ooo extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current data. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - $use_xslt = Util::extensionExists('xslt') || function_exists('domxml_xslt_stylesheet_file'); - if ($use_xslt) { - $tmpdir = Util::createTempDir(true); - } - - require_once 'Horde/Compress.php'; - $xml_tags = array('text:p', 'table:table ', 'table:table-row', 'table:table-cell', 'table:number-columns-spanned='); - $html_tags = array('p', 'table border="0" cellspacing="1" cellpadding="0" ', 'tr bgcolor="#cccccc"', 'td', 'colspan='); - $zip = &Horde_Compress::singleton('zip'); - $list = $zip->decompress($this->mime_part->getContents(), - array('action' => HORDE_COMPRESS_ZIP_LIST)); - foreach ($list as $key => $file) { - if ($file['name'] == 'content.xml' || - $file['name'] == 'styles.xml' || - $file['name'] == 'meta.xml') { - $content = $zip->decompress($this->mime_part->getContents(), - array('action' => HORDE_COMPRESS_ZIP_DATA, - 'info' => $list, - 'key' => $key)); - if ($use_xslt) { - $fp = fopen($tmpdir . $file['name'], 'w'); - fwrite($fp, $content); - fclose($fp); - } elseif ($file['name'] == 'content.xml') { - $content = str_replace($xml_tags, $html_tags, $content); - return $content; - } - } - } - if (!Util::extensionExists('xslt')) { - return; - } - - if (function_exists('domxml_xslt_stylesheet_file')) { - // Use DOMXML - $xslt = domxml_xslt_stylesheet_file(dirname(__FILE__) . '/ooo/main_html.xsl'); - $dom = domxml_open_file($tmpdir . 'content.xml'); - $result = @$xslt->process($dom, array('metaFileURL' => $tmpdir . 'meta.xml', 'stylesFileURL' => $tmpdir . 'styles.xml', 'disableJava' => true)); - return String::convertCharset($xslt->result_dump_mem($result), 'UTF-8', NLS::getCharset()); - } else { - // Use XSLT - $xslt = xslt_create(); - $result = @xslt_process($xslt, $tmpdir . 'content.xml', - dirname(__FILE__) . '/ooo/main_html.xsl', null, null, - array('metaFileURL' => $tmpdir . 'meta.xml', 'stylesFileURL' => $tmpdir . 'styles.xml', 'disableJava' => true)); - if (!$result) { - $result = xslt_error($xslt); - } - xslt_free($xslt); - return String::convertCharset($result, 'UTF-8', NLS::getCharset()); - } - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/common.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/common.xsl deleted file mode 100644 index 943a5b995..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/common.xsl +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - - - - - - - - - - - - = - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - height: ; - - - width: ; - - - height: ; - width: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - margin-left:; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     - - - - - - - - - - - - - - - - - - - - - - - -     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * - * - - - - - - - - - - - - * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/global_document.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/global_document.xsl deleted file mode 100644 index fc4579ef3..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/global_document.xsl +++ /dev/null @@ -1,1674 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Matching child document header No. - absolute-chapter-level: - encodedTitle: - globalDocumentRefToCurrentFile: - *** - - - - - - + - - - - - - - - - - - - - - - - - - Matching global document header No. - absolute-chapter-level: - encodedTitle: - contentTableURL: - *** - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - Creation of global document helper variable for the content table.... - - - - - - - - - - - - - - - - - Finished the Creation of global document helper variable for the content table! - - - - - Creation of global document helper variable for the child documents.... - - - - - - Finished the Creation of global document helper variable for the child documents! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - level: - title: - encoded-title: - file-url: - header-no: - ** - - ** - ** - - - childrenHeadings/heading-count: - - # - title: - ** - - - - - - - - - - - - - - - - - - Creating global document variable for chapter relations.... - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Finished global document variable for chapter relations! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *** new heading - currentChapterID: - currentChapterTitle: - currentChapterID: - currentHeadingNo: - headingTitle: - headingLevel: - headingNo: - newChildURL: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - only a heading, but not a chapter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - All child documents have been walked through without finding the chapter name! - childrenHeadings/heading-count: - currentHeadingNo: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Parsing the global document... - - - - - - - - Parsing the child documents... - - - - - - - - - - - - - Starting the child transformations... - - - - - - Contentable data exists as global data! - - - No Contentable global data exists! - - - - - - - - - - - - - Java method transformChildren to transform all children of a global document could not be found. Be sure to use the XT processor. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Previous document - - - | - - - - - - - - - - - - - - - - - - # - - - - - - Content Table - - - - - - | - - - - - - - - - - - - - - - - - - - - - Next document - - - ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - **** THE HEADING VARIABLE **** - content-table-url: - - - **** new heading: - content-table-id: - child-document-no: - file-url: - out-file-url: - level: - title: - encoded-title: - absolute-chapter-level: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - width: - - - - - - - - - - - - - - - - - - - - - - - - - - - - align: right - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/main_html.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/main_html.xsl deleted file mode 100644 index 443182a3e..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/main_html.xsl +++ /dev/null @@ -1,462 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CSS helper variable will be created.... - - CSS variable ready, header will be created.... - - - CSS header creation finished! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - description - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Creating the inline styles.... - - - - - Time for instantiating style variable: ms - - - - - - Creating the inline styles.... - - - - - Time for instantiating style variable: ms - - - - - - - - - - - Parameter dpi: - Parameter metaFileURL: - Parameter stylesFileURL: - Parameter absoluteSourceDirRef: - Parameter precedingChapterLevel1 : - Parameter precedingChapterLevel2 : - Parameter precedingChapterLevel3 : - Parameter precedingChapterLevel4 : - Parameter precedingChapterLevel5 : - Parameter precedingChapterLevel6 : - Parameter precedingChapterLevel7 : - Parameter precedingChapterLevel8 : - Parameter precedingChapterLevel9 : - Parameter precedingChapterLevel10: - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/palm.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/palm.xsl deleted file mode 100644 index 212edb167..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/palm.xsl +++ /dev/null @@ -1,404 +0,0 @@ - - - - - - - - - - - - - PalmComputingPlatform - true - - - HandheldFriendly - true - - - HistoryListText - Dateimanager : &date &time - - - description - StarPortal - - - keywords - starportal, staroffice, software - - - Content-Type - text/html; charset=iso-8859-1 - - - - - - - - - - - - - - - - - left - - - right - - - center - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - left - - - right - - - center - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #000000 - - - #FFFFFF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #000000 - - - #FFFFFF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_header.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_header.xsl deleted file mode 100644 index eeb0c204a..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_header.xsl +++ /dev/null @@ -1,379 +0,0 @@ - - - - - - - - - - - - - The CSS style header method for setting styles - - - text/css - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { - - - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *.OOo_defaults - - - , - - - - - , - - - - { - margin-top:0cm; margin-bottom:0cm; } - - - - - - - - - - - - - - - - - - - - - - , - - - - - , - - - - - - - - - - - - - - { - - - } - - - - - - - - - - - - - - - - - - - - - - - - , - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_inlined.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_inlined.xsl deleted file mode 100644 index 19159958c..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_inlined.xsl +++ /dev/null @@ -1,398 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_mapping.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_mapping.xsl deleted file mode 100644 index a9a858dc0..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/style_mapping.xsl +++ /dev/null @@ -1,660 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - float: right; - - - float: left; - - - - - - - - align: left; - - - align: right; - - - align: center; - - - - - - - - padding: - - ; - - - - - - - - - border-width:; - border-style:; - border-color:; - - - border-width:; - border-style:; - border-color:; - - - border-width:; - border-style:; - border-color:; - - - - - border-top: ; - - - border-bottom: ; - - - border-left: ; - - - border-right: ; - - - - - - width:; - - - width:; - - - - - - - - height:; - - - height:; - - - - - - - - width:; - - - width:; - - - - - - :; - - - font-family: - - - ; - - font-style:italic; - - - font-weight:bold; - - - - :; - - - :; - - - :; - - - :; - - - :; - - - :; - - - :; - - - :; - - - :; - - - - - - text-align:left ! important; - - - text-align:right ! important; - - - text-align: ! important; - - - - - :; - - - background-color:; - - - background-color:; - - - background-image:url(); - - - background-repeat:repeat; - - - background-repeat:no-repeat; - - - - - - :; - - - - text-decoration:line-through; - - - - - text-decoration:underline; - - - - - vertical-align:sub; - - - vertical-align:sup; - - - - - - - - - - - - - - - - - - - italic, - - - - - - - bold, - - - - - - underline, - - - - - - - align:left, - - - align:right, - - - align:center, - - - - - - - strike, - - - - - size::size, - - - - - - - color:#FFFFFF, - - - color:#000000, - - - - - - - - size::size, - - - - - - width::width, - - - width::width; - - - - - - - - height::height; - - - height::height; - - - - - - - - width::width; - - - width::width; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/table.xsl deleted file mode 100644 index 36339ed73..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table.xsl +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - left - - - right - - - center - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - maxRowLength: - - numberOfHiddenColumns: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - #000000 - 2 - 0 - page-break-inside:avoid - - - - - - - - - - - - - - - - Time for checking BorderStyle: ms - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_cells.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_cells.xsl deleted file mode 100644 index 4671ea96f..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_cells.xsl +++ /dev/null @@ -1,484 +0,0 @@ - - - - - - - - - - - - - - - - - - ---------------> table:table-cell has been entered with node value: - table:number-columns-repeated: -- - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NEW VALUE: column-position: -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +++++++++ starting cell writing +++++++++ - number-columns-repeated: -- - maxRowLength: -- - column-position: -- - - - - - - - - - - - - +++++++++ cell repetition +++++++++ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - WriteTest -> If nothing between '-' write cell -- - - - - - TABLE COLUMN is hidden! - - - - - - - - TABLE COLUMN is hidden! - - - - - - - - - - - th - - - td - - - - - - - - - - - -*****************************************'' element has been added! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text-align:right; - text-align:left; - - - - - - - - - - - - - - - - - - - - text-align:right; - - - text-align:left; - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text-align:right; - - - text-align:left; - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - , - - - - - - ; - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_columns.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_columns.xsl deleted file mode 100644 index a9a907ff8..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_columns.xsl +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DebugInformation: For each 'column-style-entry' of the 'allColumnStyleEntries' variable the style-name is given out. - In case of 'column-hidden-flag' attribute the text 'column is hidden' is given out. - - - - - column is hidden - - - - = - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_rows.xsl b/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_rows.xsl deleted file mode 100644 index 6f7d17d62..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/ooo/table_rows.xsl +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*************************'tr' element has been added! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/framework/mime_tmp/Horde/Mime/Viewer/pdf.php b/framework/mime_tmp/Horde/Mime/Viewer/pdf.php deleted file mode 100644 index 40e46eca7..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/pdf.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_pdf extends Horde_MIME_Viewer_Driver -{ - /** - * Return the content-type. - * - * @return string The content-type of the output. - */ - public function getType() - { - return 'application/pdf'; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/php.php b/framework/mime_tmp/Horde/Mime/Viewer/php.php deleted file mode 100644 index 0c0095487..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/php.php +++ /dev/null @@ -1,138 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_php extends Horde_MIME_Viewer_source -{ - /** - * Renders out the contents. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - ini_set('highlight.comment', 'comment'); - ini_set('highlight.default', 'default'); - ini_set('highlight.keyword', 'keyword'); - ini_set('highlight.string', 'string'); - ini_set('highlight.html', 'html'); - - $code = $this->mime_part->getContents(); - if (strpos($code, 'lineNumber(str_replace('<?php ', '', highlight_string('lineNumber(highlight_string($code, true)); - } - - // Educated guess at whether we are inline or not. - if (headers_sent() || ob_get_length()) { - return $results; - } else { - return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') - . $results - . Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); - } - } - - /** - * Add line numbers to a block of code. - * - * @param string $code The code to number. - */ - public function lineNumber($code, $linebreak = "\n") - { - // Clean up. - $code = preg_replace(array('/\s*/', - '/\s*/', - '/\s*<\/span>\s*<\/span>\s*<\/code>/', - '/\s*<\/font>\s*<\/font>\s*<\/code>/'), - '', - $code); - $code = str_replace(array(' ', - '&', - '
', - '', - ), - array(' ', - '&', - "\n", - '', - ), - $code); - $code = trim($code); - - // Normalize newlines. - $code = str_replace("\r", '', $code); - $code = preg_replace('/\n\n\n+/', "\n\n", $code); - - $lines = explode("\n", $code); - - $results = array('
    '); - $previous = false; - foreach ($lines as $lineno => $line) { - if (substr($line, 0, 7) == '') { - $previous = false; - $line = substr($line, 7); - } - - if (empty($line)) { - $line = ' '; - } - - if ($previous) { - $line = "" . $line; - } - - // Save the previous style. - if (strpos($line, '') { - $previous = false; - } elseif ($previous) { - $line .= ''; - } - - $results[] = '
  1. ' . $line . '
  2. '; - } - - $results[] = '
'; - return implode("\n", $results); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/plain.php b/framework/mime_tmp/Horde/Mime/Viewer/plain.php deleted file mode 100644 index ad0aa17b7..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/plain.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_plain extends Horde_MIME_Viewer_Driver -{ - /** - * Can this driver render various views? - * - * @var boolean - */ - protected $_canrender = array( - 'full' => true, - 'info' => false, - 'inline' => true, - ); - - /** - * Render the contents. - * - * @return array TODO - */ - protected function _render() - { - $text = $this->_mimepart->getContents(); - $charset = $this->_mimepart->getCharset(); - - /* Check for 'flowed' text data. */ - if ($this->_mimepart->getContentTypeParameter('format') == 'flowed') { - $text = $this->_formatFlowed($text, $this->_mimepart->getContentTypeParameter('delsp')); - } - - require_once 'Horde/Text/Filter.php'; - return array( - 'data' => '' . Text_Filter::filter($text, 'text2html', array('parselevel' => TEXT_HTML_MICRO, 'charset' => $charset, 'class' => null)) . '', - 'type' => 'text/html; charset=' . $charset; - ); - } - - /** - * Render the contents for inline viewing. - * - * @return string The rendered contents. - */ - protected function _renderInline() - { - $text = String::convertCharset($this->_mimepart->getContents(), $this->_mimepart->getCharset()); - - /* Check for 'flowed' text data. */ - return ($this->_mimepart->getContentTypeParameter('format') == 'flowed') - ? $this->_formatFlowed($text, $this->_mimepart->getContentTypeParameter('delsp')) - : $text; - } - - /** - * Format flowed text for HTML output. - * - * @param string $text The text to format. - * @param boolean $delsp Was text created with DelSp formatting? - * - * @return string The formatted text. - */ - protected function _formatFlowed($text, $delsp = null) - { - require_once 'Text/Flowed.php'; - $flowed = new Text_Flowed($this->_mimepart->replaceEOL($text, "\n"), $this->_mimepart->getCharset()); - $flowed->setMaxLength(0); - if (!is_null($delsp)) { - $flowed->setDelSp($delsp); - } - return $flowed->toFixed(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/rar.php b/framework/mime_tmp/Horde/Mime/Viewer/rar.php deleted file mode 100644 index 5fe863aa1..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/rar.php +++ /dev/null @@ -1,197 +0,0 @@ - - * @author Michael Cochrane - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_rar extends Horde_MIME_Viewer_Driver -{ - /** - * Rar compression methods. - * - * @var array - */ - protected $_methods = array( - 0x30 => 'Store', - 0x31 => 'Fastest', - 0x32 => 'Fast', - 0x33 => 'Normal', - 0x34 => 'Good', - 0x35 => 'Best' - ); - - /** - * Render out the currently set contents using rar. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - $contents = $this->mime_part->getContents(); - - /* Make sure this is a valid rar file. */ - if ($this->checkRarData($contents) === false) { - return '
' . _("This does not appear to be a valid rar archive.") . '
'; - } - - require_once 'Horde/Text.php'; - - $rarData = $this->getRarData($contents); - $fileCount = count($rarData); - - $text = '' . htmlspecialchars(sprintf(_("Contents of \"%s\""), $this->mime_part->getName())) . ':' . "\n"; - $text .= '
'; - $text .= Text::htmlAllSpaces(_("Archive Name") . ': ' . $this->mime_part->getName()) . "\n"; - $text .= Text::htmlAllSpaces(_("Archive File Size") . ': ' . strlen($contents) . ' bytes') . "\n"; - $text .= Text::htmlAllSpaces(sprintf(ngettext("File Count: %d file", "File Count: %d files", $fileCount), $fileCount)); - $text .= "\n\n"; - $text .= Text::htmlAllSpaces( - String::pad(_("File Name"), 50, ' ', STR_PAD_RIGHT) . - String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) . - String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) . - String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) . - String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) . - String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT) - ) . "\n"; - - $text .= str_repeat('-', 109) . "\n"; - - foreach ($rarData as $val) { - $ratio = (empty($val['size'])) ? 0 : 100 * ($val['csize'] / $val['size']); - $text .= Text::htmlAllSpaces( - String::pad($val['name'], 50, ' ', STR_PAD_RIGHT) . - String::pad($val['attr'], 10, ' ', STR_PAD_LEFT) . - String::pad($val['size'], 10, ' ', STR_PAD_LEFT) . - String::pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) . - String::pad($val['method'], 10, ' ', STR_PAD_LEFT) . - String::pad(sprintf("%1.1f%%", $ratio), 10, ' ', STR_PAD_LEFT) - ) . "\n"; - } - - $text .= str_repeat('-', 106) . "\n"; - $text .= '
'; - - return nl2br($text); - } - - /** - * Returns the MIME type of this part. - * - * @return string The MIME type of this part. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } - - /** - * Checks to see if the data is a valid Rar archive. - * - * @param string &$data The rar archive data. - * - * @return boolean True if valid, false if invalid. - */ - public function checkRarData(&$data) - { - $fileHeader = "\x52\x61\x72\x21\x1a\x07\x00"; - if (strpos($data, $fileHeader) === false) { - return false; - } else { - return true; - } - } - - /** - * Get the list of files/data from the rar archive. - * - * @param string &$data The rar archive data. - * - * @return array KEY: Position in RAR archive - * VALUES: 'attr' -- File attributes - * 'date' -- File modification time - * 'csize' -- Compressed file size - * 'method' -- Compression method - * 'name' -- Filename - * 'size' -- Original file size - */ - public function getRarData(&$data) - { - $return_array = array(); - - $blockStart = strpos($data, "\x52\x61\x72\x21\x1a\x07\x00"); - $position = $blockStart + 7; - - while ($position < strlen($data)) { - $head_crc = substr($data, $position + 0, 2); - $head_type = ord(substr($data, $position + 2, 1)); - $head_flags = unpack('vFlags', substr($data, $position + 3, 2)); - $head_flags = $head_flags['Flags']; - $head_size = unpack('vSize', substr($data, $position + 5, 2)); - $head_size = $head_size['Size']; - - $position += 7; - $head_size -= 7; - - switch ($head_type) { - - case 0x73: - /* Archive header */ - $position += $head_size; - - break; - - case 0x74: - $file = array(); - - /* File Header */ - $info = unpack('VPacked/VUnpacked/COS/VCRC32/VTime/CVersion/CMethod/vLength/vAttrib', substr($data, $position)); - - $file['name'] = substr($data, $position + 25, $info['Length']); - $file['size'] = $info['Unpacked']; - $file['csize'] = $info['Packed']; - - $file['date'] = mktime((($info['Time'] >> 11) & 0x1f), - (($info['Time'] >> 5) & 0x3f), - (($info['Time'] << 1) & 0x3e), - (($info['Time'] >> 21) & 0x07), - (($info['Time'] >> 16) & 0x1f), - ((($info['Time'] >> 25) & 0x7f) + 80)); - - $file['method'] = $this->_methods[$info['Method']]; - - $file['attr'] = ''; - $file['attr'] .= ($info['Attrib'] & 0x10) ? 'D' : '-'; - $file['attr'] .= ($info['Attrib'] & 0x20) ? 'A' : '-'; - $file['attr'] .= ($info['Attrib'] & 0x03) ? 'S' : '-'; - $file['attr'] .= ($info['Attrib'] & 0x02) ? 'H' : '-'; - $file['attr'] .= ($info['Attrib'] & 0x01) ? 'R' : '-'; - - $return_array[] = $file; - - $position += $head_size; - $position += $info['Packed']; - break; - - default: - $position += $head_size; - if (isset($add_size)) { - $position += $add_size; - } - break; - - } - } - - return $return_array; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/report.php b/framework/mime_tmp/Horde/Mime/Viewer/report.php deleted file mode 100644 index 89197e62e..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/report.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_report extends Horde_MIME_Viewer_Driver -{ - /** - * Stores the Horde_MIME_Viewer of the specified protocol. - * - * @var Horde_MIME_Viewer - */ - protected $_viewer; - - /** - * Render the multipart/report data. - * - * @param array $params An array of parameters needed. - * - * @return string The rendered data. - */ - public function render($params = array()) - { - /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ - if (!($this->_resolveViewer())) { - return; - } - - /* Render using the loaded Horde_MIME_Viewer object. */ - return $this->_viewer->render($params); - } - - /** - * Returns the content-type of the Viewer used to view the part. - * - * @return string A content-type string. - */ - public function getType() - { - /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ - if (!($this->_resolveViewer())) { - return 'application/octet-stream'; - } else { - return $this->_viewer->getType(); - } - } - - /** - * Load a Horde_MIME_Viewer according to the report-type parameter stored - * in the MIME_Part to render. If unsuccessful, try to load a generic - * multipart Horde_MIME_Viewer. - * - * @return boolean True on success, false on failure. - */ - protected function _resolveViewer() - { - $type = $viewer = null; - - if (empty($this->_viewer)) { - if (($type = $this->mime_part->getContentTypeParameter('report-type'))) { - $viewer = &Horde_MIME_Viewer::factory($this->mime_part, 'message/' . String::lower($type)); - $type = $this->mime_part->getPrimaryType(); - } else { - /* If report-type is missing, the message is an improper - * multipart/report message. Attempt to fall back to a - * multipart/mixed viewer instead. */ - $type = 'multipart'; - } - - if (empty($viewer) || - (String::lower(get_class($viewer)) == 'mime_viewer_default')) { - if (!($viewer = &Horde_MIME_Viewer::factory($this->mime_part, $type . '/*'))) { - return false; - } - } - $this->_viewer = $viewer; - } - - return true; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/rfc822.php b/framework/mime_tmp/Horde/Mime/Viewer/rfc822.php deleted file mode 100644 index b8a10be20..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/rfc822.php +++ /dev/null @@ -1,98 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_rfc822 extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the currently set contents. - * - * @param array $params An array with any parameters needed. - * - * @return string The rendered text. - */ - public function render($params = array()) - { - if (!$this->mime_part) { - return $this->formatStatusMsg(_("There was an error displaying this message part")); - } - - $part = &Util::cloneObject($this->mime_part); - $part->transferDecodeContents(); - $text = $part->getContents(); - - return $text - ? $text - : $this->formatStatusMsg(_("There was an error displaying this message part")); - } - - /** - * Render out attachment information. - * - * @param array $params An array with any parameters needed. - * - * @return string The rendered text in HTML. - */ - public function renderAttachmentInfo($params = array()) - { - if (!$this->mime_part) { - return ''; - } - - /* Get the text of the part. Since we need to look for the end of - * the headers by searching for the CRLFCRLF sequence, use - * getCanonicalContents() to make sure we are getting the text with - * CRLF's. */ - $text = $this->mime_part->getCanonicalContents(); - if (empty($text)) { - return ''; - } - - /* Search for the end of the header text (CRLFCRLF). */ - $text = substr($text, 0, strpos($text, "\r\n\r\n")); - - /* Get the list of headers now. */ - require_once 'Horde/MIME/Headers.php'; - $headers = Horde_MIME_Headers::parseHeaders($text); - - $header_array = array( - 'date' => _("Date"), - 'from' => _("From"), - 'to' => _("To"), - 'cc' => _("Cc"), - 'bcc' => _("Bcc"), - 'reply-to' => _("Reply-To"), - 'subject' => _("Subject") - ); - $header_output = array(); - - foreach ($header_array as $key => $val) { - $hdr = $headers->getValue($key); - if (!empty($hdr)) { - $header_output[] = '' . $val . ': ' . htmlspecialchars($hdr); - } - } - - require_once 'Horde/Text/Filter.php'; - return '
' . Text_Filter::filter(implode("
\n", $header_output), 'emails') . '
'; - } - - /** - * Return the MIME content type for the rendered data. - * - * @return string The content type of the data. - */ - public function getType() - { - return 'text/plain; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/richtext.php b/framework/mime_tmp/Horde/Mime/Viewer/richtext.php deleted file mode 100644 index e8c696565..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/richtext.php +++ /dev/null @@ -1,152 +0,0 @@ -" to - * "<", converts CRLFs to SPACE, converts to a newline according to - * local newline convention, removes everything between a command - * and the next balancing command, and removes all other - * formatting commands (all text enclosed in angle brackets). - * - * We implement the following tags: - * , , , , , ,
, - * , , , , , , - * , , , , - * - * The following tags are implemented differently than described in the RFC - * (due to limitations in HTML output): - * - Output as centered, bold text. - * - Output as centered, bold text. - * - Output as paragraph break. - * - * The following tags are NOT implemented: - * , , , , , - * , - * - * Copyright 2004-2008 The Horde Project (http://www.horde.org/) - * - * See the enclosed file COPYING for license information (LGPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. - * - * @author Michael Slusarz - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_richtext extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the currently set contents in HTML format. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - if (($text = $this->mime_part->getContents()) === false) { - return false; - } - - if (trim($text) == '') { - return $text; - } - - /* Use str_ireplace() if using PHP 5.0+. */ - $has_str_ireplace = function_exists('str_ireplace'); - - /* We add space at the beginning and end of the string as it will - * make some regular expression checks later much easier (so we - * don't have to worry about start/end of line characters). */ - $text = ' ' . $text . ' '; - - /* Remove everything between tags. */ - $text = preg_replace('/.*<\/comment>/Uis', '', $text); - - /* Remove any unrecognized tags in the text. We don't need - * in $tags since it doesn't do anything anyway. All tags - * have already been removed. */ - $tags = '
'; - $text = strip_tags($text, $tags); - - /* becomes a '<'. CRLF becomes a SPACE. */ - if ($has_str_ireplace) { - $text = str_ireplace(array('', "\r\n"), array('<', ' '), $text); - } else { - $text = preg_replace(array('//i', "/\r\n/"), array('<', ' '), $text); - } - - /* We try to protect against bad stuff here. */ - $text = @htmlspecialchars($text, ENT_QUOTES, $this->mime_part->getCharset()); - - /* becomes a newline (
); - * becomes a paragraph break (

). */ - if ($has_str_ireplace) { - $text = str_ireplace(array('<nl>', '<np>'), array('
', '

'), $text); - } else { - $text = preg_replace(array('/(?', '

'), $text); - } - - /* Now convert the known tags to html. Try to remove any tag - * parameters to stop people from trying to pull a fast one. */ - $pattern = array( - '/(?\1', - '\1', - '\1', - '\1', - '\1', - '\1', - '

\1
', - '
\1
', - '
\1
', - '
\1
', - '\1', - '\1', - '\1', - '
\1

', - '
\1

', - '

\1

', - '
\1
', - ); - $text = preg_replace($pattern, $replace, $text); - - /* Now we remove the leading/trailing space we added at the start. */ - $text = substr($text, 1, -1); - - /* Wordwrap. */ - $text = str_replace(array("\t", ' ', "\n "), array(' ', '  ', "\n "), $text); - if ($text[0] == ' ') { - $text = ' ' . substr($text, 1); - } - - return '

' . nl2br($text) . '

'; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/rpm.php b/framework/mime_tmp/Horde/Mime/Viewer/rpm.php deleted file mode 100644 index 5c12665b6..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/rpm.php +++ /dev/null @@ -1,55 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_rpm extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the RPM contents. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['rpm']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['rpm']['location']) . '
'; - } - - $data = ''; - $tmp_rpm = Horde::getTempFile('horde_rpm'); - - $fh = fopen($tmp_rpm, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - $fh = popen($GLOBALS['mime_drivers']['horde']['rpm']['location'] . " -qip $tmp_rpm 2>&1", 'r'); - while (($rc = fgets($fh, 8192))) { - $data .= $rc; - } - pclose($fh); - - return '
' . htmlentities($data) . '
'; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/rtf.php b/framework/mime_tmp/Horde/Mime/Viewer/rtf.php deleted file mode 100644 index e48e63466..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/rtf.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * See the enclosed file COPYING for license information (LGPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. - * - * @author Duck - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_rtf extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current data using UnRTF. - * - * @param array $params Any parameters the viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['rtf']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['rtf']['location']) . '
'; - } - - $tmp_rtf = Horde::getTempFile('rtf'); - $tmp_output = Horde::getTempFile('rtf'); - $args = " $tmp_rtf > $tmp_output"; - - $fh = fopen($tmp_rtf, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - exec($GLOBALS['mime_drivers']['horde']['rtf']['location'] . $args); - - if (!file_exists($tmp_output)) { - return _("Unable to translate this RTF document"); - } - - return file_get_contents($tmp_output); - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/security.php b/framework/mime_tmp/Horde/Mime/Viewer/security.php deleted file mode 100644 index 480b6e441..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/security.php +++ /dev/null @@ -1,88 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_security extends Horde_MIME_Viewer_Driver -{ - /** - * Stores the Horde_MIME_Viewer of the specified security protocol. - * - * @var Horde_MIME_Viewer - */ - protected $_viewer; - - /** - * The $mime_part class variable has the information to render - * out, encapsulated in a Horde_MIME_Part object. - * - * @param $params mixed The parameters (if any) to pass to the underlying - * Horde_MIME_Viewer. - * - * @return string Rendering of the content. - */ - public function render($params = array()) - { - /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ - if (!($this->_resolveViewer())) { - return; - } - - /* Render using the loaded Horde_MIME_Viewer object. */ - return $this->_viewer->render($params); - } - - /** - * Returns the content-type of the Viewer used to view the part. - * - * @return string A content-type string. - */ - public function getType() - { - /* Get the appropriate Horde_MIME_Viewer for the protocol specified. */ - if (!($this->_resolveViewer())) { - return 'application/octet-stream'; - } else { - return $this->_viewer->getType(); - } - } - - /** - * Load a Horde_MIME_Viewer according to the protocol parameter stored - * in the Horde_MIME_Part to render. If unsuccessful, try to load a generic - * multipart Horde_MIME_Viewer. - * - * @return boolean True on success, false on failure. - */ - protected function _resolveViewer() - { - $viewer = null; - - if (empty($this->_viewer)) { - $protocol = $this->mime_part->getContentTypeParameter('protocol'); - if (empty($protocol)) { - return false; - } - $viewer = &Horde_MIME_Viewer::factory($this->mime_part, $protocol); - if (empty($viewer) || - (String::lower(get_class($viewer)) == 'mime_viewer_default')) { - $viewer = &Horde_MIME_Viewer::factory($this->mime_part, $this->mime_part->getPrimaryType() . '/*'); - if (empty($viewer)) { - return false; - } - } - $this->_viewer = $viewer; - } - - return true; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/simple.php b/framework/mime_tmp/Horde/Mime/Viewer/simple.php deleted file mode 100644 index d2eecd342..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/simple.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_simple extends Horde_MIME_Viewer_Driver -{ - /** - * Return the MIME type of the rendered content. - * - * @return string MIME-type of the output content. - */ - public function getType() - { - return 'text/plain'; - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/smil.php b/framework/mime_tmp/Horde/Mime/Viewer/smil.php deleted file mode 100644 index 8f521a481..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/smil.php +++ /dev/null @@ -1,98 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_smil extends Horde_MIME_Viewer_Driver -{ - /** - * Handle for the XML parser object. - * - * @var resource - */ - protected $_parser; - - /** - * String buffer to hold the generated content - * - * @var string - */ - protected $_content = ''; - - /** - * Renders out the contents. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Create a new parser and set its default properties. */ - $this->_parser = xml_parser_create(); - xml_set_object($this->_parser, $this); - xml_set_element_handler($this->_parser, '_startElement', '_endElement'); - xml_set_character_data_handler($this->_parser, '_defaultHandler'); - xml_parse($this->_parser, $this->mime_part->getContents(), true); - return $this->_content; - } - - /** - * User-defined function callback for start elements. - * - * @param object $parser Handle to the parser instance. - * @param string $name The name of this XML element. - * @param array $attrs List of this element's attributes. - */ - protected function _startElement($parser, $name, $attrs) - { - switch ($name) { - case 'IMG': - if (isset($attrs['SRC'])) { - $this->_content .= ''; - } - break; - } - } - - /** - * User-defined function callback for end elements. - * - * @param object $parser Handle to the parser instance. - * @param string $name The name of this XML element. - */ - protected function _endElement($parser, $name) - { - } - - /** - * User-defined function callback for character data. - * - * @param object $parser Handle to the parser instance. - * @param string $data String of character data. - */ - protected function _defaultHandler($parser, $data) - { - $data = trim($data); - if (!empty($data)) { - $this->_content .= ' ' . htmlspecialchars($data); - } - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/source.php b/framework/mime_tmp/Horde/Mime/Viewer/source.php deleted file mode 100644 index 336946be5..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/source.php +++ /dev/null @@ -1,40 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_source extends Horde_MIME_Viewer_Driver -{ - /** - * Add line numbers to a block of code. - * - * @param string $code The code to number. - */ - public function lineNumber($code, $linebreak = "\n") - { - $lines = substr_count($code, $linebreak) + 1; - $html = '
'; - for ($l = 1; $l <= $lines; $l++) { - $html .= sprintf('%s
', $l, $l, $l) . "\n"; - } - return $html . '
' . $code . '
'; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/srchighlite.php b/framework/mime_tmp/Horde/Mime/Viewer/srchighlite.php deleted file mode 100644 index aa04725a7..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/srchighlite.php +++ /dev/null @@ -1,102 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_srchighlite extends Horde_MIME_Viewer_source -{ - /** - * Render out the currently set contents using Source-highlight - * - * @param array $params Any parameters the viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['srchighlite']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['srchighlite']['location']) . '
'; - } - - /* Create temporary files for Webcpp. */ - $tmpin = Horde::getTempFile('SrcIn'); - $tmpout = Horde::getTempFile('SrcOut', false); - - /* Write the contents of our buffer to the temporary input file. */ - $contents = $this->mime_part->getContents(); - $fh = fopen($tmpin, 'wb'); - fwrite($fh, $contents, strlen($contents)); - fclose($fh); - - /* Determine the language from the mime type. */ - $lang = ''; - switch ($this->mime_part->getType()) { - case 'text/x-java': - $lang = 'java'; - break; - - case 'text/x-csrc': - case 'text/x-c++src': - case 'text/cpp': - $lang = 'cpp'; - break; - - case 'application/x-perl': - $lang = 'perl'; - break; - - case 'application/x-php': - case 'x-extension/phps': - case 'x-extension/php3s': - case 'application/x-httpd-php': - case 'application/x-httpd-php3': - case 'application/x-httpd-phps': - $lang = 'php3'; - break; - - case 'application/x-python': - $lang = 'python'; - break; - - // $lang = 'prolog'; - // break; - - // $lang = 'flex'; - // break; - - // $lang = 'changelog'; - // break; - - // $lang = 'ruby'; - // break; - } - - /* Execute Source-Highlite. */ - exec($GLOBALS['mime_drivers']['horde']['srchighlite']['location'] . " --src-lang $lang --out-format xhtml --input $tmpin --output $tmpout"); - $results = file_get_contents($tmpout); - unlink($tmpout); - - /* Educated Guess at whether we are inline or not. */ - if (headers_sent() || ob_get_length()) { - return $this->lineNumber($results); - } else { - return Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') . - $this->lineNumber($results) . - Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc'); - } - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/tgz.php b/framework/mime_tmp/Horde/Mime/Viewer/tgz.php deleted file mode 100644 index 4bd76649d..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/tgz.php +++ /dev/null @@ -1,104 +0,0 @@ - - * @author Michael Cochrane - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_tgz extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the currently set tar file contents. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - $contents = $this->mime_part->getContents(); - - /* Only decompress gzipped files. */ - $subtype = $this->mime_part->getSubType(); - if (($subtype == 'x-compressed-tar') || - ($subtype == 'tgz') || - ($subtype == 'x-tgz') || - ($subtype == 'gzip') || - ($subtype == 'x-gzip') || - ($subtype == 'x-gzip-compressed') || - ($subtype == 'x-gtar')) { - $gzip = &Horde_Compress::singleton('gzip'); - $contents = $gzip->decompress($contents); - if (empty($contents)) { - return _("Unable to open compressed archive."); - } elseif (is_a($contents, 'PEAR_Error')) { - return $contents->getMessage(); - } - } - - if ($subtype == 'gzip' || - $subtype == 'x-gzip' || - $subtype == 'x-gzip-compressed') { - global $conf; - require_once 'Horde/MIME/Magic.php'; - $mime_type = MIME_Magic::analyzeData($contents, isset($conf['mime']['magic_db']) ? $conf['mime']['magic_db'] : null); - if (!$mime_type) { - $mime_type = _("Unknown"); - } - return sprintf(_("Content type of compressed file: %s"), $mime_type); - } - - /* Obtain the list of files/data in the tar file. */ - $tar = Horde_Compress::factory('tar'); - $tarData = $tar->decompress($contents); - if (is_a($tarData, 'PEAR_Error')) { - return $tarData->getMessage(); - } - - $fileCount = count($tarData); - $text = '' . htmlspecialchars(sprintf(_("Contents of \"%s\""), $this->mime_part->getName())) . ':' . "\n" . - '
' . - Text::htmlAllSpaces(_("Archive Name") . ': ' . $this->mime_part->getName()) . "\n" . - Text::htmlAllSpaces(_("Archive File Size") . ': ' . strlen($contents) . ' bytes') . "\n" . - Text::htmlAllSpaces(sprintf(ngettext("File Count: %d file", "File Count: %d files", $fileCount), $fileCount)) . - "\n\n" . - Text::htmlAllSpaces( - str_pad(_("File Name"), 62, ' ', STR_PAD_RIGHT) . - str_pad(_("Attributes"), 15, ' ', STR_PAD_LEFT) . - str_pad(_("Size"), 10, ' ', STR_PAD_LEFT) . - str_pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) - ) . "\n" . - str_repeat('-', 106) . "\n"; - - foreach ($tarData as $val) { - $text .= Text::htmlAllSpaces( - str_pad($val['name'], 62, ' ', STR_PAD_RIGHT) . - str_pad($val['attr'], 15, ' ', STR_PAD_LEFT) . - str_pad($val['size'], 10, ' ', STR_PAD_LEFT) . - str_pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) - ) . "\n"; - } - - return nl2br($text . str_repeat('-', 106) . "\n" . - '
'); - } - - /** - * Return the content-type - * - * @return string The content-type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/tnef.php b/framework/mime_tmp/Horde/Mime/Viewer/tnef.php deleted file mode 100644 index 64856df00..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/tnef.php +++ /dev/null @@ -1,54 +0,0 @@ - - * @author Michael Slusarz - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_tnef extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current tnef data. - * - * @param array $params Any parameters the viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - require_once 'Horde/Compress.php'; - - $tnef = &Horde_Compress::singleton('tnef'); - - $data = ''; - $info = $tnef->decompress($this->mime_part->getContents()); - if (empty($info) || is_a($info, 'PEAR_Error')) { - $data .= ''; - } else { - $data .= ''; - foreach ($info as $part) { - $data .= ''; - } - } - $data .= '
' . _("MS-TNEF Attachment contained no data.") . '
' . _("Name") . '' . _("Mime Type") . '
' . $part['name'] . '' . $part['type'] . '/' . $part['subtype'] . '
'; - - return $data; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/vcard.php b/framework/mime_tmp/Horde/Mime/Viewer/vcard.php deleted file mode 100644 index b116eb8b3..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/vcard.php +++ /dev/null @@ -1,372 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_vcard extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the vcard contents. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = null) - { - global $registry, $prefs, $notification; - - require_once 'Horde/iCalendar.php'; - - $app = false; - $data = $this->mime_part->getContents(); - $html = ''; - $import_msg = null; - $title = _("vCard"); - - $iCal = new Horde_iCalendar(); - if (!$iCal->parsevCalendar($data, 'VCALENDAR', - $this->mime_part->getCharset())) { - $notification->push( - _("There was an error reading the contact data."), - 'horde.error'); - } - - if (Util::getFormData('import') && - Util::getFormData('source') && - $registry->hasMethod('contacts/import')) { - $source = Util::getFormData('source'); - $contacts = $registry->call('contacts/import', - array($data, 'text/x-vcard', $source)); - if (is_a($contacts, 'PEAR_Error')) { - $notification->push( - _("There was an error importing the contact data:") . ' ' - . $contacts->getMessage(), - 'horde.error'); - } else { - $notification->push(sprintf(ngettext( - "%d contact was successfully added to your address book.", - "%d contacts were successfully added to your address book.", - $iCal->getComponentCount()), - $iCal->getComponentCount()), - 'horde.success'); - } - } - - $html .= ''; - - $i = 0; - foreach ($iCal->getComponents() as $vc) { - if ($i > 0) { - $html .= ''; - } - ++$i; - - $html .= ''; - - $n = $vc->printableName(); - if (!empty($n)) { - $html .= $this->_row(_("Name"), $n); - } - - $aliases = $vc->getAttributeValues('ALIAS'); - if (!is_a($aliases, 'PEAR_Error')) { - $html .= $this->_row(_("Alias"), implode("\n", $aliases)); - } - $birthdays = $vc->getAttributeValues('BDAY'); - if (!is_a($birthdays, 'PEAR_Error')) { - $birthday = new Horde_Date($birthdays[0]); - $html .= $this->_row( - _("Birthday"), - $birthday->strftime($prefs->getValue('date_format'))); - } - - $photos = $vc->getAllAttributes('PHOTO'); - foreach ($photos as $photo) { - if (!isset($photo['params']['VALUE']) || - String::upper($photo['params']['VALUE']) != 'URI') { - continue; - } - $html .= $this->_row(_("Photo"), - '', - false); - } - - $labels = $vc->getAllAttributes('LABEL'); - foreach ($labels as $label) { - if (isset($label['params']['TYPE'])) { - if (!is_array($item['params']['TYPE'])) { - $item['params']['TYPE'] = array($item['params']['TYPE']); - } - } else { - $item['params']['TYPE'] = array_keys($item['params']); - } - $types = array(); - foreach ($item['params']['TYPE'] as $type) { - switch(String::upper($type)) { - case 'HOME': - $types[] = _("Home Address"); - break; - case 'WORK': - $types[] = _("Work Address"); - break; - case 'DOM': - $types[] = _("Domestic Address"); - break; - case 'INTL': - $types[] = _("International Address"); - break; - case 'POSTAL': - $types[] = _("Postal Address"); - break; - case 'PARCEL': - $types[] = _("Parcel Address"); - break; - case 'PREF': - $types[] = _("Preferred Address"); - break; - default: - $types[] = _("Address"); - break; - } - } - $html .= $this->_row(implode('/', $types), $label['value']); - } - - $adrs = $vc->getAllAttributes('ADR'); - foreach ($adrs as $item) { - if (isset($item['params']['TYPE'])) { - if (!is_array($item['params']['TYPE'])) { - $item['params']['TYPE'] = array($item['params']['TYPE']); - } - } else { - $item['params']['TYPE'] = array_keys($item['params']); - } - $address = $item['values']; - $a = array(); - if (isset($address[VCARD_ADR_STREET])) { - $a[] = $address[VCARD_ADR_STREET]; - } - if (isset($address[VCARD_ADR_LOCALITY])) { - $a[] = $address[VCARD_ADR_LOCALITY]; - } - if (isset($address[VCARD_ADR_REGION])) { - $a[] = $address[VCARD_ADR_REGION]; - } - if (isset($address[VCARD_ADR_POSTCODE])) { - $a[] = $address[VCARD_ADR_POSTCODE]; - } - if (isset($address[VCARD_ADR_COUNTRY])) { - $a[] = $address[VCARD_ADR_COUNTRY]; - } - $types = array(); - foreach ($item['params']['TYPE'] as $type) { - switch(String::upper($type)) { - case 'HOME': - $types[] = _("Home Address"); - break; - case 'WORK': - $types[] = _("Work Address"); - break; - case 'DOM': - $types[] = _("Domestic Address"); - break; - case 'INTL': - $types[] = _("International Address"); - break; - case 'POSTAL': - $types[] = _("Postal Address"); - break; - case 'PARCEL': - $types[] = _("Parcel Address"); - break; - case 'PREF': - $types[] = _("Preferred Address"); - break; - default: - $types[] = _("Address"); - break; - } - } - $html .= $this->_row(implode('/', $types), implode("\n", $a)); - } - - $numbers = $vc->getAllAttributes('TEL'); - - foreach ($numbers as $number) { - if (isset($number['params']['TYPE'])) { - if (!is_array($number['params']['TYPE'])) { - $number['params']['TYPE'] = array($number['params']['TYPE']); - } - foreach ($number['params']['TYPE'] as $type) { - $number['params'][String::upper($type)] = true; - } - } - if (isset($number['params']['FAX'])) { - $html .= $this->_row(_("Fax"), $number['value']); - } else { - if (isset($number['params']['HOME'])) { - $html .= $this->_row(_("Home Phone"), - $number['value']); - } elseif (isset($number['params']['WORK'])) { - $html .= $this->_row(_("Work Phone"), - $number['value']); - } elseif (isset($number['params']['CELL'])) { - $html .= $this->_row(_("Cell Phone"), - $number['value']); - } else { - $html .= $this->_row(_("Phone"), - $number['value']); - } - } - } - - $addresses = $vc->getAllAttributes('EMAIL'); - $emails = array(); - foreach ($addresses as $address) { - if (isset($address['params']['TYPE'])) { - if (!is_array($address['params']['TYPE'])) { - $address['params']['TYPE'] = array($address['params']['TYPE']); - } - foreach ($address['params']['TYPE'] as $type) { - $address['params'][String::upper($type)] = true; - } - } - $email = '' . htmlspecialchars($address['value']) . ''; - if (isset($address['params']['PREF'])) { - array_unshift($emails, $email); - } else { - $emails[] = $email; - } - } - - if (count($emails)) { - $html .= $this->_row(_("Email"), implode("\n", $emails), false); - } - - $title = $vc->getAttributeValues('TITLE'); - if (!is_a($title, 'PEAR_Error')) { - $html .= $this->_row(_("Title"), $title[0]); - } - - $role = $vc->getAttributeValues('ROLE'); - if (!is_a($role, 'PEAR_Error')) { - $html .= $this->_row(_("Role"), $role[0]); - } - - $org = $vc->getAttributeValues('ORG'); - if (!is_a($org, 'PEAR_Error')) { - $html .= $this->_row(_("Company"), $org[0]); - if (isset($org[1])) { - $html .= $this->_row(_("Department"), $org[1]); - } - } - - $notes = $vc->getAttributeValues('NOTE'); - if (!is_a($notes, 'PEAR_Error')) { - $html .= $this->_row(_("Notes"), $notes[0]); - } - - $url = $vc->getAttributeValues('URL'); - if (!is_a($url, 'PEAR_Error')) { - $html .= $this->_row( - _("URL"), - '' . htmlspecialchars($url[0]) - . '', - false); - } - } - - if ($registry->hasMethod('contacts/import') && - $registry->hasMethod('contacts/sources')) { - $html .= ''; - } - - $html .= '
 
'; - $fullname = $vc->getAttributeDefault('FN', false); - if ($fullname !== false) { - $html .= $fullname; - } - $html .= '
' - . Util::formInput(); - foreach ($_GET as $key => $val) { - $html .= ''; - } - - $sources = $registry->call('contacts/sources', array(true)); - if (count($sources) > 1) { - $html .= - '' - . '' - . '' - . ''; - } - - $html .= '
 
'; - - return - Util::bufferOutput( - 'include', - $registry->get('templates', 'horde') . '/common-header.inc') - . Util::bufferOutput(array($notification, 'notify'), - array('listeners' => 'status')) - . $html - . Util::bufferOutput( - 'include', - $registry->get('templates', 'horde') . '/common-footer.inc'); - } - - function _row($label, $value, $encode = true) - { - if ($encode) { - $label = htmlspecialchars($label); - $value = htmlspecialchars($value); - } - return '' . $label - . '' . nl2br($value) - . "\n"; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/webcpp.php b/framework/mime_tmp/Horde/Mime/Viewer/webcpp.php deleted file mode 100644 index 6c4ad0da8..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/webcpp.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_webcpp extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the currently set contents using Web C Plus Plus. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - protected function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['webcpp']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['webcpp']['location']) . '
'; - } - - /* Create temporary files for Webcpp. */ - $tmpin = Horde::getTempFile('WebcppIn'); - $tmpout = Horde::getTempFile('WebcppOut'); - - /* Write the contents of our buffer to the temporary input file. */ - $contents = $this->mime_part->getContents(); - $fh = fopen($tmpin, 'wb'); - fwrite($fh, $contents, strlen($contents)); - fclose($fh); - - /* Get the extension for the mime type. */ - include_once 'Horde/MIME/Magic.php'; - $ext = MIME_Magic::MIMEToExt($this->mime_part->getType()); - - /* Execute Web C Plus Plus. Specifying the in and out files didn't - work for me but pipes did. */ - exec($GLOBALS['mime_drivers']['horde']['webcpp']['location'] . " --pipe --pipe -x=$ext -l -a -t < $tmpin > $tmpout"); - $results = file_get_contents($tmpout); - - /* If we are not displaying inline, all the formatting is already - * done for us. */ - if (!$this->viewInline()) { - /* The first 2 lines are the Content-Type line and a blank line - * so we should remove them before outputting. */ - return preg_replace("/.*\n.*\n/", '', $results, 1); - } - - /* Extract the style sheet, removing any global body formatting - * if we're displaying inline. */ - $res = preg_split(';()|(
' . $body . '
'; - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - protected function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/wordperfect.php b/framework/mime_tmp/Horde/Mime/Viewer/wordperfect.php deleted file mode 100644 index c65184cc3..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/wordperfect.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_wordperfect extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current data using wpd2html. - * - * @param array $params Any parameters the viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - /* Check to make sure the program actually exists. */ - if (!file_exists($GLOBALS['mime_drivers']['horde']['wordperfect']['location'])) { - return '
' . sprintf(_("The program used to view this data type (%s) was not found on the system."), $GLOBALS['mime_drivers']['horde']['wordperfect']['location']) . '
'; - } - - $tmp_wpd = Horde::getTempFile('wpd'); - $tmp_output = Horde::getTempFile('wpd'); - $args = " $tmp_wpd > $tmp_output"; - - $fh = fopen($tmp_wpd, 'w'); - fwrite($fh, $this->mime_part->getContents()); - fclose($fh); - - exec($GLOBALS['mime_drivers']['horde']['wordperfect']['location'] . $args); - - if (!file_exists($tmp_output)) { - return _("Unable to translate this WordPerfect document"); - } - - return file_get_contents($tmp_output); - } - - /** - * Return the MIME content type of the rendered content. - * - * @return string The content type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/Viewer/zip.php b/framework/mime_tmp/Horde/Mime/Viewer/zip.php deleted file mode 100644 index ebdca0b94..000000000 --- a/framework/mime_tmp/Horde/Mime/Viewer/zip.php +++ /dev/null @@ -1,135 +0,0 @@ - - * @author Michael Cochrane - * @package Horde_MIME_Viewer - */ -class Horde_MIME_Viewer_zip extends Horde_MIME_Viewer_Driver -{ - /** - * Render out the current zip contents. - * - * @param array $params Any parameters the Viewer may need. - * - * @return string The rendered contents. - */ - public function render($params = array()) - { - return $this->_render($this->mime_part->getContents()); - } - - /** - * Output the file list. - * - * @param string $contents The contents of the zip archive. - * @param mixed $callback The callback function to use on the zipfile - * information. - * - * @return string The file list. - */ - protected function _render($contents, $callback = null) - { - require_once 'Horde/Compress.php'; - - $zip = &Horde_Compress::factory('zip'); - - /* Make sure this is a valid zip file. */ - if ($zip->checkZipData($contents) === false) { - return '
' . _("This does not appear to be a valid zip file.")
-                . '
'; - } - - $zipInfo = $zip->decompress( - $contents, - array('action' => HORDE_COMPRESS_ZIP_LIST)); - if (is_a($zipInfo, 'PEAR_Error')) { - return $zipInfo->getMessage(); - } - $fileCount = count($zipInfo); - - /* Determine maximum file name length. */ - $maxlen = 0; - foreach ($zipInfo as $val) { - $maxlen = max($maxlen, strlen($val['name'])); - } - - require_once 'Horde/Text.php'; - - $text = '' - . htmlspecialchars(sprintf(_("Contents of \"%s\""), - $this->mime_part->getName())) - . ':' . "\n" - . '
' - . Text::htmlAllSpaces( - _("Archive Name") . ': ' . $this->mime_part->getName() . "\n" - . _("Archive File Size") . ': ' . strlen($contents) - . ' bytes' . "\n" - . sprintf( - ngettext("File Count: %d file", "File Count: %d files", - $fileCount), - $fileCount) - . "\n\n" - . String::pad(_("File Name"), $maxlen, ' ', STR_PAD_RIGHT) - . String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) - . String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) - . String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) - . String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) - . String::pad(_("CRC"), 10, ' ', STR_PAD_LEFT) - . String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT) - . "\n") - . str_repeat('-', 69 + $maxlen) . "\n"; - - foreach ($zipInfo as $key => $val) { - $ratio = (empty($val['size'])) - ? 0 - : 100 * ($val['csize'] / $val['size']); - - $val['name'] = String::pad($val['name'], - $maxlen, ' ', STR_PAD_RIGHT); - $val['attr'] = String::pad($val['attr'], - 10, ' ', STR_PAD_LEFT); - $val['size'] = String::pad($val['size'], - 10, ' ', STR_PAD_LEFT); - $val['date'] = String::pad(strftime("%d-%b-%Y %H:%M", - $val['date']), - 19, ' ', STR_PAD_LEFT); - $val['method'] = String::pad($val['method'], - 10, ' ', STR_PAD_LEFT); - $val['crc'] = String::pad($val['crc'], - 10, ' ', STR_PAD_LEFT); - $val['ratio'] = String::pad(sprintf("%1.1f%%", $ratio), - 10, ' ', STR_PAD_LEFT); - - $val = array_map(array('Text', 'htmlAllSpaces'), $val); - if (!is_null($callback)) { - $val = call_user_func($callback, $key, $val); - } - - $text .= $val['name'] . $val['attr'] . $val['size'] . $val['date'] - . $val['method'] . $val['crc'] . $val['ratio'] . "\n"; - } - - $text .= str_repeat('-', 69 + $maxlen) . "\n" - . '
'; - - return nl2br($text); - } - - /** - * Return the content-type - * - * @return string The content-type of the output. - */ - public function getType() - { - return 'text/html; charset=' . NLS::getCharset(); - } -} diff --git a/framework/mime_tmp/Horde/Mime/mime.magic.php b/framework/mime_tmp/Horde/Mime/mime.magic.php deleted file mode 100644 index d63efbea0..000000000 Binary files a/framework/mime_tmp/Horde/Mime/mime.magic.php and /dev/null differ diff --git a/framework/mime_tmp/Horde/Mime/mime.mapping.php b/framework/mime_tmp/Horde/Mime/mime.mapping.php deleted file mode 100644 index 82aebacea..000000000 --- a/framework/mime_tmp/Horde/Mime/mime.mapping.php +++ /dev/null @@ -1,894 +0,0 @@ -' where is the unknown file extension. - * - * @package Horde_MIME - * - * $Horde: framework/MIME/MIME/mime.mapping.php,v 1.18 2008/11/06 04:33:47 chuck Exp $ - * - * Generated: 11/05/08 23:30:23 by chuck on technest.org - */ -$mime_extension_map = array( - '__MAXPERIOD__' => '1', - 'ez' => 'application/andrew-inset', - 'atom' => 'application/atom+xml', - 'atomcat' => 'application/atomcat+xml', - 'atomsvc' => 'application/atomsvc+xml', - 'ccxml' => 'application/ccxml+xml', - 'davmount' => 'application/davmount+xml', - 'ecma' => 'application/ecmascript', - 'pfr' => 'application/font-tdpfr', - 'stk' => 'application/hyperstudio', - 'js' => 'application/x-javascript', - 'json' => 'application/json', - 'hqx' => 'application/mac-binhex40', - 'cpt' => 'application/mac-compactpro', - 'mrc' => 'application/marc', - 'ma' => 'application/mathematica', - 'nb' => 'application/mathematica', - 'mb' => 'application/mathematica', - 'mathml' => 'application/mathml+xml', - 'mbox' => 'application/mbox', - 'mscml' => 'application/mediaservercontrol+xml', - 'mp4s' => 'application/mp4', - 'doc' => 'application/msword', - 'dot' => 'application/msword', - 'mxf' => 'application/mxf', - 'bin' => 'application/octet-stream', - 'dms' => 'application/octet-stream', - 'lha' => 'application/x-lha', - 'lzh' => 'application/x-lha', - 'class' => 'application/x-java', - 'so' => 'application/x-sharedlib', - 'iso' => 'application/x-cd-image', - 'dmg' => 'application/octet-stream', - 'dist' => 'application/octet-stream', - 'distz' => 'application/octet-stream', - 'pkg' => 'application/octet-stream', - 'bpk' => 'application/octet-stream', - 'dump' => 'application/octet-stream', - 'elc' => 'application/octet-stream', - 'oda' => 'application/oda', - 'ogg' => 'application/ogg', - 'pdf' => 'application/pdf', - 'pgp' => 'application/pgp', - 'asc' => 'text/plain', - 'sig' => 'application/pgp-signature', - 'prf' => 'application/pics-rules', - 'p10' => 'application/pkcs10', - 'p7m' => 'application/pkcs7-mime', - 'p7c' => 'application/pkcs7-mime', - 'p7s' => 'application/pkcs7-signature', - 'cer' => 'application/x-x509-ca-cert', - 'crl' => 'application/pkix-crl', - 'pkipath' => 'application/pkix-pkipath', - 'pki' => 'application/pkixcmp', - 'pls' => 'audio/x-scpls', - 'ai' => 'application/illustrator', - 'eps' => 'image/x-eps', - 'ps' => 'application/postscript', - 'cww' => 'application/prs.cww', - 'rdf' => 'text/rdf', - 'rif' => 'application/reginfo+xml', - 'rnc' => 'application/relax-ng-compact-syntax', - 'rl' => 'application/resource-lists+xml', - 'rs' => 'application/rls-services+xml', - 'rsd' => 'application/rsd+xml', - 'rss' => 'text/rss', - 'rtf' => 'application/rtf', - 'sbml' => 'application/sbml+xml', - 'scq' => 'application/scvp-cv-request', - 'scs' => 'application/scvp-cv-response', - 'spq' => 'application/scvp-vp-request', - 'spp' => 'application/scvp-vp-response', - 'sdp' => 'application/vnd.stardivision.impress', - 'setpay' => 'application/set-payment-initiation', - 'setreg' => 'application/set-registration-initiation', - 'shf' => 'application/shf+xml', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'rq' => 'application/sparql-query', - 'srx' => 'application/sparql-results+xml', - 'gram' => 'application/srgs', - 'grxml' => 'application/srgs+xml', - 'ssml' => 'application/ssml+xml', - 'plb' => 'application/vnd.3gpp.pic-bw-large', - 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'pvb' => 'application/vnd.3gpp.pic-bw-var', - 'tcap' => 'application/vnd.3gpp2.tcap', - 'pwn' => 'application/vnd.3m.post-it-notes', - 'aso' => 'application/vnd.accpac.simply.aso', - 'imp' => 'application/vnd.accpac.simply.imp', - 'acu' => 'application/vnd.acucobol', - 'atc' => 'application/vnd.acucorp', - 'acutc' => 'application/vnd.acucorp', - 'xdp' => 'application/vnd.adobe.xdp+xml', - 'xfdf' => 'application/vnd.adobe.xfdf', - 'ami' => 'application/vnd.amiga.ami', - 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', - 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', - 'atx' => 'application/vnd.antix.game-component', - 'mpkg' => 'application/vnd.apple.installer+xml', - 'aep' => 'application/vnd.audiograph', - 'mpm' => 'application/vnd.blueice.multipass', - 'bmi' => 'application/vnd.bmi', - 'rep' => 'application/vnd.businessobjects', - 'cdxml' => 'application/vnd.chemdraw+xml', - 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', - 'cdy' => 'application/vnd.cinderella', - 'cla' => 'application/vnd.claymore', - 'c4g' => 'application/vnd.clonk.c4group', - 'c4d' => 'application/vnd.clonk.c4group', - 'c4f' => 'application/vnd.clonk.c4group', - 'c4p' => 'application/vnd.clonk.c4group', - 'c4u' => 'application/vnd.clonk.c4group', - 'csp' => 'application/vnd.commonspace', - 'cst' => 'application/vnd.commonspace', - 'cdbcmsg' => 'application/vnd.contact.cmsg', - 'cmc' => 'application/vnd.cosmocaller', - 'clkx' => 'application/vnd.crick.clicker', - 'clkk' => 'application/vnd.crick.clicker.keyboard', - 'clkp' => 'application/vnd.crick.clicker.palette', - 'clkt' => 'application/vnd.crick.clicker.template', - 'clkw' => 'application/vnd.crick.clicker.wordbank', - 'wbs' => 'application/vnd.criticaltools.wbs+xml', - 'pml' => 'application/vnd.ctc-posml', - 'ppd' => 'application/vnd.cups-ppd', - 'curl' => 'application/vnd.curl', - 'rdz' => 'application/vnd.data-vision.rdz', - 'fe_launch' => 'application/vnd.denovo.fcselayout-link', - 'dna' => 'application/vnd.dna', - 'mlp' => 'application/vnd.dolby.mlp', - 'dpg' => 'application/vnd.dpgraph', - 'dfac' => 'application/vnd.dreamfactory', - 'mag' => 'application/vnd.ecowin.chart', - 'nml' => 'application/vnd.enliven', - 'esf' => 'application/vnd.epson.esf', - 'msf' => 'application/vnd.epson.msf', - 'qam' => 'application/vnd.epson.quickanime', - 'slt' => 'application/vnd.epson.salt', - 'ssf' => 'application/vnd.epson.ssf', - 'es3' => 'application/vnd.eszigno3+xml', - 'et3' => 'application/vnd.eszigno3+xml', - 'ez2' => 'application/vnd.ezpix-album', - 'ez3' => 'application/vnd.ezpix-package', - 'fdf' => 'application/vnd.fdf', - 'gph' => 'application/vnd.flographit', - 'ftc' => 'application/vnd.fluxtime.clip', - 'fm' => 'application/vnd.framemaker', - 'frame' => 'application/vnd.framemaker', - 'maker' => 'application/vnd.framemaker', - 'fnc' => 'application/vnd.frogans.fnc', - 'ltf' => 'application/vnd.frogans.ltf', - 'fsc' => 'application/vnd.fsc.weblaunch', - 'oas' => 'application/vnd.fujitsu.oasys', - 'oa2' => 'application/vnd.fujitsu.oasys2', - 'oa3' => 'application/vnd.fujitsu.oasys3', - 'fg5' => 'application/vnd.fujitsu.oasysgp', - 'bh2' => 'application/vnd.fujitsu.oasysprs', - 'ddd' => 'application/vnd.fujixerox.ddd', - 'xdw' => 'application/vnd.fujixerox.docuworks', - 'xbd' => 'application/vnd.fujixerox.docuworks.binder', - 'fzs' => 'application/vnd.fuzzysheet', - 'txd' => 'application/vnd.genomatix.tuxedo', - 'kml' => 'application/vnd.google-earth.kml+xml', - 'kmz' => 'application/vnd.google-earth.kmz', - 'gqf' => 'application/vnd.grafeq', - 'gqs' => 'application/vnd.grafeq', - 'gac' => 'application/vnd.groove-account', - 'ghf' => 'application/vnd.groove-help', - 'gim' => 'application/vnd.groove-identity-message', - 'grv' => 'application/vnd.groove-injector', - 'gtm' => 'application/vnd.groove-tool-message', - 'tpl' => 'application/vnd.groove-tool-template', - 'vcg' => 'application/vnd.groove-vcard', - 'zmm' => 'application/vnd.handheld-entertainment+xml', - 'hbci' => 'application/vnd.hbci', - 'les' => 'application/vnd.hhe.lesson-player', - 'hpgl' => 'application/vnd.hp-hpgl', - 'hpid' => 'application/vnd.hp-hpid', - 'hps' => 'application/vnd.hp-hps', - 'jlt' => 'application/vnd.hp-jlyt', - 'pcl' => 'application/vnd.hp-pcl', - 'pclxl' => 'application/vnd.hp-pclxl', - 'x3d' => 'application/vnd.hzn-3d-crossword', - 'mpy' => 'application/vnd.ibm.minipay', - 'afp' => 'application/vnd.ibm.modcap', - 'listafp' => 'application/vnd.ibm.modcap', - 'list3820' => 'application/vnd.ibm.modcap', - 'irm' => 'application/vnd.ibm.rights-management', - 'sc' => 'application/vnd.ibm.secure-container', - 'igl' => 'application/vnd.igloader', - 'ivp' => 'application/vnd.immervision-ivp', - 'ivu' => 'application/vnd.immervision-ivu', - 'xpw' => 'application/vnd.intercon.formnet', - 'xpx' => 'application/vnd.intercon.formnet', - 'qbo' => 'application/vnd.intu.qbo', - 'qfx' => 'application/vnd.intu.qfx', - 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', - 'irp' => 'application/vnd.irepository.package+xml', - 'xpr' => 'application/vnd.is-xpr', - 'jam' => 'application/vnd.jam', - 'rms' => 'application/vnd.jcp.javame.midlet-rms', - 'jisp' => 'application/vnd.jisp', - 'joda' => 'application/vnd.joost.joda-archive', - 'ktz' => 'application/vnd.kahootz', - 'ktr' => 'application/vnd.kahootz', - 'karbon' => 'application/x-karbon', - 'chrt' => 'application/x-kchart', - 'kfo' => 'application/x-kformula', - 'flw' => 'application/x-kivio', - 'kon' => 'application/x-kontour', - 'kpr' => 'application/x-kpresenter', - 'kpt' => 'application/x-kpresenter', - 'ksp' => 'application/x-kspread', - 'kwd' => 'application/x-kword', - 'kwt' => 'application/x-kword', - 'htke' => 'application/vnd.kenameaapp', - 'kia' => 'application/vnd.kidspiration', - 'kne' => 'application/vnd.kinar', - 'knp' => 'application/vnd.kinar', - 'skp' => 'application/vnd.koan', - 'skd' => 'application/vnd.koan', - 'skt' => 'application/vnd.koan', - 'skm' => 'application/vnd.koan', - 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', - 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', - '123' => 'application/vnd.lotus-1-2-3', - 'apr' => 'application/vnd.lotus-approach', - 'pre' => 'application/vnd.lotus-freelance', - 'nsf' => 'application/vnd.lotus-notes', - 'org' => 'application/vnd.lotus-organizer', - 'scm' => 'text/x-scheme', - 'lwp' => 'application/vnd.lotus-wordpro', - 'portpkg' => 'application/vnd.macports.portpkg', - 'mcd' => 'application/vnd.mcd', - 'mc1' => 'application/vnd.medcalcdata', - 'cdkey' => 'application/vnd.mediastation.cdkey', - 'mwf' => 'application/vnd.mfer', - 'mfm' => 'application/vnd.mfmp', - 'flo' => 'application/vnd.micrografx.flo', - 'igx' => 'application/vnd.micrografx.igx', - 'mif' => 'application/x-mif', - 'daf' => 'application/vnd.mobius.daf', - 'dis' => 'application/vnd.mobius.dis', - 'mbk' => 'application/vnd.mobius.mbk', - 'mqy' => 'application/vnd.mobius.mqy', - 'msl' => 'application/vnd.mobius.msl', - 'plc' => 'application/vnd.mobius.plc', - 'txf' => 'application/vnd.mobius.txf', - 'mpn' => 'application/vnd.mophun.application', - 'mpc' => 'application/vnd.mophun.certificate', - 'xul' => 'application/vnd.mozilla.xul+xml', - 'cil' => 'application/vnd.ms-artgalry', - 'asf' => 'video/x-ms-asf', - 'cab' => 'application/vnd.ms-cab-compressed', - 'xls' => 'application/vnd.ms-excel', - 'xlm' => 'application/vnd.ms-excel', - 'xla' => 'application/vnd.ms-excel', - 'xlc' => 'application/vnd.ms-excel', - 'xlt' => 'application/vnd.ms-excel', - 'xlw' => 'application/vnd.ms-excel', - 'eot' => 'application/vnd.ms-fontobject', - 'chm' => 'application/x-chm', - 'ims' => 'application/vnd.ms-ims', - 'lrm' => 'application/vnd.ms-lrm', - 'ppt' => 'application/vnd.ms-powerpoint', - 'pps' => 'application/vnd.ms-powerpoint', - 'pot' => 'text/x-gettext-translation-template', - 'mpp' => 'application/vnd.ms-project', - 'mpt' => 'application/vnd.ms-project', - 'wps' => 'application/vnd.ms-works', - 'wks' => 'application/vnd.lotus-1-2-3', - 'wcm' => 'application/vnd.ms-works', - 'wdb' => 'application/vnd.ms-works', - 'wpl' => 'application/vnd.ms-wpl', - 'xps' => 'application/vnd.ms-xpsdocument', - 'mseq' => 'application/vnd.mseq', - 'mus' => 'application/vnd.musician', - 'msty' => 'application/vnd.muvee.style', - 'nlu' => 'application/vnd.neurolanguage.nlu', - 'nnd' => 'application/vnd.noblenet-directory', - 'nns' => 'application/vnd.noblenet-sealer', - 'nnw' => 'application/vnd.noblenet-web', - 'ngdat' => 'application/vnd.nokia.n-gage.data', - 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', - 'rpst' => 'application/vnd.nokia.radio-preset', - 'rpss' => 'application/vnd.nokia.radio-presets', - 'edm' => 'application/vnd.novadigm.edm', - 'edx' => 'application/vnd.novadigm.edx', - 'ext' => 'application/vnd.novadigm.ext', - 'odc' => 'application/vnd.oasis.opendocument.chart', - 'otc' => 'application/vnd.oasis.opendocument.chart-template', - 'odf' => 'application/vnd.oasis.opendocument.formula', - 'otf' => 'application/vnd.oasis.opendocument.formula-template', - 'odg' => 'application/vnd.oasis.opendocument.graphics', - 'otg' => 'application/vnd.oasis.opendocument.graphics-template', - 'odi' => 'application/vnd.oasis.opendocument.image', - 'oti' => 'application/vnd.oasis.opendocument.image-template', - 'odp' => 'application/vnd.oasis.opendocument.presentation', - 'otp' => 'application/vnd.oasis.opendocument.presentation-template', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', - 'odt' => 'application/vnd.oasis.opendocument.text', - 'otm' => 'application/vnd.oasis.opendocument.text-master', - 'ott' => 'application/vnd.oasis.opendocument.text-template', - 'oth' => 'application/vnd.oasis.opendocument.text-web', - 'xo' => 'application/vnd.olpc-sugar', - 'dd2' => 'application/vnd.oma.dd2+xml', - 'oxt' => 'application/vnd.openofficeorg.extension', - 'dp' => 'application/vnd.osgi.dp', - 'prc' => 'application/vnd.palm', - 'pdb' => 'application/vnd.palm', - 'pqa' => 'application/vnd.palm', - 'oprc' => 'application/vnd.palm', - 'str' => 'application/vnd.pg.format', - 'ei6' => 'application/vnd.pg.osasli', - 'efif' => 'application/vnd.picsel', - 'plf' => 'application/vnd.pocketlearn', - 'pbd' => 'application/vnd.powerbuilder6', - 'box' => 'application/vnd.previewsystems.box', - 'mgz' => 'application/vnd.proteus.magazine', - 'qps' => 'application/vnd.publishare-delta-tree', - 'ptid' => 'application/vnd.pvi.ptid1', - 'qxd' => 'application/vnd.quark.quarkxpress', - 'qxt' => 'application/vnd.quark.quarkxpress', - 'qwd' => 'application/vnd.quark.quarkxpress', - 'qwt' => 'application/vnd.quark.quarkxpress', - 'qxl' => 'application/vnd.quark.quarkxpress', - 'qxb' => 'application/vnd.quark.quarkxpress', - 'mxl' => 'application/vnd.recordare.musicxml', - 'rm' => 'audio/x-pn-realaudio', - 'see' => 'application/vnd.seemail', - 'sema' => 'application/vnd.sema', - 'semd' => 'application/vnd.semd', - 'semf' => 'application/vnd.semf', - 'ifm' => 'application/vnd.shana.informed.formdata', - 'itp' => 'application/vnd.shana.informed.formtemplate', - 'iif' => 'application/vnd.shana.informed.interchange', - 'ipk' => 'application/vnd.shana.informed.package', - 'twd' => 'application/vnd.simtech-mindmapper', - 'twds' => 'application/vnd.simtech-mindmapper', - 'mmf' => 'application/vnd.smaf', - 'sdkm' => 'application/vnd.solent.sdkm+xml', - 'sdkd' => 'application/vnd.solent.sdkm+xml', - 'dxp' => 'application/vnd.spotfire.dxp', - 'sfs' => 'application/vnd.spotfire.sfs', - 'sus' => 'application/vnd.sus-calendar', - 'susp' => 'application/vnd.sus-calendar', - 'svd' => 'application/vnd.svd', - 'xsm' => 'application/vnd.syncml+xml', - 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'xdm' => 'application/vnd.syncml.dm+xml', - 'tao' => 'application/vnd.tao.intent-module-archive', - 'tmo' => 'application/vnd.tmobile-livetv', - 'tpt' => 'application/vnd.trid.tpt', - 'mxs' => 'application/vnd.triscape.mxs', - 'tra' => 'application/vnd.trueapp', - 'ufd' => 'application/vnd.ufdl', - 'ufdl' => 'application/vnd.ufdl', - 'utz' => 'application/vnd.uiq.theme', - 'umj' => 'application/vnd.umajin', - 'unityweb' => 'application/vnd.unity', - 'uoml' => 'application/vnd.uoml+xml', - 'vcx' => 'application/vnd.vcx', - 'vsd' => 'application/vnd.visio', - 'vst' => 'application/vnd.visio', - 'vss' => 'application/vnd.visio', - 'vsw' => 'application/vnd.visio', - 'vis' => 'application/vnd.visionary', - 'vsf' => 'application/vnd.vsf', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'wmlsc' => 'application/vnd.wap.wmlscriptc', - 'wtb' => 'application/vnd.webturbo', - 'wpd' => 'application/vnd.wordperfect', - 'wqd' => 'application/vnd.wqd', - 'stf' => 'application/vnd.wt.stf', - 'xar' => 'application/vnd.xara', - 'xfdl' => 'application/vnd.xfdl', - 'hvd' => 'application/vnd.yamaha.hv-dic', - 'hvs' => 'application/vnd.yamaha.hv-script', - 'hvp' => 'application/vnd.yamaha.hv-voice', - 'saf' => 'application/vnd.yamaha.smaf-audio', - 'spf' => 'application/vnd.yamaha.smaf-phrase', - 'cmp' => 'application/vnd.yellowriver-custom-menu', - 'zaz' => 'application/vnd.zzazz.deck+xml', - 'vxml' => 'application/voicexml+xml', - 'hlp' => 'application/winhlp', - 'wsdl' => 'application/wsdl+xml', - 'wspolicy' => 'application/wspolicy+xml', - 'ace' => 'application/x-ace-compressed', - 'bcpio' => 'application/x-bcpio', - 'torrent' => 'application/x-bittorrent', - 'bz' => 'application/x-bzip', - 'bz2' => 'application/x-bzip', - 'boz' => 'application/x-bzip2', - 'vcd' => 'application/x-cdlink', - 'chat' => 'application/x-chat', - 'pgn' => 'application/x-chess-pgn', - 'cpio' => 'application/x-cpio', - 'csh' => 'application/x-csh', - 'dcr' => 'application/x-director', - 'dir' => 'application/x-director', - 'dxr' => 'application/x-director', - 'fgd' => 'application/x-director', - 'dvi' => 'application/x-dvi', - 'spl' => 'application/x-futuresplash', - 'gtar' => 'application/x-gtar', - 'hdf' => 'application/x-hdf', - 'latex' => 'application/x-latex', - 'wmd' => 'application/x-ms-wmd', - 'wmz' => 'application/x-ms-wmz', - 'mdb' => 'application/x-msaccess', - 'obd' => 'application/x-msbinder', - 'crd' => 'application/x-mscardfile', - 'clp' => 'application/x-msclip', - 'exe' => 'application/x-ms-dos-executable', - 'dll' => 'application/x-msdownload', - 'com' => 'application/x-msdownload', - 'bat' => 'application/x-msdownload', - 'msi' => 'application/x-msdownload', - 'mvb' => 'application/x-msmediaview', - 'm13' => 'application/x-msmediaview', - 'm14' => 'application/x-msmediaview', - 'wmf' => 'image/x-wmf', - 'mny' => 'application/x-msmoney', - 'pub' => 'application/x-mspublisher', - 'scd' => 'application/x-msschedule', - 'trm' => 'application/x-msterminal', - 'wri' => 'application/x-mswrite', - 'nc' => 'application/x-netcdf', - 'cdf' => 'application/x-netcdf', - 'p12' => 'application/x-pkcs12', - 'pfx' => 'application/x-pkcs12', - 'p7b' => 'application/x-pkcs7-certificates', - 'spc' => 'application/x-pkcs7-certificates', - 'p7r' => 'application/x-pkcs7-certreqresp', - 'rar' => 'application/x-rar', - 'sh' => 'application/x-shellscript', - 'shar' => 'application/x-shar', - 'swf' => 'application/x-shockwave-flash', - 'sit' => 'application/stuffit', - 'sitx' => 'application/x-stuffitx', - 'sv4cpio' => 'application/x-sv4cpio', - 'sv4crc' => 'application/x-sv4crc', - 'tar' => 'application/x-tar', - 'tcl' => 'text/x-tcl', - 'tex' => 'text/x-tex', - 'texinfo' => 'text/x-texinfo', - 'texi' => 'text/x-texinfo', - 'ustar' => 'application/x-ustar', - 'src' => 'application/x-wais-source', - 'der' => 'application/x-x509-ca-cert', - 'crt' => 'application/x-x509-ca-cert', - 'xenc' => 'application/xenc+xml', - 'xhtml' => 'application/xhtml+xml', - 'xht' => 'application/xhtml+xml', - 'xml' => 'text/xml', - 'xsl' => 'text/x-xslt', - 'dtd' => 'text/x-dtd', - 'xop' => 'application/xop+xml', - 'xslt' => 'text/x-xslt', - 'xspf' => 'application/xspf+xml', - 'mxml' => 'application/xv+xml', - 'xhvml' => 'application/xv+xml', - 'xvml' => 'application/xv+xml', - 'xvm' => 'application/xv+xml', - 'zip' => 'application/zip', - 'au' => 'audio/basic', - 'snd' => 'audio/basic', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'kar' => 'audio/midi', - 'rmi' => 'audio/midi', - 'mp4a' => 'audio/mp4', - 'mpga' => 'audio/mpeg', - 'mp2' => 'video/mpeg', - 'mp2a' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'm2a' => 'audio/mpeg', - 'm3a' => 'audio/mpeg', - 'eol' => 'audio/vnd.digital-winds', - 'lvp' => 'audio/vnd.lucent.voice', - 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', - 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', - 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', - 'wav' => 'audio/x-wav', - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'm3u' => 'audio/x-mpegurl', - 'wax' => 'audio/x-ms-wax', - 'wma' => 'audio/x-ms-wma', - 'ram' => 'audio/x-pn-realaudio', - 'ra' => 'audio/x-pn-realaudio', - 'rmp' => 'audio/x-pn-realaudio-plugin', - 'cdx' => 'chemical/x-cdx', - 'cif' => 'chemical/x-cif', - 'cmdf' => 'chemical/x-cmdf', - 'cml' => 'chemical/x-cml', - 'csml' => 'chemical/x-csml', - 'xyz' => 'chemical/x-xyz', - 'bmp' => 'image/bmp', - 'cgm' => 'image/cgm', - 'g3' => 'image/fax-g3', - 'gif' => 'image/gif', - 'ief' => 'image/ief', - 'jpg' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpe' => 'image/jpeg', - 'png' => 'image/png', - 'btif' => 'image/prs.btif', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - 'tiff' => 'image/tiff', - 'tif' => 'image/tiff', - 'psd' => 'image/x-psd', - 'djvu' => 'image/vnd.djvu', - 'djv' => 'image/vnd.djvu', - 'dwg' => 'image/vnd.dwg', - 'dxf' => 'image/vnd.dxf', - 'fbs' => 'image/vnd.fastbidsheet', - 'fpx' => 'image/vnd.fpx', - 'fst' => 'image/vnd.fst', - 'mmr' => 'image/vnd.fujixerox.edmics-mmr', - 'rlc' => 'image/vnd.fujixerox.edmics-rlc', - 'mdi' => 'image/vnd.ms-modi', - 'npx' => 'image/vnd.net-fpx', - 'wbmp' => 'image/vnd.wap.wbmp', - 'xif' => 'image/vnd.xiff', - 'ras' => 'image/x-cmu-raster', - 'cmx' => 'image/x-cmx', - 'ico' => 'image/x-ico', - 'pcx' => 'image/x-pcx', - 'pic' => 'image/x-pict', - 'pct' => 'image/x-pict', - 'pnm' => 'image/x-portable-anymap', - 'pbm' => 'image/x-portable-bitmap', - 'pgm' => 'image/x-portable-graymap', - 'ppm' => 'image/x-portable-pixmap', - 'rgb' => 'image/x-rgb', - 'xbm' => 'image/x-xbitmap', - 'xpm' => 'image/x-xpixmap', - 'xwd' => 'image/x-xwindowdump', - 'eml' => 'message/rfc822', - 'mime' => 'message/rfc822', - 'igs' => 'model/iges', - 'iges' => 'model/iges', - 'msh' => 'model/mesh', - 'mesh' => 'model/mesh', - 'silo' => 'model/mesh', - 'dwf' => 'model/vnd.dwf', - 'gdl' => 'model/vnd.gdl', - 'gtw' => 'model/vnd.gtw', - 'mts' => 'model/vnd.mts', - 'vtu' => 'model/vnd.vtu', - 'wrl' => 'model/vrml', - 'vrml' => 'model/vrml', - 'ics' => 'text/calendar', - 'ifb' => 'text/calendar', - 'css' => 'text/css', - 'csv' => 'text/x-comma-separated-values', - 'html' => 'text/html', - 'htm' => 'text/html', - 'txt' => 'text/plain', - 'text' => 'text/plain', - 'conf' => 'text/plain', - 'def' => 'text/plain', - 'list' => 'text/plain', - 'log' => 'text/x-log', - 'in' => 'text/plain', - 'dsc' => 'text/prs.lines.tag', - 'rtx' => 'text/richtext', - 'sgml' => 'text/sgml', - 'sgm' => 'text/sgml', - 'tsv' => 'text/tab-separated-values', - 't' => 'application/x-troff', - 'tr' => 'application/x-troff', - 'roff' => 'application/x-troff', - 'man' => 'application/x-troff-man', - 'me' => 'text/x-troff-me', - 'ms' => 'text/x-troff-ms', - 'uri' => 'text/x-uri', - 'uris' => 'text/uri-list', - 'urls' => 'text/uri-list', - 'fly' => 'text/vnd.fly', - 'flx' => 'text/vnd.fmi.flexstor', - '3dml' => 'text/vnd.in3d.3dml', - 'spot' => 'text/vnd.in3d.spot', - 'jad' => 'text/vnd.sun.j2me.app-descriptor', - 'wml' => 'text/vnd.wap.wml', - 'wmls' => 'text/vnd.wap.wmlscript', - 's' => 'text/x-asm', - 'asm' => 'text/x-asm', - 'c' => 'text/x-csrc', - 'cc' => 'text/x-c++src', - 'cxx' => 'text/x-c++src', - 'cpp' => 'text/x-c++src', - 'h' => 'text/x-chdr', - 'hh' => 'text/x-c++hdr', - 'dic' => 'text/x-c', - 'f' => 'text/x-fortran', - 'for' => 'text/x-fortran', - 'f77' => 'text/x-fortran', - 'f90' => 'text/x-fortran', - 'p' => 'text/x-pascal', - 'pas' => 'text/x-pascal', - 'java' => 'text/x-java', - 'etx' => 'text/x-setext', - 'uu' => 'text/x-uuencode', - 'vcs' => 'text/calendar', - 'vcf' => 'text/directory', - '3gp' => 'video/3gpp', - '3g2' => 'video/3gpp2', - 'h261' => 'video/h261', - 'h263' => 'video/h263', - 'h264' => 'video/h264', - 'jpgv' => 'video/jpeg', - 'jpm' => 'video/jpm', - 'jpgm' => 'video/jpm', - 'mj2' => 'video/mj2', - 'mjp2' => 'video/mj2', - 'mp4' => 'video/mp4', - 'mp4v' => 'video/mp4', - 'mpg4' => 'video/mp4', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpe' => 'video/mpeg', - 'm1v' => 'video/mpeg', - 'm2v' => 'video/mpeg', - 'qt' => 'video/quicktime', - 'mov' => 'video/quicktime', - 'fvt' => 'video/vnd.fvt', - 'mxu' => 'video/vnd.mpegurl', - 'm4u' => 'video/vnd.mpegurl', - 'viv' => 'video/vnd.vivo', - 'fli' => 'video/x-flic', - 'asx' => 'video/x-ms-asf', - 'wm' => 'video/x-ms-wm', - 'wmv' => 'video/x-ms-wmv', - 'wmx' => 'video/x-ms-wmx', - 'wvx' => 'video/x-ms-wvx', - 'avi' => 'video/x-msvideo', - 'movie' => 'video/x-sgi-movie', - 'ice' => 'x-conference/x-cooltalk', - 'odb' => 'application/vnd.oasis.opendocument.database', - 'oot' => 'application/vnd.oasis.opendocument.text', - 'odm' => 'application/vnd.oasis.opendocument.text-master', - 'sxc' => 'application/vnd.sun.xml.calc', - 'stc' => 'application/vnd.sun.xml.calc.template', - 'sxd' => 'application/vnd.sun.xml.draw', - 'std' => 'application/vnd.sun.xml.draw.template', - 'sxg' => 'application/vnd.sun.xml.writer.global', - 'sxm' => 'application/vnd.sun.xml.math', - 'sxi' => 'application/vnd.sun.xml.impress', - 'sti' => 'application/vnd.sun.xml.impress.template', - 'sxw' => 'application/vnd.sun.xml.writer', - 'stw' => 'application/vnd.sun.xml.writer.template', - 'Z' => 'application/x-compress', - 'gz' => 'application/x-gzip', - 'tgz' => 'application/x-compressed-tar', - 'php' => 'application/x-php', - 'php3' => 'application/x-php', - 'pl' => 'application/x-perl', - 'pm' => 'application/x-perl', - 'gsm' => 'audio/x-gsm', - 'vfb' => 'text/calendar', - 'diff' => 'text/x-patch', - 'patch' => 'text/x-patch', - 'shtml' => 'text/html', - 'po' => 'text/x-gettext-translation', - 'sgl' => 'application/vnd.stardivision.writer', - 'wk4' => 'application/vnd.lotus-1-2-3', - 'pict2' => 'image/x-pict', - 'lhz' => 'application/x-lhz', - 'tar.bz2' => 'application/x-bzip-compressed-tar', - 'rle' => 'image/rle', - 'pcf.Z' => 'application/x-font-type1', - 'm15' => 'audio/x-mod', - 'flac' => 'audio/x-flac', - 'dc' => 'application/x-dc-rom', - 'm' => 'text/x-objcsrc', - 'o' => 'application/x-object', - 'fits' => 'image/x-fits', - 'pfa' => 'application/x-font-type1', - 'jnlp' => 'application/x-java-jnlp-file', - 'pfb' => 'application/x-font-type1', - 'smd' => 'application/vnd.stardivision.mail', - 'it' => 'audio/x-it', - 'bib' => 'text/x-bibtex', - 'moc' => 'text/x-moc', - 'theme' => 'application/x-theme', - 'mod' => 'audio/x-mod', - 'smf' => 'application/vnd.stardivision.math', - 'uni' => 'audio/x-mod', - 'mtm' => 'audio/x-mod', - 'ppz' => 'application/vnd.ms-powerpoint', - 's3m' => 'audio/x-s3m', - 'deb' => 'application/x-deb', - 'tk' => 'text/x-tcl', - 'cdr' => 'application/vnd.corel-draw', - 'lwob' => 'image/x-lwo', - 'sml' => 'application/smil', - 'etheme' => 'application/x-e-theme', - '3ds' => 'image/x-3ds', - 'vob' => 'video/mpeg', - 'voc' => 'audio/x-voc', - 'bdf' => 'application/x-font-bdf', - 'ps.gz' => 'application/x-gzpostscript', - 'uil' => 'text/x-uil', - 'ts' => 'application/x-linguist', - 'asp' => 'application/x-asp', - 'nes' => 'application/x-nes-rom', - 'sms' => 'application/x-sms-rom', - 'BLEND' => 'application/x-blender', - 'kil' => 'application/x-killustrator', - 'icb' => 'image/x-icb', - 'lyx' => 'application/x-lyx', - 'jng' => 'image/x-jng', - 'vor' => 'application/vnd.stardivision.writer', - 'adb' => 'text/x-adasrc', - 'flc' => 'video/x-flic', - 'wpg' => 'application/x-wpg', - 'wb1' => 'application/x-quattropro', - 'gra' => 'application/x-graphite', - 'wb2' => 'application/x-quattropro', - 'ltx' => 'text/x-tex', - 'xac' => 'application/x-gnucash', - 'wb3' => 'application/x-quattropro', - 'epsf' => 'image/x-eps', - 'el' => 'text/x-emacs-lisp', - 'jp2' => 'image/jpeg2000', - 'tar.gz' => 'application/x-compressed-tar', - 'epsi' => 'image/x-eps', - 'ui' => 'application/x-designer', - 'old' => 'application/x-trash', - 'tar.Z' => 'application/x-tarz', - 'ttf' => 'application/x-font-ttf', - 'siag' => 'application/x-siag', - 'sid' => 'audio/prs.sid', - 'msod' => 'image/x-msod', - 'h++' => 'text/x-chdr', - 'tar.lzo' => 'application/x-tzo', - 'tar.bz' => 'application/x-bzip-compressed-tar', - 'ads' => 'text/x-adasrc', - 'sda' => 'application/vnd.stardivision.draw', - 'lzo' => 'application/x-lzop', - 'cur' => 'image/x-win-bitmap', - 'sdc' => 'application/vnd.stardivision.calc', - 'sik' => 'application/x-trash', - 'sdd' => 'application/vnd.stardivision.impress', - 'xld' => 'application/vnd.ms-excel', - 'gmo' => 'application/x-gettext-translation', - 'xll' => 'application/vnd.ms-excel', - 'blend' => 'application/x-blender', - 'pw' => 'application/x-pw', - 'kud' => 'application/x-kugar', - 'mkv' => 'application/x-matroska', - 'obj' => 'application/x-tgif', - 'py' => 'text/x-python', - 'sds' => 'application/vnd.stardivision.chart', - 'idl' => 'text/x-idl', - 'dat' => 'video/mpeg', - 'stm' => 'audio/x-stm', - 'PAR2' => 'application/x-par2', - 'xcf.bz2' => 'image/x-compressed-xcf', - 'psid' => 'audio/prs.sid', - 'pict' => 'image/x-pict', - 'ag' => 'image/x-applix-graphics', - 'fo' => 'text/x-xslfo', - 'sdw' => 'application/vnd.stardivision.writer', - 'abw.CRASHED' => 'application/x-abiword', - 'gsf' => 'application/x-font-type1', - 'xcf.gz' => 'image/x-compressed-xcf', - 'pcd' => 'image/x-photo-cd', - 'egon' => 'application/x-egon', - 'pcf' => 'application/x-font-pcf', - 'al' => 'application/x-perl', - 'gnc' => 'application/x-gnucash', - 'tzo' => 'application/x-tzo', - 'la' => 'application/x-shared-library-la', - 'kpm' => 'application/x-kpovmodeler', - 'qif' => 'application/x-qw', - 'sty' => 'text/x-tex', - 'psf' => 'application/x-font-linux-psf', - 'as' => 'application/x-applix-spreadsheet', - 'dbf' => 'application/x-dbase', - 'ilbm' => 'image/x-ilbm', - 'aw' => 'application/x-applix-word', - 'gb' => 'application/x-gameboy-rom', - 'xmi' => 'text/x-xmi', - 'abw.gz' => 'application/x-abiword', - 'XM' => 'audio/x-mod', - 'gnumeric' => 'application/x-gnumeric', - 'bak' => 'application/x-trash', - 'xslfo' => 'text/x-xslfo', - 'gg' => 'application/x-sms-rom', - 'cgi' => 'application/x-cgi', - 'mgp' => 'application/x-magicpoint', - 'spd' => 'application/x-font-speedo', - 'gnucash' => 'application/x-gnucash', - 'cls' => 'text/x-tex', - 'php4' => 'application/x-php', - 'sun' => 'image/x-sun-raster', - 'pyc' => 'application/x-python-bytecode', - 'xcf' => 'image/x-xcf', - 'xbel' => 'application/x-xbel', - 'jpr' => 'application/x-jbuilder-project', - 'afm' => 'application/x-font-afm', - 'fig' => 'image/x-xfig', - 'perl' => 'application/x-perl', - 'rej' => 'application/x-reject', - 'qtvr' => 'video/quicktime', - 'jpx' => 'application/x-jbuilder-project', - '669' => 'audio/x-mod', - 'kdelnk' => 'application/x-desktop', - 'md' => 'application/x-genesis-rom', - 'pyo' => 'application/x-python-bytecode', - 'oleo' => 'application/x-oleo', - 'ac3' => 'audio/ac3', - 'mml' => 'text/mathml', - 'par2' => 'application/x-par2', - 'sylk' => 'text/spreadsheet', - 'C' => 'text/x-c++src', - 'cert' => 'application/x-x509-ca-cert', - 'ult' => 'audio/x-mod', - 'lwo' => 'image/x-lwo', - 'dcl' => 'text/x-dcl', - 'zoo' => 'application/x-zoo', - 'dcm' => 'application/dicom', - 'mm' => 'text/x-troff-mm', - 'iff' => 'image/x-iff', - 'lws' => 'image/x-lws', - 'zabw' => 'application/x-abiword', - 'blender' => 'application/x-blender', - 'glade' => 'application/x-glade', - 'rpm' => 'application/x-rpm', - 'tga' => 'image/x-tga', - 'jar' => 'application/x-jar', - 'cpio.gz' => 'application/x-cpio-compressed', - 'dsl' => 'text/x-dsl', - 'kra' => 'application/x-krita', - 'n64' => 'application/x-n64-rom', - 'm4a' => 'audio/x-m4a', - 'c++' => 'text/x-c++src', - 'moov' => 'video/quicktime', - 'sam' => 'application/x-amipro', - 'nsv' => 'video/x-nsv', - 'dia' => 'application/x-dia-diagram', - 'xi' => 'audio/x-xi', - 'hp' => 'text/x-chdr', - 'gen' => 'application/x-genesis-rom', - 'url' => 'text/x-uri', - 'hs' => 'text/x-haskell', - 'xm' => 'audio/x-xm', - 'sql' => 'text/x-sql', - 'NSV' => 'video/x-nsv', - 'desktop' => 'application/x-desktop', - 'mng' => 'video/x-mng', - 'pem' => 'application/x-x509-ca-cert', - 'slk' => 'text/spreadsheet', - 'cs' => 'text/x-csharp', - 'arj' => 'application/x-arj', - 'a' => 'application/x-archive', - 'lhs' => 'text/x-literate-haskell', - 'gcrd' => 'text/directory', - 'vct' => 'text/directory', - 'wk1' => 'application/vnd.lotus-1-2-3', - 'msx' => 'application/x-msx-rom', - 'sgi' => 'image/x-sgi', - 'd' => 'text/x-dsrc', - 'CSSL' => 'text/css', - 'wk3' => 'application/vnd.lotus-1-2-3', - 'abw' => 'application/x-abiword', - 'pict1' => 'image/x-pict' -); \ No newline at end of file