<?php
//
// +--------------------------------------------------------------------------+
// | |
// | XS PHP Library Generic Classes Library |
// | |
// | Copyright (c) 2001-2002 XSPHPLib Group. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Distributed under the terms of the GNU Lesser General Public License as |
// | published by the Free Software Foundation version 2.1 |
// | See the GNU Lesser General Public License for more details. You should |
// | have received a copy of the GNU Lesser General Public License along with |
// | this package; if not, write to the Free Software Foundation, Inc., |
// | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Authors: Robert Bala <hide@address.com> |
// | |
// +--------------------------------------------------------------------------+
//
// $Id: mime.inc.php,v 1.1.1.1 2002/11/26 23:00:31 rbala Exp $
/**
* 7 bit MIME encoding.
*
* 7bit data refers to data that is all represented as relatively short lines
* with 998 octets or less between CRLF line separation sequences [RFC-821].
* No octets with decimal values greater than 127 are allowed and neither are
* NULs (octets with decimal value 0). CRLF octets only occur as part of CRLF
* line separation sequences.
*/
define('MIME_ENCODING_7BIT', '7bit');
/**
* Base64 MIME encoding.
*
* The Base64 content-transfer-encoding is designed to represent arbitrary
* sequences of octets in a form that need not be humanly readable.
* The encoding and decoding algorithms are simple, but the encoded data are
* consistently only about 33 percent larger than the unencoded data.
*/
define('MIME_ENCODING_BASE64', 'base64');
/**
* Quoted-Printable MIME encoding.
*
* "Quoted-Printable" refers to content-transfer-encoding defined in RFC 2045.
* It is designed to allow text containing mostly ASCII characters to be
* decipherable on an ASCII terminal without decoding.
*/
define('MIME_ENCODING_QUOTEDPRINTABLE', 'quoted-printable');
/**
* MIME entity class.
*
* MIME entity class is a wrapper to the MIME-defined header fields and contents
* of either a message or one of the parts in the body of a multipart entity.
* Any sort of field may be present in the header of an entity, but only those
* fields whose names begin with "content-" actually have any MIME-related
* meaning. Note - this class is not finished yet. There are still some things
* to implement according to MIME standards.
*
* @author Robert Bala <hide@address.com>
* @access public
* @package net
* @version $Id: mime.inc.php,v 1.1.1.1 2002/11/26 23:00:31 rbala Exp $
*/
class Mime extends Object {
/**
* The MIME type the MIME entity.
* @access private
* @var string
*/
var $_mtype;
/**
* The MIME subtype the MIME entity.
* @access private
* @var string
*/
var $_stype;
/**
* The content of the MIME entity.
* @access private
* @var string
*/
var $_content;
/**
* The unique boundary of the MIME entity used with multipart entities.
* @access private
* @var string
*/
var $_boundary;
/**
* The encoding of the MIME entity.
* @access private
* @var string
*/
var $_encoding;
var $_mimeparts;
var $_mimeparams;
/**
* The content disposition (Content-Disposition) of the MIME entity.
* @access private
* @var string
*/
var $_disposition;
/**
* The content description (Content-Description) of the MIME entity.
* @access private
* @var string
*/
var $_description;
/**
* MIME class constructor.
*
* Creates the new instance of MIME class and sets up basic properties.
*
* @access public
* @param string $mtype the MIME type, defaults to "text".
* @param string $stype the MIME subtype, defaults to "plain".
* @return void
*/
function Mime($mtype='text', $stype='plain') {
Object::Object();
$this->_mtype = $mtype;
$this->_stype = $stype;
$this->_content = '';
$this->_boundary = '';
$this->_encoding = '7bit';
$this->_mimeparts = array();
$this->_mimeparams = array();
$this->_disposition = '';
$this->_description = '';
}
/**
* Gets content of the MIME entity.
*
* Returns content of the MIME entity, or empty string.
*
* @access public
* @return string
*/
function getContent() {
return $this->_content;
}
/**
* Gets encoding of the MIME entity.
*
* Returns cencoding of the MIME entity. Encoding could be one of the
* following constants (or strings): {@link MIME_ENCODING_7BIT},
* {@link MIME_ENCODING_BASE64}, {@link MIME_ENCODING_QUOTEDPRINTABLE}
*
* @access public
* @return string
*/
function getEncoding() {
return $this->_encoding;
}
/**
* Gets MIME entity subpart entity object.
*
* Returns the referenct to subpart object if it is registered, null otherwise.
*
* @access public
* @param string $part the subpart name.
* @return mixed
*/
function &getMimePart($part) {
$part = strtolower(trim($part));
if (isset($this->_mimeparts[$part])) {
return $this->_mimeparts[$part];
}
return null;
}
/**
* Gets param for MIME entity headers.
*
* If the the param is registered returns its value or empty string otherwise.
*
* @access public
* @param string $param the param name.
* @return boolean
*/
function getMimeParam($param) {
$param = strtolower(trim($param));
if (isset($this->_mimeparams[$param])) {
return $this->_mimeparams[$param];
}
return '';
}
/**
* Gets content disposition of the MIME entity.
*
* Returns content disposition (Content-Disposition) of the MIME entity.
*
* @access public
* @return string
*/
function getDisposition() {
return $this->_disposition;
}
/**
* Gets content description of the MIME entity.
*
* Returns content description (Content-Description) of the MIME entity.
*
* @access public
* @return string
*/
function getDescription() {
return $this->_description;
}
/**
* Sets content of the MIME entity.
*
* If content Returns true on success, error object otherwise. If content
* param is path to readable file the file content is loaded.
*
* @access public
* @param string $content the MIME entity content.
* @return mixed
*/
function setContent($content) {
if ((strlen($content) < 256) && file_exists($content)) {
if (is_readable($content)) {
$this->_content = implode('', @file($content));
} else {
return new Error('setcontent(): Content file is not readable.');
}
} else {
$this->_content = trim($content);
}
return true;
}
/**
* Sets encoding of the MIME entity.
*
* Returns true on success, false otherwise.
*
* @access public
* @param string $encoding the MIME entity encoding.
* @return boolean
*/
function setEncoding($encoding) {
$this->_encoding = $encoding;
return true;
}
/**
* Sets content disposition of the MIME entity.
*
* Returns true on success, false otherwise.
*
* @access public
* @param string $disposition the MIME entity content disposition.
* @return boolean
*/
function setDisposition($disposition) {
$this->_disposition = $disposition;
return true;
}
/**
* Sets content description of the MIME entity.
*
* Returns true on success, false otherwise.
*
* @access public
* @param string $description the MIME entity content description.
* @return boolean
*/
function setDescription($description) {
$this->_description = $description;
return true;
}
/**
* Sets param for MIME entity headers.
*
* Returns true on success, error object otherwise.
*
* @access public
* @param string $param the param name.
* @param string $param the param value.
* @return boolean
*/
function setMimeParam($param, $value) {
$param = strtolower(trim($param));
if (strlen($param)) {
$this->_mimeparams[$param] = $value;
} else {
return new Error('setmimeparam(): Param name could not be empty.');
}
return true;
}
/**
* Adds MIME entity subpart entity object.
*
* Returns the referenct to added subpart object, error object otherwise.
* Added subpart object is stored internally and can be accessible by its
* name specified in part name using the {@link MIME::getMimeParam()}. Error
* object will be returned if master entity type is not set to multipart.
*
* @access public
* @param string $part the subpart name.
* @param string $mtype the subpart MIME type, defaults to "text".
* @param string $stype the subpart MIME subtype, defaults to "plain".
* @return mixed
*/
function &addMimePart($part, $mtype='text', $stype='plain') {
$part = strtolower(trim($part));
if (($this->_mtype == 'multipart') && strlen($part)) {
$this->_mimeparts[$part] = new Mime($mtype, $stype);
} else {
return new Error('addmimepart(): Media type must be set to multipart and part name could not be empty.');
}
return $this->_mimeparts[$part];
}
/**
* Encodes MIME entity content.
*
* Returns encoded MIME entity content according to MIME entity encoding.
* If MIME entity content is not encoded it is returned as it is.
*
* @access public
* @param string $content the MIME entity content.
* @return boolean
*/
function encode() {
return mime_encode($this->_encoding, $this->_content);
}
/**
* Decodes MIME entity content.
*
* Set content, decode it according to MIME entity encoding and returns
* true on success, false otherwise.
*
* @access public
* @param string $content the MIME entity content.
* @return boolean
*/
function decode($content) {
$this->_content = mime_decode($this->_encoding, $content);
return true;
}
/**
* Retrieves MIME entity headers.
*
* Returns MIME entity headers.
*
* @access public
* @return string
*/
function mimeHeaders() {
global $HTTP_SERVER_VARS;
$result = 'Content-Type: ' . $this->_mtype . '/' . $this->_stype . ';';
if (($this->_mtype == 'text') && isset($this->_mimeparams['charset'])) {
$result .= " charset=\"" . $this->_mimeparams['charset'] . "\"\r\n";
} elseif ($this->_mtype == 'text') {
if (isset($HTTP_SERVER_VARS['HTTP_ACCEPT_CHARSET'])) {
$charsets = explode(',', $HTTP_SERVER_VARS['HTTP_ACCEPT_CHARSET']);
if (isset($charsets[0])) {
$result .= " charset=\"" . $charsets[0] . "\"\r\n";
} else {
$result .= " charset=\"us-ascii\"\r\n";
}
} else {
$result .= " charset=\"us-ascii\"\r\n";
}
} elseif ($this->_mtype == 'multipart') {
if ($this->_boundary == '') {
$this->_boundary = mime_boundary();
}
$result .= " boundary=\"" . $this->_boundary . "\"\r\n";
} elseif (isset($this->_mimeparams['name'])) {
$result .= " name=\"" . $this->_mimeparams['name'] . "\"\r\n";
} else {
$result .= "\r\n";
}
if ($this->_mtype != 'multipart') {
$result .= 'Content-Transfer-Encoding: ' . $this->_encoding . "\r\n";
}
if (strlen($this->_disposition)) {
$result .= 'Content-Disposition: ' . $this->_disposition . ';';
if (($this->_disposition == 'attachment') && isset($this->_mimeparams['filename'])) {
$result .= " filename=\"" . $this->_mimeparams['filename'] . "\"\r\n";
} elseif (($this->_disposition == 'attachment') && isset($this->_mimeparams['name'])) {
$result .= " filename=\"" . $this->_mimeparams['name'] . "\"\r\n";
} else {
$result .= "\r\n";
}
}
if (strlen($this->_description)) {
$result .= 'Content-Description: ' . $this->_description . "\r\n";
}
return $result;
}
/**
* Retrieves MIME entity message.
*
* Returns MIME entity content. If MIME entity is multipart type and has
* subpart objects their headers and message bodies are included.
*
* @access public
* @return string
*/
function mimeMessage() {
$result = "\r\n";
if ($this->_mtype == 'multipart') {
if ($this->_boundary == '') {
$this->_boundary = mime_boundary();
}
if ($this->_stype == 'mixed') {
$result .= "This is a multi-part message in MIME format.\r\n\r\n";
} else {
$result .= "\r\n";
}
foreach ($this->_mimeparts as $part) {
$result .= '--' . $this->_boundary . "\r\n";
$result .= $part->mimeHeaders();
$result .= $part->mimeMessage() . "\r\n";
}
$result .= '--' . $this->_boundary . "--\r\n";
} else {
$result .= $this->encode() . "\r\n";
}
return $result;
}
/**
* Finds whether the MIME entity is multipart.
*
* Returns true if MIME entity is multipart, false otherwise.
*
* @access public
* @return boolean
*/
function isMultipart() {
return ($this->_mtype == 'multipart');
}
}
/**
* Generates unique MIME boundary.
*
* Returns generated unique MIME boundary
*
* @author Robert Bala <hide@address.com>
* @access private
* @return string
*/
function mime_boundary() {
return '----=_' . date( 'YmdHis' ) . '_' . mt_rand( 10000, 99999 );
}
/**
* Encode MIME entity content.
*
* Returns encoded content of the MIME entity if the specified encoding is one of
* the following constants (or strings): {@link MIME_ENCODING_7BIT},
* {@link MIME_ENCODING_BASE64}, {@link MIME_ENCODING_QUOTEDPRINTABLE},
* unchanged content otherwise. Note - Quote-printable encoding is not supported.
*
* @author Robert Bala <hide@address.com>
* @access private
* @param string $encoding the MIME entity encoding.
* @param string $content the MIME entity content.
* @return boolean
*/
function mime_encode($encoding, $content) {
switch ($encoding) {
case MIME_ENCODING_BASE64:
$content = trim(chunk_split(base64_encode($content)));
break;
case MIME_ENCODING_7BIT:
$content = str_replace("\r\n", "\n", $content);
$content = str_replace("\r", "\n", $content);
$content = str_replace("\n", "\r\n", $content);
break;
case MIME_ENCODING_QUOTEDPRINTABLE:
/*
$hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
$lines = preg_split("/(?:\r\n|\r|\n)/", $input);
$escape = "=";
$output = "";
while( list(, $line) = each($content) ) {
$linlen = strlen($line);
$newline = "";
for($i = 0; $i < $linlen; $i++) {
$c = substr($line, $i, 1);
$dec = ord($c);
if ( ($dec == 32) && ($i == ($linlen - 1)) ) {
$c = "=20";
} elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) {
$h2 = floor($dec/16); $h1 = floor($dec%16);
$c = $escape.$hex["$h2"].$hex["$h1"];
}
if ( (strlen($newline) + strlen($c)) >= $line_max ) {
$output .= $newline.$escape . "\r\n";
$newline = "";
}
$newline .= $c;
}
$output .= $newline . "\r\n";
}
return trim($output);
*/
break;
}
return $content;
}
/**
* Decode MIME entity content.
*
* Returns decoded content of the MIME entity if the specified encoding is one of
* the following constants (or strings): {@link MIME_ENCODING_7BIT},
* {@link MIME_ENCODING_BASE64}, {@link MIME_ENCODING_QUOTEDPRINTABLE}, empty
* string otherwise.
*
* @author Robert Bala <hide@address.com>
* @access private
* @param string $encoding the MIME entity encoding.
* @param string $content the MIME entity content.
* @return boolean
*/
function mime_decode($encoding, $content) {
switch ($encoding) {
case MIME_ENCODING_7BIT:
break;
case MIME_ENCODING_BASE64:
$content = base64_decode($content);
break;
case MIME_ENCODING_QUOTEDPRINTABLE:
$content = quoted_printable_decode($content);
while (ereg("=\n", $content)) {
$content = ereg_replace ("=\n", '', $content);
}
break;
}
return $content;
}
/**
* Check if specified encoding is supported.
*
* Returns true is specified encoding is supported, false otherwise.
*
* @author Robert Bala <hide@address.com>
* @access private
* @param string $string the MIME entity encoding.
* @return boolean
*/
function mime_validateEncoding($string) {
switch ($string) {
case MIME_ENCODING_7BIT:
return true;
case MIME_ENCODING_BASE64:
return true;
}
return false;
}
?>