<?php
// (c) Copyright 2002-2012 by authors of the Tiki Wiki CMS Groupware Project
//
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id: mimelib.php 40096 2012-03-09 21:54:05Z pkdille $

//this script may only be included - so its better to die if called directly.
if (strpos($_SERVER['SCRIPT_NAME'], basename(__FILE__)) !== false) {
	header('location: index.php');
	exit;
}

class mime
{
	function mime()
	{

	}

	function decode($input,$default_ctype = 'text/plain', $crlf = "\r\n")
	{
		$back = array();

		$pos = strpos($input, $crlf.$crlf);
		if (!$pos) {
			$crlf = "\n";
			$pos = strpos($input, $crlf.$crlf);
			if (!$pos) {
				return false;
			}
		}

		$header = substr($input, 0, $pos);
		$body = substr($input, $pos + (2 * strlen($crlf)));

		$headparsed = preg_replace('/' . $crlf . "(\t| )/", ' ', $header);
		$heads = explode($crlf, trim($headparsed));

		if (substr($heads[0], 0, 5) == 'From ') {
			$heads[0] = str_replace('From ', 'x-From: ', $heads[0]);
		}

		foreach ($heads as $line) {
			$hdr_name = trim(substr($line, 0, strpos($line, ':')));
			$hdr_value = trim(substr($line, strpos($line, ':')+1));

			if (substr($hdr_value, 0, 1) == ' ')
				$hdr_value = substr($hdr_value, 1);

			$hdr_value = preg_replace('/(=\?[^?]+\?(Q|B|q|b)\?[^?]*\?=)( |' . "\t|" . $crlf . ')+=\?/', '\1=?', $hdr_value);

			while (preg_match('/(=\?([^?]+)\?(Q|B|q|b)\?([^?]*)\?=)/', $hdr_value, $matches)) {
				list(,$encoded,$charset,$encoding,$text) = $matches;

				switch ($encoding) {
					case 'B':
					case 'b':
						$text = base64_decode($text);
									break;

					case 'Q':
					case 'q':
						$text = str_replace('_', ' ', $text);
						preg_match_all('/=([A-F0-9]{2})/', $text, $matches);
						foreach ($matches[1] as $value) {
							$text = str_replace('=' . $value, chr(hexdec($value)), $text);
						}
									break;
				}

				if ($charset == 'iso-8859-1') {
					$text = utf8_encode($text);
				} elseif ($charset != 'utf-8' && function_exists('mb_convert_encoding')) {
					$text = mb_convert_encoding($text, 'utf-8', $charset);
				}

				$hdr_value = str_replace($encoded, $text, $hdr_value);
			}

			$lname = strtolower($hdr_name);

			if (isset($back['header'][$lname]) and !is_array($back['header'][$lname])) {
				$back['header'][$lname] = array($back['header'][$lname]);
				$back['header'][$lname][] = $hdr_value;
			} elseif (isset($back['header'][$lname])) {
				$back['header'][$lname][] = $hdr_value;
			} else {
				$back['header'][$lname] = $hdr_value;
			}

			$headers["$lname"] = $hdr_value;
		}

		while (list($key, $value) = each($headers)) {
			$input = $headers[$key];
			$it = array();
			if (($pos = strpos($input, ';')) !== false) {
				$it['value'] = trim(substr($input, 0, $pos));
				$input = trim(substr($input, $pos + 1));
				if (strlen($input) > 0) {
					preg_match_all('/(([[:alnum:]]+)="?([^"]*)"?\s?;?)+/i', $input, $matches);
					for ($i = 0, $icount_matches = count($matches[2]); $i < $icount_matches; $i++) {
						$it['other'][strtolower($matches[2][$i])] = $matches[3][$i];
					}
				}
			} else {
				$it['value'] = trim($input);
			}

			switch ($key) {
				case 'content-type':
					$content_type = $it;
					$back['type'] = $content_type['value'];
					if (isset($content_type['other'])) {
						while (list($p_name, $p_value) = each($content_type['other'])) {
							$back['ctype_parameters'][$p_name] = $p_value;
						}
					}
								break;

				case 'content-disposition':
					$content_disposition = $it;
					$back['disposition'] = $content_disposition['value'];

					if (isset($content_disposition['other'])) {
						while (list($p_name, $p_value) = each($content_disposition['other'])) {
							$back['d_parameters'][$p_name] = $p_value;
						}
					}
								break;

				case 'content-transfer-encoding':
					$content_transfer_encoding = $it;
								break;
			}
		}

		if (isset($content_type)) {
			$type = 'text';
			switch (strtolower($content_type['value'])) {
				case 'text/html':
					$type = 'html';

				case 'text/plain':
					if (!empty($content_disposition) && $content_disposition['value'] == 'attachment') {
						$back['attachments'][] = $back['d_parameters'];
					}
					$encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
					$back['body'] = mime::decodeBody($body, $encoding);
					if ( array_key_exists('ctype_parameters', $back)
							and isset($back['ctype_parameters'])
							and $back['ctype_parameters']
							and (!isset($back['ctype_parameters']['charset']) or strtolower($back['ctype_parameters']['charset']) == 'iso-8858-1')
							and function_exists('utf8_encode')
					) {
						$back[$type][] = utf8_encode($back['body']);
					} elseif ( array_key_exists('ctype_parameters', $back)
										and isset($back['ctype_parameters'])
										and $back['ctype_parameters']
										and strtolower($back['ctype_parameters']['charset']) != 'utf-8'
										and function_exists('mb_convert_encoding')
					) {
					$back[$type][] = mb_convert_encoding($back['body'], 'utf-8', $back['ctype_parameters']['charset']);
					} else {
						$back[$type][] = $back['body'];
					}
								break;

				case 'multipart/signed':
				case 'multipart/digest':
				case 'multipart/alternative':
				case 'multipart/related':
				case 'multipart/mixed':
					$default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';
					$tmp = explode('--' . $content_type['other']['boundary'], $body);
					for ($i = 1, $icount_tmp = count($tmp); $i < $icount_tmp - 1; $i++) {
						$parts[] = $tmp[$i];
					}

					for ($i = 0, $icount_parts = count($parts); $i < $icount_parts; $i++) {
						$back['parts'][] = mime::decode($parts[$i], $default_ctype);
					}
								break;

				case 'message/rfc822':
					$back['parts'][] = mime::decode($body);
								break;

				default:
					if (!isset($content_transfer_encoding['value'])) {
						$content_transfer_encoding['value'] = '7bit';
					}
					$back['body'] = mime::decodeBody($body, $content_transfer_encoding['value']);
								break;
			}
		} else {
			$back['body'] = mime::decodeBody($body);
		}
		$ctype = explode('/', $default_ctype);
		$back['ctype_primary'] = $ctype[0];
		$back['ctype_secondary'] = $ctype[1];

		return $back;
	}

