science-ation/Rmail/Rmail.php

1112 lines
31 KiB
PHP

<?php
/**
* o------------------------------------------------------------------------------o
* | This package is licensed under the Phpguru license. A quick summary is |
* | that for commercial use, there is a small one-time licensing fee to pay. For |
* | registered charities and educational institutes there is a reduced license |
* | fee available. You can read more at: |
* | |
* | http://www.phpguru.org/static/license.html |
* o------------------------------------------------------------------------------o
*
* © Copyright 2008,2009 Richard Heyes
*/
require_once(dirname(__FILE__) . '/mimePart.php');
class Rmail
{
/**
* The html part of the message
* @var string
*/
private $html;
/**
* The text part of the message(only used in TEXT only messages)
* @private string
*/
private $text;
/**
* The main body of the message after building
* @private string
*/
private $output;
/**
* An array of embedded images /objects
* @private array
*/
private $html_images;
/**
* An array of recognised image types for the findHtmlImages() method
* @private array
*/
private $image_types;
/**
* Parameters that affect the build process
* @private array
*/
private $build_params;
/**
* Array of attachments
* @private array
*/
private $attachments;
/**
* The main message headers
* @private array
*/
private $headers;
/**
* The return path address. If not set the From:
* address is used instead
* @private string
*/
private $return_path;
/**
* Array of information needed for smtp sending
* @private array
*/
private $smtp_params;
/**
* Sendmail path. Do not include -f
* @private $sendmail_path
*/
private $sendmail_path;
/**
* Constructor function.
*/
public function __construct()
{
/**
* Initialise some variables.
*/
$this->attachments = array();
$this->html_images = array();
$this->headers = array();
$this->text = '';
$this->sendmail_path = '/usr/lib/sendmail -ti';
/**
* If you want the auto load functionality
* to find other image/file types, add the
* extension and content type here.
*/
$this->image_types = array('gif' => 'image/gif',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'bmp' => 'image/bmp',
'png' => 'image/png',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'swf' => 'application/x-shockwave-flash');
/**
* Set these up
*/
$this->build_params['html_encoding'] = new QPrintEncoding();
$this->build_params['text_encoding'] = new SevenBitEncoding();
$this->build_params['html_charset'] = 'ISO-8859-1';
$this->build_params['text_charset'] = 'ISO-8859-1';
$this->build_params['head_charset'] = 'ISO-8859-1';
$this->build_params['text_wrap'] = 998;
/**
* Defaults for smtp sending
*/
if (!empty($_SERVER['HTTP_HOST'])) {
$helo = $_SERVER['HTTP_HOST'];
} elseif (!empty($_SERVER['SERVER_NAME'])) {
$helo = $_SERVER['SERVER_NAME'];
} else {
$helo = 'localhost';
}
$this->smtp_params['host'] = 'localhost';
$this->smtp_params['port'] = 25;
$this->smtp_params['helo'] = $helo;
$this->smtp_params['auth'] = false;
$this->smtp_params['user'] = '';
$this->smtp_params['pass'] = '';
/**
* Make sure the MIME version header is first.
*/
$this->headers['MIME-Version'] = '1.0';
$this->headers['X-Mailer'] = 'Rmail <http://www.phpguru.org/>';
}
/**
* Accessor to set the CRLF style
*
* @param string $crlf CRLF style to use.
* Use \r\n for SMTP, and \n
* for normal.
*/
public function setCRLF($crlf = "\n")
{
if (!defined('RMAIL_CRLF')) {
define('RMAIL_CRLF', $crlf, true);
}
if (!defined('MAIL_MIMEPART_CRLF')) {
define('MAIL_MIMEPART_CRLF', $crlf, true);
}
}
/**
* Accessor to set the SMTP parameters
*
* @param string $host Hostname
* @param string $port Port
* @param string $helo HELO string to use
* @param bool $auth User authentication or not
* @param string $user Username
* @param string $pass Password
*/
public function setSMTPParams($host = null, $port = null, $helo = null, $auth = null, $user = null, $pass = null)
{
if (!is_null($host)) $this->smtp_params['host'] = $host;
if (!is_null($port)) $this->smtp_params['port'] = $port;
if (!is_null($helo)) $this->smtp_params['helo'] = $helo;
if (!is_null($auth)) $this->smtp_params['auth'] = $auth;
if (!is_null($user)) $this->smtp_params['user'] = $user;
if (!is_null($pass)) $this->smtp_params['pass'] = $pass;
}
/**
* Sets sendmail path and options (optionally) (when directly piping to sendmail)
*
* @param string $path Path and options for sendmail command
*/
public function setSendmailPath($path)
{
$this->sendmail_path = $path;
}
/**
* Accessor function to set the text encoding
*
* @param object $encoding Text encoding to use
*/
public function setTextEncoding(iEncoding $encoding)
{
$this->build_params['text_encoding'] = $encoding;
}
/**
* Accessor function to set the HTML encoding
*
* @param object $encoding HTML encoding to use
*/
public function setHTMLEncoding(iEncoding $encoding)
{
$this->build_params['html_encoding'] = $encoding;
}
/**
* Accessor function to set the text charset
*
* @param string $charset Character set to use
*/
public function setTextCharset($charset = 'ISO-8859-1')
{
$this->build_params['text_charset'] = $charset;
}
/**
* Accessor function to set the HTML charset
*
* @param string $charset Character set to use
*/
public function setHTMLCharset($charset = 'ISO-8859-1')
{
$this->build_params['html_charset'] = $charset;
}
/**
* Accessor function to set the header encoding charset
*
* @param string $charset Character set to use
*/
public function setHeadCharset($charset = 'ISO-8859-1')
{
$this->build_params['head_charset'] = $charset;
}
/**
* Accessor function to set the text wrap count
*
* @param integer $count Point at which to wrap text
*/
public function setTextWrap($count = 998)
{
$this->build_params['text_wrap'] = $count;
}
/**
* Accessor to set a header
*
* @param string $name Name of header
* @param string $value Value of header
*/
public function setHeader($name, $value)
{
$this->headers[$name] = $value;
}
/**
* Sets the delivery reciept address
*
* @param string $email The address you want the delivery reciept
* sent to. Note that this is sent at the
* discretion of the recipient
*/
public function setReceipt($email)
{
$this->headers['Disposition-Notification-To'] = $email;
}
/**
* Accessor to add a Subject: header
*
* @param string $subject Subject to set
*/
public function setSubject($subject)
{
$this->headers['Subject'] = $subject;
}
/**
* Accessor to add a From: header
*
* @param string $from From address
*/
public function setFrom($from)
{
$this->headers['From'] = $from;
}
/**
* Accessor to set priority. Priority given should be either
* high, normal or low. Can also be specified numerically,
* being 1, 3 or 5 (respectively).
*
* @param mixed $priority The priority to use.
*/
public function setPriority($priority = 'normal')
{
switch (strtolower($priority)) {
case 'high':
case '1':
$this->headers['X-Priority'] = '1';
$this->headers['X-MSMail-Priority'] = 'High';
break;
case 'normal':
case '3':
$this->headers['X-Priority'] = '3';
$this->headers['X-MSMail-Priority'] = 'Normal';
break;
case 'low':
case '5':
$this->headers['X-Priority'] = '5';
$this->headers['X-MSMail-Priority'] = 'Low';
break;
}
}
/**
* Accessor to set the return path
*
* @param string $return_path Return path to use
*/
public function setReturnPath($return_path)
{
$this->return_path = $return_path;
}
/**
* Accessor to add a Cc: header
*
* @param string $cc Carbon Copy address
*/
public function setCc($cc)
{
$this->headers['Cc'] = $cc;
}
/**
* Accessor to add a Bcc: header
*
* @param string $bcc Blind Carbon Copy address
*/
public function setBcc($bcc)
{
$this->headers['Bcc'] = $bcc;
}
/**
* Adds plain text. Use this function
* when NOT sending html email
*
* @param string $text Plain text of email
*/
public function setText($text)
{
$this->text = $text;
}
/**
* Adds HTML to the emails, with an associated text part.
* If third part is given, images in the email will be loaded
* from this directory.
*
* @param string $html HTML part of email
* @param string $images_dir Images directory
*/
function setHTML($html, $images_dir = null)
{
$this->html = $html;
if (!empty($images_dir)) {
$this->findHtmlImages($images_dir);
}
}
/**
* Function for extracting images from
* html source. This function will look
* through the html code supplied by setHTML()
* and find any file that ends in one of the
* extensions defined in $obj->image_types.
* If the file exists it will read it in and
* embed it, (not an attachment).
*
* @param string $images_dir Images directory to look in
*/
private function findHtmlImages($images_dir)
{
// Build the list of image extensions
$extensions = array_keys($this->image_types);
preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $matches);
foreach ($matches[1] as $m) {
if (file_exists($images_dir . $m)) {
$html_images[] = $m;
$this->html = str_replace($m, basename($m), $this->html);
}
}
/**
* Go thru found images
*/
if (!empty($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
$html_images = array_unique($html_images);
sort($html_images);
foreach ($html_images as $img) {
if ($image = file_get_contents($images_dir . $img)) {
$ext = preg_replace('#^.*\.(\w{3,4})$#e', 'strtolower("$1")', $img);
$content_type = $this->image_types[$ext];
$this->addEmbeddedImage(new stringEmbeddedImage($image, basename($img), $content_type));
}
}
}
}
/**
* Adds an image to the list of embedded
* images.
*
* @param string $object Embedded image object
*/
public function addEmbeddedImage($embeddedImage)
{
$embeddedImage->cid = md5(uniqid(time()));
$this->html_images[] = $embeddedImage;
}
/**
* Adds a file to the list of attachments.
*
* @param string $attachment Attachment object
*/
public function addAttachment($attachment)
{
$this->attachments[] = $attachment;
}
/**
* Adds a text subpart to a mime_part object
*
* @param object $obj
* @return object Mime part object
*/
private function addTextPart(&$message)
{
$params['content_type'] = 'text/plain';
$params['encoding'] = $this->build_params['text_encoding']->getType();
$params['charset'] = $this->build_params['text_charset'];
if (!empty($message)) {
$message->addSubpart($this->text, $params);
} else {
$message = new Mail_mimePart($this->text, $params);
}
}
/**
* Adds a html subpart to a mime_part object
*
* @param object $obj
* @return object Mime part object
*/
private function addHtmlPart(&$message)
{
$params['content_type'] = 'text/html';
$params['encoding'] = $this->build_params['html_encoding']->getType();
$params['charset'] = $this->build_params['html_charset'];
if (!empty($message)) {
$message->addSubpart($this->html, $params);
} else {
$message = new Mail_mimePart($this->html, $params);
}
}
/**
* Starts a message with a mixed part
*
* @return object Mime part object
*/
private function addMixedPart(&$message)
{
$params['content_type'] = 'multipart/mixed';
$message = new Mail_mimePart('', $params);
}
/**
* Adds an alternative part to a mime_part object
*
* @param object $obj
* @return object Mime part object
*/
private function addAlternativePart(&$message)
{
$params['content_type'] = 'multipart/alternative';
if (!empty($message)) {
return $message->addSubpart('', $params);
} else {
$message = new Mail_mimePart('', $params);
}
}
/**
* Adds a html subpart to a mime_part object
*
* @param object $obj
* @return object Mime part object
*/
private function addRelatedPart(&$message)
{
$params['content_type'] = 'multipart/related';
if (!empty($message)) {
return $message->addSubpart('', $params);
} else {
$message = new Mail_mimePart('', $params);
}
}
/**
* Adds all html images to a mime_part object
*
* @param object $obj Message object
*/
private function addHtmlImageParts(&$message)
{
foreach ($this->html_images as $value) {
$params['content_type'] = $value->contentType;
$params['encoding'] = $value->encoding->getType();
$params['disposition'] = 'inline';
$params['dfilename'] = $value->name;
$params['cid'] = $value->cid;
$message->addSubpart($value->data, $params);
}
}
/**
* Adds all attachments to a mime_part object
*
* @param object $obj Message object
*/
private function addAttachmentParts(&$message)
{
foreach ($this->attachments as $value) {
$params['content_type'] = $value->contentType;
$params['encoding'] = $value->encoding->getType();
$params['disposition'] = 'attachment';
$params['dfilename'] = $value->name;
$message->addSubpart($value->data, $params);
}
}
/**
* Builds the multipart message.
*/
private function build()
{
if (!empty($this->html_images)) {
foreach ($this->html_images as $value) {
$quoted = preg_quote($value->name);
$cid = preg_quote($value->cid);
$this->html = preg_replace("#src=\"$quoted\"|src='$quoted'#", "src=\"cid:$cid\"", $this->html);
$this->html = preg_replace("#background=\"$quoted\"|background='$quoted'#", "background=\"cid:$cid\"", $this->html);
}
}
$message = null;
$attachments = !empty($this->attachments);
$html_images = !empty($this->html_images);
$html = !empty($this->html);
$text = !$html;
switch (true) {
case $text:
$message = null;
if ($attachments) {
$this->addMixedPart($message);
}
$this->addTextPart($message);
// Attachments
$this->addAttachmentParts($message);
break;
case $html AND !$attachments AND !$html_images:
$this->addAlternativePart($message);
$this->addTextPart($message);
$this->addHtmlPart($message);
break;
case $html AND !$attachments AND $html_images:
$this->addRelatedPart($message);
$alt = $this->addAlternativePart($message);
$this->addTextPart($alt);
$this->addHtmlPart($alt);
// HTML images
$this->addHtmlImageParts($message);
break;
case $html AND $attachments AND !$html_images:
$this->addMixedPart($message);
$alt = $this->addAlternativePart($message);
$this->addTextPart($alt);
$this->addHtmlPart($alt);
// Attachments
$this->addAttachmentParts($message);
break;
case $html AND $attachments AND $html_images:
$this->addMixedPart($message);
$rel = $this->addRelatedPart($message);
$alt = $this->addAlternativePart($rel);
$this->addTextPart($alt);
$this->addHtmlPart($alt);
// HTML images
$this->addHtmlImageParts($rel);
// Attachments
$this->addAttachmentParts($message);
break;
}
if (isset($message)) {
$output = $message->encode();
$this->output = $output['body'];
$this->headers = array_merge($this->headers, $output['headers']);
// Figure out hostname
if (!empty($_SERVER['HTTP_HOST'])) {
$hostname = $_SERVER['HTTP_HOST'];
} else if (!empty($_SERVER['SERVER_NAME'])) {
$hostname = $_SERVER['SERVER_NAME'];
} else if (!empty($_ENV['HOSTNAME'])) {
$hostname = $_ENV['HOSTNAME'];
} else {
$hostname = 'localhost';
}
$message_id = sprintf('<%s.%s@%s>', base_convert(time(), 10, 36), base_convert(rand(), 10, 36), $hostname);
$this->headers['Message-ID'] = $message_id;
return true;
} else {
return false;
}
}
/**
* Function to encode a header if necessary
* according to RFC2047
*
* @param string $input Value to encode
* @param string $charset Character set to use
* @return string Encoded value
*/
private function encodeHeader($input, $charset = 'ISO-8859-1')
{
preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches);
foreach ($matches[1] as $value) {
$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
}
return $input;
}
/**
* Sends the mail.
*
* @param array $recipients Array of receipients to send the mail to
* @param string $type How to send the mail ('mail' or 'sendmail' or 'smtp')
* @return mixed
*/
public function send($recipients, $type = 'mail')
{
if (!defined('RMAIL_CRLF')) {
$this->setCRLF( ($type == 'mail' OR $type == 'sendmail') ? "\n" : "\r\n");
}
$this->build();
switch ($type) {
case 'mail':
$subject = '';
if (!empty($this->headers['Subject'])) {
$subject = $this->encodeHeader($this->headers['Subject'], $this->build_params['head_charset']);
unset($this->headers['Subject']);
}
// Get flat representation of headers
foreach ($this->headers as $name => $value) {
$headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
}
$to = $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
if (!empty($this->return_path)) {
$result = mail($to, $subject, $this->output, implode(RMAIL_CRLF, $headers), '-f' . $this->return_path);
} else {
$result = mail($to, $subject, $this->output, implode(RMAIL_CRLF, $headers));
}
// Reset the subject in case mail is resent
if ($subject !== '') {
$this->headers['Subject'] = $subject;
}
// Return
return $result;
break;
case 'sendmail':
// Get flat representation of headers
foreach ($this->headers as $name => $value) {
$headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
}
// Encode To:
$headers[] = 'To: ' . $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
// Get return path arg for sendmail command if necessary
$returnPath = '';
if (!empty($this->return_path)) {
$returnPath = '-f' . $this->return_path;
}
$pipe = popen($this->sendmail_path . " " . $returnPath, 'w');
$bytes = fputs($pipe, implode(RMAIL_CRLF, $headers) . RMAIL_CRLF . RMAIL_CRLF . $this->output);
$r = pclose($pipe);
return $r;
break;
case 'smtp':
require_once(dirname(__FILE__) . '/smtp.php');
require_once(dirname(__FILE__) . '/RFC822.php');
$smtp = &smtp::connect($this->smtp_params);
// Parse recipients argument for internet addresses
foreach ($recipients as $recipient) {
$addresses = Mail_RFC822::parseAddressList($recipient, $this->smtp_params['helo'], null, false);
foreach ($addresses as $address) {
$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
}
}
unset($addresses); // These are reused
unset($address); // These are reused
// Get flat representation of headers, parsing
// Cc and Bcc as we go
foreach ($this->headers as $name => $value) {
if ($name == 'Cc' OR $name == 'Bcc') {
$addresses = Mail_RFC822::parseAddressList($value, $this->smtp_params['helo'], null, false);
foreach ($addresses as $address) {
$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
}
}
if ($name == 'Bcc') {
continue;
}
$headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
}
// Add To header based on $recipients argument
$headers[] = 'To: ' . $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
// Add headers to send_params
$send_params['headers'] = $headers;
$send_params['recipients'] = array_values(array_unique($smtp_recipients));
$send_params['body'] = $this->output;
// Setup return path
if (isset($this->return_path)) {
$send_params['from'] = $this->return_path;
} elseif (!empty($this->headers['From'])) {
$from = Mail_RFC822::parseAddressList($this->headers['From']);
$send_params['from'] = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
} else {
$send_params['from'] = 'postmaster@' . $this->smtp_params['helo'];
}
// Send it
if (!$smtp->send($send_params)) {
$this->errors = $smtp->getErrors();
return false;
}
return true;
break;
}
}
/**
* Use this method to return the email
* in message/rfc822 format. Useful for
* adding an email to another email as
* an attachment.
*
* @param array $recipients Array of recipients
* @param string $type Method to be used to send the mail.
* Used to determine the line ending type.
*/
public function getRFC822($recipients, $type = 'mail')
{
// Make up the date header as according to RFC822
$this->setHeader('Date', date('D, d M y H:i:s O'));
if (!defined('RMAIL_CRLF')) {
$this->setCRLF($type == 'mail' ? "\n" : "\r\n");
}
$this->build();
// Return path ?
if (isset($this->return_path)) {
$headers[] = 'Return-Path: ' . $this->return_path;
}
// Get flat representation of headers
foreach ($this->headers as $name => $value) {
$headers[] = $name . ': ' . $value;
}
$headers[] = 'To: ' . implode(', ', $recipients);
return implode(RMAIL_CRLF, $headers) . RMAIL_CRLF . RMAIL_CRLF . $this->output;
}
} // End of class.
/**
* Attachment classes
*/
class attachment
{
/**
* Data of attachment
* @var string
*/
public $data;
/**
* Name of attachment (filename)
* @var string
*/
public $name;
/**
* Content type of attachment
* @var string
*/
public $contentType;
/**
* Encoding type of attachment
* @var object
*/
public $encoding;
/**
* Constructor
*
* @param string $data File data
* @param string $name Name of attachment (filename)
* @param string $contentType Content type of attachment
* @param object $encoding Encoding type to use
*/
public function __construct($data, $name, $contentType, iEncoding $encoding)
{
$this->data = $data;
$this->name = $name;
$this->contentType = $contentType;
$this->encoding = $encoding;
}
}
/**
* File based attachment class
*/
class fileAttachment extends attachment
{
/**
* Constructor
*
* @param string $filename Name of file
* @param string $contentType Content type of file
* @param string $encoding What encoding to use
*/
public function __construct($filename, $contentType = 'application/octet-stream', $encoding = null)
{
$encoding = is_null($encoding) ? new Base64Encoding() : $encoding;
parent::__construct(file_get_contents($filename), basename($filename), $contentType, $encoding);
}
}
/**
* Attachment class to handle attachments which are contained
* in a variable.
*/
class stringAttachment extends attachment
{
/**
* Constructor
*
* @param string $data File data
* @param string $name Name of attachment (filename)
* @param string $contentType Content type of file
* @param string $encoding What encoding to use
*/
public function __construct($data, $name = '', $contentType = 'application/octet-stream', $encoding = null)
{
$encoding = is_null($encoding) ? new Base64Encoding() : $encoding;
parent::__construct($data, $name, $contentType, $encoding);
}
}
/**
* File based embedded image class
*/
class fileEmbeddedImage extends fileAttachment
{
}
/**
* String based embedded image class
*/
class stringEmbeddedImage extends stringAttachment
{
}
/**
*
*/
/**
* Encoding interface
*/
interface iEncoding
{
public function encode($input);
public function getType();
}
/**
* Base64 Encoding class
*/
class Base64Encoding implements iEncoding
{
/*
* Function to encode data using
* base64 encoding.
*
* @param string $input Data to encode
*/
public function encode($input)
{
return rtrim(chunk_split(base64_encode($input), 76, defined('MAIL_MIME_PART_CRLF') ? MAIL_MIME_PART_CRLF : "\r\n"));
}
/**
* Returns type
*/
public function getType()
{
return 'base64';
}
}
/**
* Quoted Printable Encoding class
*/
class QPrintEncoding implements iEncoding
{
/*
* Function to encode data using
* quoted-printable encoding.
*
* @param string $input Data to encode
*/
public function encode($input)
{
// Replace non printables
$input = preg_replace('/([^\x20\x21-\x3C\x3E-\x7E\x0A\x0D])/e', 'sprintf("=%02X", ord("\1"))', $input);
$inputLen = strlen($input);
$outLines = array();
$output = '';
$lines = preg_split('/\r?\n/', $input);
// Walk through each line
for ($i=0; $i<count($lines); $i++) {
// Is line too long ?
if (strlen($lines[$i]) > $lineMax) {
$outLines[] = substr($lines[$i], 0, $lineMax - 1) . "="; // \r\n Gets added when lines are imploded
$lines[$i] = substr($lines[$i], $lineMax - 1);
$i--; // Ensure this line gets redone as we just changed it
} else {
$outLines[] = $lines[$i];
}
}
// Convert trailing whitespace
$output = preg_replace('/(\x20+)$/me', 'str_replace(" ", "=20", "\1")', $outLines);
return implode("\r\n", $output);
}
/**
* Returns type
*/
public function getType()
{
return 'quoted-printable';
}
}
/**
* 7Bit Encoding class
*/
class SevenBitEncoding implements iEncoding
{
/*
* Function to "encode" data using
* 7bit encoding.
*
* @param string $input Data to encode
*/
public function encode($input)
{
return $input;
}
/**
* Returns type
*/
public function getType()
{
return '7bit';
}
}
/**
* 8Bit Encoding class
*/
class EightBitEncoding implements iEncoding
{
/*
* Function to "encode" data using
* 8bit encoding.
*
* @param string $input Data to encode
*/
public function encode($input)
{
return $input;
}
/**
* Returns type
*/
public function getType()
{
return '8bit';
}
}
?>