Version 3.4.5
This commit is contained in:
1 parent
fb6b5baabc
commit
e4478369d8
1360 files changed
+228921
-179445
No files matched your search
@@ -2,19 +2,19 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.3.4
|
||||
* IP.Board v3.4.5
|
||||
* Parse Incoming Emails
|
||||
* Last Updated: $Date: 2012-06-01 11:18:06 -0400 (Fri, 01 Jun 2012) $
|
||||
* Last Updated: $Date: 2013-05-08 17:43:20 -0400 (Wed, 08 May 2013) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: mark $
|
||||
* @author $Author: bfarber $
|
||||
* @copyright © 2010 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/company/standards.php#license
|
||||
* @package IP.Board
|
||||
* @subpackage Kernel
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 25th June 2010
|
||||
* @version $Revision: 10854 $
|
||||
* @version $Revision: 12240 $
|
||||
*/
|
||||
|
||||
class incomingEmail
|
||||
@@ -35,7 +35,7 @@ class incomingEmail
|
||||
/**
|
||||
* Debug Mode
|
||||
*/
|
||||
protected $debug_mode = FALSE;
|
||||
protected $debug_mode = false;
|
||||
|
||||
/**
|
||||
* Preferred order for alterative parts
|
||||
@@ -64,7 +64,7 @@ class incomingEmail
|
||||
$this->DB->execute();
|
||||
while ( $r = $this->DB->fetch() )
|
||||
{
|
||||
$this->types[ $r['atype_mimetype'] ][] = $r;
|
||||
$this->types[ $r['atype_extension'] ] = $r;
|
||||
}
|
||||
|
||||
/* Set our preferred format */
|
||||
@@ -97,8 +97,8 @@ class incomingEmail
|
||||
//-----------------------------------------
|
||||
|
||||
// It raises strict warnings
|
||||
@error_reporting( E_NONE );
|
||||
@ini_set( 'display_errors', 'off' );
|
||||
//@error_reporting( E_NONE );
|
||||
//@ini_set( 'display_errors', 'off' );
|
||||
|
||||
require_once ( IPS_KERNEL_PATH . 'PEAR/Mail/mimeDecode.php' );/*noLibHook*/
|
||||
$decoder = new Mail_mimeDecode( $email );
|
||||
@@ -107,7 +107,7 @@ class incomingEmail
|
||||
'decode_bodies' => TRUE,
|
||||
'decode_headers' => TRUE,
|
||||
) );
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
// Parse Headers
|
||||
//--------------------------------------
|
||||
@@ -188,11 +188,11 @@ class incomingEmail
|
||||
{
|
||||
if ( preg_match( "/.+? <(.+?)>/", $_cc, $matches ) )
|
||||
{
|
||||
$cc[] = htmlentities( $matches[1] );
|
||||
$cc[] = $matches[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$cc[] = htmlentities( trim( $_cc, '<> ' ) );
|
||||
$cc[] = trim( $_cc, '<> ' );
|
||||
}
|
||||
}
|
||||
$obj->cc = str_replace( array( '>', '<' ), '', implode( ',', $cc ) );
|
||||
@@ -201,14 +201,14 @@ class incomingEmail
|
||||
// Ignore?
|
||||
//-----------------------------------------
|
||||
|
||||
if ( !$obj->debug_mode )
|
||||
if ( !$obj->debug_mode and !$doNotRoute )
|
||||
{
|
||||
$escapedFrom = $obj->DB->addSlashes( $obj->from );
|
||||
$log = $obj->DB->buildAndFetch( array( 'select' => '*', 'from' => 'core_incoming_email_log', 'where' => "log_email='{$escapedFrom}'" ) );
|
||||
if ( $log['log_id'] )
|
||||
{
|
||||
$oneMinuteAgo = time() - 60;
|
||||
if ( $log['log_time'] > $oneMinuteAgo )
|
||||
if ( $log['log_time'] > $oneMinuteAgo && $this->settings['sixty_second_rule'] )
|
||||
{
|
||||
$ignore = TRUE;
|
||||
}
|
||||
@@ -229,29 +229,34 @@ class incomingEmail
|
||||
//-----------------------------------------
|
||||
// Now destruct the message
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
$obj->message = '';
|
||||
$obj->_parsePart( $mail );
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Purify It
|
||||
//-----------------------------------------
|
||||
|
||||
// sometimes breaks
|
||||
$obj->message = str_replace( ' ', ' ', $obj->message );
|
||||
|
||||
|
||||
/* Load */
|
||||
require_once( IPS_KERNEL_PATH . 'HTMLPurifier/HTMLPurifier.auto.php' );
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
|
||||
|
||||
/* Set Configuration */
|
||||
$config->set( 'AutoFormat.Linkify', TRUE );
|
||||
$config->set( 'Core.Encoding', IPS_DOC_CHAR_SET );
|
||||
$config->set( 'HTML.TargetBlank', TRUE );
|
||||
$config->set( 'URI.Munge', ipsRegistry::getClass('output')->buildUrl('app=nexus&module=support§ion=redirect&url=%s&key=%t&resource=%r', 'public' ) );
|
||||
$config->set( 'URI.Munge', ipsRegistry::getClass('output')->buildUrl('app=nexus&module=support§ion=redirect&url=%s&key=%t&resource=%r', 'publicNoSession' ) );
|
||||
$config->set( 'URI.MungeResources', TRUE );
|
||||
$config->set( 'URI.MungeSecretKey', md5( ipsRegistry::$settings['sql_pass'] . ipsRegistry::$settings['board_url'] . ipsRegistry::$settings['sql_database'] ) );
|
||||
|
||||
|
||||
/* Retain collapse data attribute */
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def->addAttribute( 'blockquote', 'data-author', 'CDATA' );
|
||||
$def->addAttribute( 'blockquote', 'data-collapsed', 'Number' );
|
||||
|
||||
/* Purify */
|
||||
$purifier = new HTMLPurifier( $config );
|
||||
$obj->message = $purifier->purify( $obj->message );
|
||||
@@ -381,6 +386,13 @@ class incomingEmail
|
||||
/* Some clients use uppercase, but we check by lowercase */
|
||||
$part->ctype_primary = strtolower( $part->ctype_primary );
|
||||
$part->ctype_secondary = strtolower( $part->ctype_secondary );
|
||||
|
||||
/* Make sure .txt files get attached as .txt files */
|
||||
if ( $part->ctype_primary == 'text' and $part->disposition == 'attachment' )
|
||||
{
|
||||
$part->ctype_primary = 'unknown';
|
||||
$part->ctype_secondary = 'unknown';
|
||||
}
|
||||
|
||||
/* What is this? */
|
||||
switch ( $part->ctype_primary )
|
||||
@@ -448,7 +460,7 @@ class incomingEmail
|
||||
|
||||
/* Text */
|
||||
case 'text':
|
||||
|
||||
|
||||
$body = $part->body;
|
||||
$this->original_message .= $body;
|
||||
|
||||
@@ -474,9 +486,10 @@ class incomingEmail
|
||||
}
|
||||
|
||||
// Convert
|
||||
//$body = IPSText::convertCharsets( $body, $part->ctype_parameters['charset'], IPS_DOC_CHAR_SET );
|
||||
$body = IPSText::convertCharsets( $body, $part->ctype_parameters['charset'], IPS_DOC_CHAR_SET );
|
||||
$part->ctype_parameters['charset'] = IPS_DOC_CHAR_SET;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Parse > style quotes
|
||||
//-----------------------------------------
|
||||
@@ -515,7 +528,7 @@ class incomingEmail
|
||||
if ( $quotableLine )
|
||||
{
|
||||
$this->message = substr( $this->message, 0, strrpos( $this->message, $quotableLine ) );
|
||||
$this->message .= "[quote collapse='{$quotableLine}']";
|
||||
$this->message .= "[quote collapse='1' name='" . str_replace( array( "\r", "\n" ), ' ', $quotableLine ) . "']";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -546,48 +559,48 @@ class incomingEmail
|
||||
//-----------------------------------------
|
||||
// Parse HTML block quotes
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
/* Loop */
|
||||
preg_match_all( '/<blockquote.+?>/s', $this->message, $matches );
|
||||
while ( !empty( $matches ) and !empty( $matches[0] ) )
|
||||
{
|
||||
$m = $matches[0][0];
|
||||
|
||||
|
||||
// Get all the content before the quote
|
||||
$stripped = substr( $this->message, 0, strpos( $this->message, $m ) );
|
||||
|
||||
|
||||
// Knock off any breaks or closed divs after it
|
||||
$stripped = preg_replace( '/<br.+?>/s', '', $stripped );
|
||||
$stripped = str_replace( '</div>', '', $stripped );
|
||||
|
||||
$stripped = trim( str_replace( '</div>', '', $stripped ) );
|
||||
$stripped = preg_replace( '/((<br(\s*\/)?>| )*$)/s', '', $stripped );
|
||||
|
||||
// Now scan back until we hit some other html
|
||||
$pos = strrpos( $stripped, '>' ) + 1;
|
||||
$stripped = trim( substr( $stripped, $pos ) );
|
||||
|
||||
|
||||
// If it's an acceptable header, use it
|
||||
if ( substr( $stripped, -1, 1 ) == ':' )
|
||||
{
|
||||
// Chop it out
|
||||
$this->message = substr_replace( $this->message, '', strpos( $this->message, $stripped ), strlen( $stripped ) );
|
||||
|
||||
|
||||
// We have to encode the header so future tags don't replace it
|
||||
$stripped = '{{QUOTE-ENCODE:' . base64_encode( $stripped ) . '}}';
|
||||
|
||||
// Replace the blockquote
|
||||
$this->message = substr_replace( $this->message, "[quote collapse='{$stripped}']", strpos( $this->message, $m ), strlen( $m ) );
|
||||
$this->message = substr_replace( $this->message, "[quote collapse='1' name='{$stripped}']", strpos( $this->message, $m ), strlen( $m ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace the blockquote
|
||||
// Replace the blockquote
|
||||
$this->message = substr_replace( $this->message, "[quote collapse='1']", strpos( $this->message, $m ), strlen( $m ) );
|
||||
}
|
||||
|
||||
// Do the scan again
|
||||
preg_match_all( '/<blockquote.+?>/s', $this->message, $matches );
|
||||
}
|
||||
|
||||
|
||||
/* Decode the quote headers we made */
|
||||
$this->message = preg_replace_callback( '/{{QUOTE-ENCODE:(.+?)}}/', create_function( '$m', 'return base64_decode( $m[1] );' ), $this->message );
|
||||
$this->message = preg_replace_callback( '/{{QUOTE-ENCODE:(.+?)}}/', create_function( '$m', 'return str_replace( array( "\r", "\n" ), " ", base64_decode( $m[1] ) );' ), $this->message );
|
||||
|
||||
/* Add in closing [/quote] tags */
|
||||
$this->message = preg_replace( '/<\/blockquote>/', '[/quote]', $this->message );
|
||||
@@ -608,49 +621,139 @@ class incomingEmail
|
||||
|
||||
if ( preg_match( '/-{10,}\s+(.+?)\s-{10,}/', $this->message, $matches ) )
|
||||
{
|
||||
$this->message = str_replace( $matches[0], "[quote collapse='{$matches[1]}']", $this->message );
|
||||
$this->message = str_replace( $matches[0], "[quote collapse='1']", $this->message );
|
||||
$this->message .= '[/quote]';
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Look for common quote encapsulation methods
|
||||
//-----------------------------------------
|
||||
|
||||
if( strpos( $this->message, 'OLK_SRC_BODY_SECTION' ) !== false )
|
||||
{
|
||||
if ( preg_match( '/<span id=["\']OLK_SRC_BODY_SECTION[\'"]>/ims', $this->message, $matches ) )
|
||||
{
|
||||
$this->message = str_replace( $matches[0], "[quote collapse='1']{$matches[0]}", $this->message );
|
||||
|
||||
if( strpos( $this->message, '</body>' ) !== false )
|
||||
{
|
||||
$this->message = str_replace( '</body>', "[/quote]</body>", $this->message );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->message .= '[/quote]';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( strpos( $this->message, 'MsoNormal' ) !== false ) // This must be from Outlook
|
||||
{
|
||||
if ( preg_match( '/<div style=["\'].+?border-top:.+?[\'"]>.*?<p class=["\']MsoNormal["\']>(.+)<\/div>/ims', $this->message, $matches ) )
|
||||
{
|
||||
$this->message = str_replace( $matches[0], "[quote collapse='1']{$matches[0]}[/quote]", $this->message );
|
||||
}
|
||||
}
|
||||
|
||||
// This code does work, however:
|
||||
// --Differing email clients have differing formats, so it's not reliable
|
||||
// --There can be cases where you have [quote collapse='1' name='On date, at time, so and so wrote:'] already, which results in [quote name='[quote ...]'], breaking the parsing
|
||||
/*if( preg_match( '/\bon\s+?.+?,\s*?at.+?,\s*?' . $this->settings['board_name'] . '.+?' . $this->settings['email_out'] . '.+?wrote:/ims', $this->message, $matches ) )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// If there's an opening <div> right after this, go there instead
|
||||
// but only if we're not going to strip quotes (otherwise we get a stray "blah blah said:" line)
|
||||
//-----------------------------------------
|
||||
|
||||
if( strpos( $this->message, "<div>", strpos( $this->message, $matches[0] ) ) !== false )
|
||||
{
|
||||
$matches[0] = substr( $this->message, strpos( $this->message, $matches[0] ), strpos( $this->message, "<div>", strpos( $this->message, $matches[0] ) ) - strpos( $this->message, $matches[0] ) + 5 );
|
||||
|
||||
$this->message = str_replace( $matches[0], "{$matches[0]}[quote collapse='1']", $this->message );
|
||||
$this->message = preg_replace( "/<\/div>\s*?<\/body>/", "[/quote]</div></body>", $this->message );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->message = str_replace( $matches[0], "{$matches[0]}[quote collapse='1']", $this->message );
|
||||
|
||||
if( strpos( $this->message, '</body>' ) !== false )
|
||||
{
|
||||
$this->message = str_replace( '</body>', "[/quote]</body>", $this->message );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->message .= '[/quote]';
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Are we missing any closing tags? */
|
||||
$_opening = substr_count( $this->message, '[quote ' );
|
||||
$_closing = substr_count( $this->message, '[/quote]' );
|
||||
|
||||
if( $_opening > $_closing )
|
||||
{
|
||||
for( $i = $_opening; $i < $_closing; $i++ )
|
||||
{
|
||||
$this->message .= '[/quote]';
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Parse the quote tag
|
||||
//-----------------------------------------
|
||||
|
||||
//$this->message = preg_replace( "/\[quote collapse='(.*?)'\]/ims", "<blockquote class='ipsBlockquote' data-collapsed='\\1'>", $this->message );
|
||||
//$this->message = str_replace( "[/quote]", "</blockquote>", $this->message );
|
||||
|
||||
/* Parse BBCode */
|
||||
IPSText::getTextClass('bbcode')->parse_html = 0;
|
||||
IPSText::getTextClass('bbcode')->parse_nl2br = 1;
|
||||
IPSText::getTextClass('bbcode')->parse_smilies = 1;
|
||||
IPSText::getTextClass('bbcode')->parse_bbcode = 1;
|
||||
IPSText::getTextClass('bbcode')->parsing_section = 'support';
|
||||
|
||||
$this->message = IPSText::getTextClass('bbcode')->parseSingleBbcodes( $this->message, 'display', 'quote' );
|
||||
|
||||
return;
|
||||
|
||||
/* Attachments */
|
||||
default:
|
||||
|
||||
if ( $part->ctype_primary == '_text' )
|
||||
{
|
||||
$part->ctype_primary = 'text';
|
||||
}
|
||||
|
||||
$mime = "{$part->ctype_primary}/{$part->ctype_secondary}";
|
||||
|
||||
$content = "{ATTACHMENT WITH INCOMPATIBLE MIME TYPE: {$mime}}";
|
||||
$name = $part->ctype_parameters['name'] ? $part->ctype_parameters['name'] : $part->d_parameters['filename'];
|
||||
$name_parts = explode( '.', $name );
|
||||
$ext = array_pop( $name_parts );
|
||||
|
||||
if ( isset( $this->types[ $mime ] ) )
|
||||
$content = "{ATTACHMENT WITH EXTENSION: {$ext}}";
|
||||
|
||||
if ( isset( $this->types[ $ext ] ) and $this->types[ $ext ]['atype_post'] )
|
||||
{
|
||||
foreach ( $this->types[ $mime ] as $data )
|
||||
/* Create the file */
|
||||
$masked_name = md5( uniqid( 'email' ) ) . "-{$name}";
|
||||
while ( is_file( $this->settings['upload_dir'] . "/{$masked_name}" ) )
|
||||
{
|
||||
$name_parts = explode( '.', $part->ctype_parameters['name'] );
|
||||
$ext = array_pop( $name_parts );
|
||||
if ( strtolower( $data['atype_extension'] ) == strtolower( $ext ) and $data['atype_post'] )
|
||||
{
|
||||
/* Create the file */
|
||||
$masked_name = md5( uniqid( 'email' ) ) . "-{$part->ctype_parameters['name']}";
|
||||
while ( is_file( $this->settings['upload_dir'] . "/{$masked_name}" ) )
|
||||
{
|
||||
$masked_name = md5( uniqid( 'email' ) . microtime() ) . "-{$part->ctype_parameters['name']}";
|
||||
}
|
||||
file_put_contents( $this->settings['upload_dir'] . "/{$masked_name}", $part->body );
|
||||
|
||||
/* Store attachment data */
|
||||
$this->akey++;
|
||||
$this->attachments[ $this->akey ] = array(
|
||||
'attach_ext' => $ext,
|
||||
'attach_file' => $part->ctype_parameters['name'],
|
||||
'attach_location' => $masked_name,
|
||||
'attach_is_image' => ( $part->ctype_primary == 'image' ) ? 1 : 0,
|
||||
'attach_date' => time(),
|
||||
'attach_filesize' => $part->d_parameters['size'],
|
||||
);
|
||||
$content = "{ATTACHMENT:{$this->akey}}";
|
||||
break;
|
||||
}
|
||||
$masked_name = md5( uniqid( 'email' ) . microtime() ) . "-{$name}";
|
||||
}
|
||||
file_put_contents( $this->settings['upload_dir'] . "/{$masked_name}", $part->body );
|
||||
|
||||
/* Store attachment data */
|
||||
$this->akey++;
|
||||
$this->attachments[ $this->akey ] = array(
|
||||
'attach_ext' => $ext,
|
||||
'attach_file' => $name,
|
||||
'attach_location' => $masked_name,
|
||||
'attach_is_image' => ( $part->ctype_primary == 'image' ) ? 1 : 0,
|
||||
'attach_date' => time(),
|
||||
'attach_filesize' => $part->d_parameters['size'],
|
||||
);
|
||||
$content = "{ATTACHMENT:{$this->akey}}";
|
||||
break;
|
||||
}
|
||||
|
||||
$addedContent = FALSE;
|
||||
|
||||
Reference in new issue
Block a user