	function decodeBody($input, $encoding = '7bit')
	{
		switch ($encoding) {
			case '7bit':
				return $input;
							break;

			case 'quoted-printable':
				$input = preg_replace('/=\r?\n/', '', $input);
				if (preg_match_all('/=[A-Z0-9]{2}/', $input, $matches)) {
					$matches = array_unique($matches[0]);
					foreach ($matches as $value) {
						$input = str_replace($value, chr(hexdec(substr($value, 1))), $input);
					}
				}
				return $input;

							break;

			case 'base64':
				return base64_decode($input);
							break;

			default:
				return $input;
		}
	}

	function get_bodies($output)
	{
			$bodies = array();	/* BUG: only one body for the moment */
			if (isset($output['text'][0]))
				$body = $output['text'][0];
			elseif (isset($output['parts'][0]) && isset($output['parts'][0]['text'][0]))
				$body = $output['parts'][0]['text'][0];
			elseif (isset($output['parts'][0]) && isset($output['parts'][0]['parts'][0]) && isset($output['parts'][0]['parts'][0]['text'][0]))
				$body = $output['parts'][0]['parts'][0]['text'][0];
			else
				$body = '';
			$bodies[] = $body;
			return $bodies;
	}

	function get_attachments($output)
	{
		$cnt = 0;
		$attachments = array();

		if (!isset($output['parts'])) {
			return $attachments;

		}

		$att = array();

		for ($it = 0, $itcount_output = count($output['parts']); $it < $itcount_output; $it++) {
			if (isset($output['parts'][$it]['d_parameters']['filename'])) {
				$attachmentPart = $output['parts'][$it];
				$att['part'] = $it;
				$att['name'] = $attachmentPart['d_parameters']['filename'];
				if (isset($attachmentPart['ctype_primary']))
					$att['type'] = $attachmentPart['ctype_primary'] .'/'. $attachmentPart['ctype_secondary'];
				else
					$att['type'] = '';
				$att['data'] = $attachmentPart['body'];
				$att['size'] = strlen($att['data']);
				$attachments[] = $att;
			}
		}

		return $attachments;
	}

}
