<?php
// $horde: horde/lib/mime.php,v 1.63 2001/08/08 21:00:27 chuck exp $
$mime_types =
array(
typetext => 'text', 'text' => typetext,
typemultipart => 'multipart', 'multipart' => typemultipart,
typemessage => 'message', 'message' => typemessage,
typeapplication => 'application', 'application' => typeapplication,
typeaudio => 'audio', 'audio' => typeaudio,
typeimage => 'image', 'image' => typeimage,
typevideo => 'video', 'video' => typevideo,
typeother => 'unknown', 'unknown' => typeother
);
$mime_encodings =
array(
enc7bit => '7bit', '7bit' => enc7bit,
enc8bit => '8bit', '8bit' => enc8bit,
encbinary => 'binary', 'binary' => encbinary,
encbase64 => 'base64', 'base64' => encbase64,
encquotedprintable => 'quoted-printable', 'quoted-printable' => encquotedprintable,
encother => 'unknown', 'unknown' => encother
);
/**
* the mime:: class provides methods for dealing with mime standards.
*
* @author chuck hagenbuch <chuck@horde.org>
* @version $revision: 1.64 $
* @since horde 1.3
* @package horde.mime
*/
class mime {
/**
* determine if a string contains 8-bit characters.
* @access private
*
* @param string $string the string to check.
* @return boolean true if it does, false if it doesn't.
*/
function is8bit($string)
{
if (is_string($string)) {
for ($i = 0; $i < strlen($string); $i++) {
if (ord($string[$i]) >> 7)
return true;
}
return false;
}
return false;
}
/**
* encode a string containing non-ascii characters according to rfc 2047.
*
* @param string $text the text to encode.
* @param string $charset (optional) the character set of the text.
* @param boolean $outer is this the final iteration?
*
* @return string the text, encoded only if it contains non-ascii characters.
*/
function encode($text, $charset = null, $outer = true)
{
if (mime::is8bit($text)) {
if (((strlen($text) * 3) + strlen($charset) + 7) > 76) {
$text = mime::encode(substr($text, 0, (23 - strlen($charset))), $charset) . mime::encode(substr($text, (23 - strlen($charset))), $charset, false);
} else {
$text = "=?$charset?b?" . strtr(trim(base64_encode($text)), ' ', '_') . "?=\n\t";
}
}
// if this is the final iteration, take off any trailing
// newline/tab chars.
if ($outer && (substr($text, -2) == "\n\t"))
$text = substr($text, 0, -2);
return $text;
}
/**
* encode a string containing email addresses according to rfc 2047.
*
* this differs from mime::encode() because it keeps email
* addresses legal, only encoding the personal information.
*
* @param string $text the email addresses to encode.
* @param string $charset (optional) the character set of the text.
* @param string $defserver (optional) the default domain to append to mailboxes.
*
* @return string the text, encoded only if it contains non-ascii characters.
*/
function encodeaddress($text, $charset = null, $defserver = null)
{
include_once 'mail/rfc822.php';
$addr_arr = mail_rfc822::parseaddresslist($text, $defserver, false, false);
$text = '';
if (is_array($addr_arr)) {
foreach ($addr_arr as $addr) {
if (empty($addr->personal)) {
$personal = '';
} else {
if ((substr($addr->personal, 0, 1) == '"') &&
(substr($addr->personal, -1) == '"')) {
$addr->personal = substr($addr->personal, 1, -1);
}
$personal = mime::encode($addr->personal, $charset);
}
if (strlen($text) != 0) $text .= ', ';
// fixme: dependency on imap module
$text .= mime::trimemailaddress(imap_rfc822_write_address($addr->mailbox, $addr->host, $personal));
}
}
return $text;
}
/**
* decode an rfc 2047-encoded string.
*
* @param string $string the text to decode.
* @return string the decoded text, or the original string if it was not encoded.
*/
function decode($string)
{
$pos = strpos($string, '=?');
if ($pos === false) {
return $string;
}
// take out any spaces between multiple encoded words
$string = preg_replace('|\?=\s=\?|', '?==?', $string);
$preceding = substr($string, 0, $pos); // save any preceding text
$search = substr($string, $pos + 2, 75); // the mime header spec says this is the longest a single encoded word can be
$d1 = strpos($search, '?');
if (!is_int($d1)) {
return $string;
}
$charset = substr($string, $pos + 2, $d1);
$search = substr($search, $d1 + 1);
$d2 = strpos($search, '?');
if (!is_int($d2)) {
return $string;
}
$encoding = substr($search, 0, $d2);
$search = substr($search, $d2+1);
$end = strpos($search, '?=');
if (!is_int($end)) {
return $string;
}
$encoded_text = substr($search, 0, $end);
$rest = substr($string, (strlen($preceding . $charset . $encoding . $encoded_text) + 6));
switch ($encoding) {
case 'q':
case 'q':
$encoded_text = str_replace('_', '%20', $encoded_text);
$encoded_text = str_replace('=', '%', $encoded_text);
$decoded = urldecode($encoded_text);
/* convert cyrillic character sets. */
if (stristr($globals['registry']->getcharset(), 'windows-1251')) {
if (stristr($charset, 'koi8-r')) {
$decoded = convert_cyr_string($decoded, 'k', 'w');
}
}
if (stristr($globals['registry']->getcharset(), 'koi8-r')) {
if (stristr($charset, 'windows-1251')) {
$decoded = convert_cyr_string($decoded, 'w', 'k');
}
}
break;
case 'b':
case 'b':
$decoded = urldecode(base64_decode($encoded_text));
if (stristr($globals['registry']->getcharset(), 'windows-1251')) {
if (stristr($charset, 'koi8-r')) {
$decoded = convert_cyr_string($decoded, 'k', 'w');
}
}
if (stristr($globals['registry']->getcharset(), 'koi8-r')) {
if (stristr($charset, 'windows-1251')) {
$decoded = convert_cyr_string($decoded, 'w', 'k');
}
}
break;
default:
$decoded = '=?' . $charset . '?' . $encoding . '?' . $encoded_text . '?=';
break;
}
return $preceding . $decoded . mime::decode($rest);
}
/**
* 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.
*/
function trimemailaddress($address)
{
$address = trim($address);
if ((substr($address, 0, 1) == '<') && (substr($address, -1) == '>')) {
$address = substr($address, 1, -1);
}
return $address;
}
}
?>