Skip to content

Commit

Permalink
Balance html tags & neutralize unsafe tags on emailed html'ed emails.
Browse files Browse the repository at this point in the history
  • Loading branch information
protich committed Mar 5, 2013
1 parent 304dff4 commit 6b53486
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 56 deletions.
59 changes: 29 additions & 30 deletions include/class.mailfetch.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@ class MailFetcher {

var $charset = 'UTF-8';
var $encodings =array('UTF-8','WINDOWS-1251', 'ISO-8859-5', 'ISO-8859-1','KOI8-R');

function MailFetcher($email, $charset='UTF-8') {


if($email && is_numeric($email)) //email_id
$email=Email::lookup($email);

if(is_object($email))
$this->ht = $email->getMailAccountInfo();
elseif(is_array($email) && $email['host']) //hashtable of mail account info
$this->ht = $email;
$this->ht = $email;
else
$this->ht = null;

$this->charset = $charset;

if($this->ht) {
Expand All @@ -59,12 +59,12 @@ function MailFetcher($email, $charset='UTF-8') {
$this->srvstr=sprintf('{%s:%d/%s', $this->getHost(), $this->getPort(), $this->getProtocol());
if(!strcasecmp($this->getEncryption(), 'SSL'))
$this->srvstr.='/ssl';

$this->srvstr.='/novalidate-cert}';

}

//Set timeouts
//Set timeouts
if(function_exists('imap_timeout')) imap_timeout(1,20);

}
Expand Down Expand Up @@ -92,7 +92,7 @@ function getEncryption() {
function getUsername() {
return $this->ht['username'];
}

function getPassword() {
return $this->ht['password'];
}
Expand All @@ -112,7 +112,7 @@ function getArchiveFolder() {
}

/* Core */

function connect() {
return ($this->mbox && $this->ping())?$this->mbox:$this->open();
}
Expand All @@ -123,7 +123,7 @@ function ping() {

/* Default folder is inbox - TODO: provide user an option to fetch from diff folder/label */
function open($box='INBOX') {

if($this->mbox)
$this->close();

Expand Down Expand Up @@ -157,7 +157,7 @@ function getMailboxes() {
function createMailbox($folder) {

if(!$folder) return false;

return imap_createmailbox($this->mbox, imap_utf7_encode($this->srvstr.trim($folder)));
}

Expand Down Expand Up @@ -187,23 +187,23 @@ function decode($text, $encoding) {
$text=imap_qprint($text);
break;
}

return $text;
}

//Convert text to desired encoding..defaults to utf8
function mime_encode($text, $charset=null, $encoding='utf-8') { //Thank in part to afterburner
function mime_encode($text, $charset=null, $encoding='utf-8') { //Thank in part to afterburner
return Format::encode($text, $charset, $encoding);
}

//Generic decoder - resulting text is utf8 encoded -> mirrors imap_utf8
function mime_decode($text, $encoding='utf-8') {

$str = '';
$parts = imap_mime_header_decode($text);
foreach ($parts as $part)
$str.= $this->mime_encode($part->text, $part->charset, $encoding);

return $str?$str:imap_utf8($text);
}

Expand All @@ -215,12 +215,12 @@ function getMimeType($struct) {
$mimeType = array('TEXT', 'MULTIPART', 'MESSAGE', 'APPLICATION', 'AUDIO', 'IMAGE', 'VIDEO', 'OTHER');
if(!$struct || !$struct->subtype)
return 'TEXT/PLAIN';

return $mimeType[(int) $struct->type].'/'.$struct->subtype;
}

function getHeaderInfo($mid) {

if(!($headerinfo=imap_headerinfo($this->mbox, $mid)) || !$headerinfo->from)
return null;

Expand All @@ -237,7 +237,7 @@ function getHeaderInfo($mid) {

//search for specific mime type parts....encoding is the desired encoding.
function getPart($mid, $mimeType, $encoding=false, $struct=null, $partNumber=false) {

if(!$struct && $mid)
$struct=@imap_fetchstructure($this->mbox, $mid);

Expand All @@ -264,7 +264,7 @@ function getPart($mid, $mimeType, $encoding=false, $struct=null, $partNumber=fal
$text='';
if($struct && $struct->parts) {
while(list($i, $substruct) = each($struct->parts)) {
if($partNumber)
if($partNumber)
$prefix = $partNumber . '.';
if(($result=$this->getPart($mid, $mimeType, $encoding, $substruct, $prefix.($i+1))))
$text.=$result;
Expand Down Expand Up @@ -332,29 +332,28 @@ function getHeader($mid) {
return imap_fetchheader($this->mbox, $mid,FT_PREFETCHTEXT);
}


function getPriority($mid) {
return Mail_Parse::parsePriority($this->getHeader($mid));
}

function getBody($mid) {

$body ='';
if(!($body = $this->getPart($mid,'TEXT/PLAIN', $this->charset))) {
if(($body = $this->getPart($mid,'TEXT/HTML', $this->charset))) {
//Convert tags of interest before we striptags
$body=str_replace("</DIV><DIV>", "\n", $body);
$body=str_replace(array("<br>", "<br />", "<BR>", "<BR />"), "\n", $body);
$body=Format::html($body); //Balance html tags before stripping.
$body=Format::striptags($body); //Strip tags??
$body=Format::safe_html($body); //Balance html tags & neutralize unsafe tags.
}
}

return $body;
}

//email to ticket
function createTicket($mid) {
//email to ticket
function createTicket($mid) {
global $ost;

if(!($mailinfo = $this->getHeaderInfo($mid)))
Expand Down Expand Up @@ -387,7 +386,7 @@ function createTicket($mid) {

if($ost->getConfig()->useEmailPriority())
$vars['priorityId']=$this->getPriority($mid);

$ticket=null;
$newticket=true;
//Check the subject line for possible ID.
Expand All @@ -397,7 +396,7 @@ function createTicket($mid) {
if(!($ticket=Ticket::lookupByExtId($tid, $vars['email'])))
$ticket=null;
}

$errors=array();
if($ticket) {
if(!($message=$ticket->postMessage($vars, 'Email')))
Expand Down Expand Up @@ -494,11 +493,11 @@ function log($error) {
/*
MailFetcher::run()
Static function called to initiate email polling
Static function called to initiate email polling
*/
function run() {
global $ost;

if(!$ost->getConfig()->isEmailPollingEnabled())
return;

Expand All @@ -510,7 +509,7 @@ function run() {
return;
}

//Hardcoded error control...
//Hardcoded error control...
$MAXERRORS = 5; //Max errors before we start delayed fetch attempts
$TIMEOUT = 10; //Timeout in minutes after max errors is reached.

Expand Down
52 changes: 26 additions & 26 deletions include/class.mailparse.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ class.mailparse.php
require_once(PEAR_DIR.'Mail/RFC822.php');

class Mail_Parse {

var $mime_message;
var $include_bodies;
var $decode_headers;
var $decode_bodies;

var $struct;

function Mail_parse($mimeMessage,$includeBodies=true,$decodeHeaders=TRUE,$decodeBodies=TRUE){

$this->mime_message=$mimeMessage;
$this->include_bodies=$includeBodies;
$this->decode_headers=$decodeHeaders;
Expand All @@ -42,9 +42,9 @@ function decode() {
'include_bodies'=> $this->include_bodies,
'decode_headers'=> $this->decode_headers,
'decode_bodies' => $this->decode_bodies);
$this->splitBodyHeader();
$this->splitBodyHeader();
$this->struct=Mail_mimeDecode::decode($params);

return (PEAR::isError($this->struct) || !(count($this->struct->headers)>1))?FALSE:TRUE;
}

Expand Down Expand Up @@ -94,7 +94,7 @@ function splitBodyHeader() {
}
return $array;
}


function getStruct(){
return $this->struct;
Expand All @@ -109,8 +109,8 @@ function getHeader() {
function getError(){
return PEAR::isError($this->struct)?$this->struct->getMessage():'';
}


function getFromAddressList(){
return Mail_Parse::parseAddressList($this->struct->headers['from']);
}
Expand All @@ -119,35 +119,35 @@ function getToAddressList(){
//Delivered-to incase it was a BBC mail.
return Mail_Parse::parseAddressList($this->struct->headers['to']?$this->struct->headers['to']:$this->struct->headers['delivered-to']);
}

function getCcAddressList(){
return $this->struct->headers['cc']?Mail_Parse::parseAddressList($this->struct->headers['cc']):null;
}

function getMessageId(){
return $this->struct->headers['message-id'];
}

function getSubject(){
return $this->struct->headers['subject'];
}

function getBody(){

$body='';
if(!($body=$this->getPart($this->struct,'text/plain'))) {
if(($body=$this->getPart($this->struct,'text/html'))) {
//Cleanup the html.
$body=str_replace("</DIV><DIV>", "\n", $body);
$body=str_replace("</DIV><DIV>", "\n", $body);
$body=str_replace(array("<br>", "<br />", "<BR>", "<BR />"), "\n", $body);
$body=Format::striptags(Format::html($body));
$body=Format::safe_html($body); //Balance html tags & neutralize unsafe tags.
}
}
return $body;
}

function getPart($struct,$ctypepart) {

if($struct && !$struct->parts) {
$ctype = @strtolower($struct->ctype_primary.'/'.$struct->ctype_secondary);
if($ctype && strcasecmp($ctype,$ctypepart)==0)
Expand All @@ -164,7 +164,7 @@ function getPart($struct,$ctypepart) {
return $data;
}


function mime_encode($text, $charset=null, $encoding='utf-8') {
return Format::encode($text, $charset, $encoding);
}
Expand All @@ -175,15 +175,15 @@ function getAttachments($part=null){
$part=$this->getStruct();

if($part && $part->disposition
&& (!strcasecmp($part->disposition,'attachment')
|| !strcasecmp($part->disposition,'inline')
&& (!strcasecmp($part->disposition,'attachment')
|| !strcasecmp($part->disposition,'inline')
|| !strcasecmp($part->ctype_primary,'image'))){

if(!($filename=$part->d_parameters['filename']) && $part->d_parameters['filename*'])
$filename=$part->d_parameters['filename*']; //Do we need to decode?
$file=array(
'name' => $filename,
'name' => $filename,
'type' => strtolower($part->ctype_primary.'/'.$part->ctype_secondary),
'data' => $this->mime_encode($part->body, $part->ctype_parameters['charset'])
);
Expand Down Expand Up @@ -245,7 +245,7 @@ class EmailDataParser {
function EmailDataParser($stream=null) {
$this->stream = $stream;
}

function parse($stream) {

$contents ='';
Expand All @@ -260,7 +260,7 @@ function parse($stream) {
$parser= new Mail_Parse($contents);
if(!$parser->decode()) //Decode...returns false on decoding errors
return $this->err('Email parse failed ['.$parser->getError().']');

$data =array();
//FROM address: who sent the email.
if(($fromlist = $parser->getFromAddressList()) && !PEAR::isError($fromlist)) {
Expand Down Expand Up @@ -293,7 +293,7 @@ function parse($stream) {
break;
}
}

$data['subject'] = Format::utf8encode($parser->getSubject());
$data['message'] = Format::utf8encode(Format::stripEmptyLines($parser->getBody()));
$data['header'] = $parser->getHeader();
Expand Down

0 comments on commit 6b53486

Please sign in to comment.