Created
December 14, 2015 21:00
-
-
Save israelshirk/56602a00d5825db31df0 to your computer and use it in GitHub Desktop.
CodeIgniter 1.7.3 email with fix for mail() security issue in recent php 5.4/5.5/5.6. Also includes basis for unit test framework on CI 1.7.3. There's some stuff you'd need to recreate/adapt for the tests - DI, disabling pieces of the loading process, etc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |
/** | |
* CodeIgniter | |
* | |
* An open source application development framework for PHP 4.3.2 or newer | |
* | |
* @package CodeIgniter | |
* @author ExpressionEngine Dev Team | |
* @copyright Copyright (c) 2008 - 2010, EllisLab, Inc. | |
* @license http://codeigniter.com/user_guide/license.html | |
* @link http://codeigniter.com | |
* @since Version 1.0 | |
* @filesource | |
*/ | |
// ------------------------------------------------------------------------ | |
/** | |
* CodeIgniter Email Class | |
* | |
* Permits email to be sent using Mail, Sendmail, or SMTP. | |
* | |
* @package CodeIgniter | |
* @subpackage Libraries | |
* @category Libraries | |
* @author ExpressionEngine Dev Team | |
* @link http://codeigniter.com/user_guide/libraries/email.html | |
*/ | |
class CI_Email { | |
var $useragent = "CodeIgniter"; | |
var $mailpath = "/usr/sbin/sendmail"; // Sendmail path | |
var $protocol = "mail"; // mail/sendmail/smtp | |
var $smtp_host = ""; // SMTP Server. Example: mail.earthlink.net | |
var $smtp_user = ""; // SMTP Username | |
var $smtp_pass = ""; // SMTP Password | |
var $smtp_port = "25"; // SMTP Port | |
var $smtp_timeout = 5; // SMTP Timeout in seconds | |
var $wordwrap = TRUE; // TRUE/FALSE Turns word-wrap on/off | |
var $wrapchars = "76"; // Number of characters to wrap at. | |
var $mailtype = "text"; // text/html Defines email formatting | |
var $charset = "utf-8"; // Default char set: iso-8859-1 or us-ascii | |
var $multipart = "mixed"; // "mixed" (in the body) or "related" (separate) | |
var $alt_message = ''; // Alternative message for HTML emails | |
var $validate = FALSE; // TRUE/FALSE. Enables email validation | |
var $priority = "3"; // Default priority (1 - 5) | |
var $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822) | |
var $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers, | |
// even on the receiving end think they need to muck with CRLFs, so using "\n", while | |
// distasteful, is the only thing that seems to work for all environments. | |
var $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo. | |
var $bcc_batch_mode = FALSE; // TRUE/FALSE Turns on/off Bcc batch feature | |
var $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch | |
var $_safe_mode = FALSE; | |
var $_subject = ""; | |
var $_body = ""; | |
var $_finalbody = ""; | |
var $_alt_boundary = ""; | |
var $_atc_boundary = ""; | |
var $_header_str = ""; | |
var $_smtp_connect = ""; | |
var $_encoding = "8bit"; | |
var $_IP = FALSE; | |
var $_smtp_auth = FALSE; | |
var $_replyto_flag = FALSE; | |
var $_debug_msg = array(); | |
var $_recipients = array(); | |
var $_cc_array = array(); | |
var $_bcc_array = array(); | |
var $_headers = array(); | |
var $_attach_name = array(); | |
var $_attach_type = array(); | |
var $_attach_disp = array(); | |
var $_protocols = array('mail', 'sendmail', 'smtp'); | |
var $_base_charsets = array('us-ascii', 'iso-2022-'); // 7-bit charsets (excluding language suffix) | |
var $_bit_depths = array('7bit', '8bit'); | |
var $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)'); | |
/** | |
* Constructor - Sets Email Preferences | |
* | |
* The constructor can be passed an array of config values | |
*/ | |
function CI_Email($config = array()) | |
{ | |
if (count($config) > 0) | |
{ | |
$this->initialize($config); | |
} | |
else | |
{ | |
$this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; | |
$this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE; | |
} | |
log_message('debug', "Email Class Initialized"); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Initialize preferences | |
* | |
* @access public | |
* @param array | |
* @return void | |
*/ | |
function initialize($config = array()) | |
{ | |
$this->clear(); | |
foreach ($config as $key => $val) | |
{ | |
if (isset($this->$key)) | |
{ | |
$method = 'set_'.$key; | |
if (method_exists($this, $method)) | |
{ | |
$this->$method($val); | |
} | |
else | |
{ | |
$this->$key = $val; | |
} | |
} | |
} | |
$this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE; | |
$this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Initialize the Email Data | |
* | |
* @access public | |
* @return void | |
*/ | |
function clear($clear_attachments = FALSE) | |
{ | |
$this->_subject = ""; | |
$this->_body = ""; | |
$this->_finalbody = ""; | |
$this->_header_str = ""; | |
$this->_replyto_flag = FALSE; | |
$this->_recipients = array(); | |
$this->_headers = array(); | |
$this->_debug_msg = array(); | |
$this->_set_header('User-Agent', $this->useragent); | |
$this->_set_header('Date', $this->_set_date()); | |
if ($clear_attachments !== FALSE) | |
{ | |
$this->_attach_name = array(); | |
$this->_attach_type = array(); | |
$this->_attach_disp = array(); | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set FROM | |
* | |
* @access public | |
* @param string | |
* @param string | |
* @return void | |
*/ | |
function from($from, $name = '') | |
{ | |
if (preg_match( '/\<(.*)\>/', $from, $match)) | |
{ | |
$from = $match['1']; | |
} | |
if ($this->validate) | |
{ | |
$this->validate_email($this->_str_to_array($from)); | |
} | |
// prepare the display name | |
if ($name != '') | |
{ | |
// only use Q encoding if there are characters that would require it | |
if ( ! preg_match('/[\200-\377]/', $name)) | |
{ | |
// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes | |
$name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"'; | |
} | |
else | |
{ | |
$name = $this->_prep_q_encoding($name, TRUE); | |
} | |
} | |
$this->_set_header('From', $name.' <'.$from.'>'); | |
$this->_set_header('Return-Path', '<'.$from.'>'); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Reply-to | |
* | |
* @access public | |
* @param string | |
* @param string | |
* @return void | |
*/ | |
function reply_to($replyto, $name = '') | |
{ | |
if (preg_match( '/\<(.*)\>/', $replyto, $match)) | |
{ | |
$replyto = $match['1']; | |
} | |
if ($this->validate) | |
{ | |
$this->validate_email($this->_str_to_array($replyto)); | |
} | |
if ($name == '') | |
{ | |
$name = $replyto; | |
} | |
if (strncmp($name, '"', 1) != 0) | |
{ | |
$name = '"'.$name.'"'; | |
} | |
$this->_set_header('Reply-To', $name.' <'.$replyto.'>'); | |
$this->_replyto_flag = TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Recipients | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function to($to) | |
{ | |
$to = $this->_str_to_array($to); | |
$to = $this->clean_email($to); | |
if ($this->validate) | |
{ | |
$this->validate_email($to); | |
} | |
if ($this->_get_protocol() != 'mail') | |
{ | |
$this->_set_header('To', implode(", ", $to)); | |
} | |
switch ($this->_get_protocol()) | |
{ | |
case 'smtp' : $this->_recipients = $to; | |
break; | |
case 'sendmail' : $this->_recipients = implode(", ", $to); | |
break; | |
case 'mail' : $this->_recipients = implode(", ", $to); | |
break; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set CC | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function cc($cc) | |
{ | |
$cc = $this->_str_to_array($cc); | |
$cc = $this->clean_email($cc); | |
if ($this->validate) | |
{ | |
$this->validate_email($cc); | |
} | |
$this->_set_header('Cc', implode(", ", $cc)); | |
if ($this->_get_protocol() == "smtp") | |
{ | |
$this->_cc_array = $cc; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set BCC | |
* | |
* @access public | |
* @param string | |
* @param string | |
* @return void | |
*/ | |
function bcc($bcc, $limit = '') | |
{ | |
if ($limit != '' && is_numeric($limit)) | |
{ | |
$this->bcc_batch_mode = TRUE; | |
$this->bcc_batch_size = $limit; | |
} | |
$bcc = $this->_str_to_array($bcc); | |
$bcc = $this->clean_email($bcc); | |
if ($this->validate) | |
{ | |
$this->validate_email($bcc); | |
} | |
if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size)) | |
{ | |
$this->_bcc_array = $bcc; | |
} | |
else | |
{ | |
$this->_set_header('Bcc', implode(", ", $bcc)); | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Email Subject | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function subject($subject) | |
{ | |
$subject = $this->_prep_q_encoding($subject); | |
$this->_set_header('Subject', $subject); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Body | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function message($body) | |
{ | |
$this->_body = stripslashes(rtrim(str_replace("\r", "", $body))); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Assign file attachments | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function attach($filename, $disposition = 'attachment') | |
{ | |
$this->_attach_name[] = $filename; | |
$fileNameParts = explode('.', basename($filename)); | |
$this->_attach_type[] = $this->_mime_types(next($fileNameParts)); | |
$this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Add a Header Item | |
* | |
* @access private | |
* @param string | |
* @param string | |
* @return void | |
*/ | |
function _set_header($header, $value) | |
{ | |
$this->_headers[$header] = $value; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Convert a String to an Array | |
* | |
* @access private | |
* @param string | |
* @return array | |
*/ | |
function _str_to_array($email) | |
{ | |
if ( ! is_array($email)) | |
{ | |
if (strpos($email, ',') !== FALSE) | |
{ | |
$email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY); | |
} | |
else | |
{ | |
$email = trim($email); | |
settype($email, "array"); | |
} | |
} | |
return $email; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Multipart Value | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function set_alt_message($str = '') | |
{ | |
$this->alt_message = ($str == '') ? '' : $str; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Mailtype | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function set_mailtype($type = 'text') | |
{ | |
$this->mailtype = ($type == 'html') ? 'html' : 'text'; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Wordwrap | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function set_wordwrap($wordwrap = TRUE) | |
{ | |
$this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Protocol | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function set_protocol($protocol = 'mail') | |
{ | |
$this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Priority | |
* | |
* @access public | |
* @param integer | |
* @return void | |
*/ | |
function set_priority($n = 3) | |
{ | |
if ( ! is_numeric($n)) | |
{ | |
$this->priority = 3; | |
return; | |
} | |
if ($n < 1 OR $n > 5) | |
{ | |
$this->priority = 3; | |
return; | |
} | |
$this->priority = $n; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Newline Character | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function set_newline($newline = "\n") | |
{ | |
if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r") | |
{ | |
$this->newline = "\n"; | |
return; | |
} | |
$this->newline = $newline; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set CRLF | |
* | |
* @access public | |
* @param string | |
* @return void | |
*/ | |
function set_crlf($crlf = "\n") | |
{ | |
if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r") | |
{ | |
$this->crlf = "\n"; | |
return; | |
} | |
$this->crlf = $crlf; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Message Boundary | |
* | |
* @access private | |
* @return void | |
*/ | |
function _set_boundaries() | |
{ | |
$this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative | |
$this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get the Message ID | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_message_id() | |
{ | |
$from = $this->_headers['Return-Path']; | |
$from = str_replace(">", "", $from); | |
$from = str_replace("<", "", $from); | |
return "<".uniqid('').strstr($from, '@').">"; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get Mail Protocol | |
* | |
* @access private | |
* @param bool | |
* @return string | |
*/ | |
function _get_protocol($return = TRUE) | |
{ | |
$this->protocol = strtolower($this->protocol); | |
$this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol; | |
if ($return == TRUE) | |
{ | |
return $this->protocol; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get Mail Encoding | |
* | |
* @access private | |
* @param bool | |
* @return string | |
*/ | |
function _get_encoding($return = TRUE) | |
{ | |
$this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding; | |
foreach ($this->_base_charsets as $charset) | |
{ | |
if (strncmp($charset, $this->charset, strlen($charset)) == 0) | |
{ | |
$this->_encoding = '7bit'; | |
} | |
} | |
if ($return == TRUE) | |
{ | |
return $this->_encoding; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get content type (text/html/attachment) | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_content_type() | |
{ | |
if ($this->mailtype == 'html' && count($this->_attach_name) == 0) | |
{ | |
return 'html'; | |
} | |
elseif ($this->mailtype == 'html' && count($this->_attach_name) > 0) | |
{ | |
return 'html-attach'; | |
} | |
elseif ($this->mailtype == 'text' && count($this->_attach_name) > 0) | |
{ | |
return 'plain-attach'; | |
} | |
else | |
{ | |
return 'plain'; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set RFC 822 Date | |
* | |
* @access private | |
* @return string | |
*/ | |
function _set_date() | |
{ | |
$timezone = date("Z"); | |
$operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+'; | |
$timezone = abs($timezone); | |
$timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60; | |
return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Mime message | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_mime_message() | |
{ | |
return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format."; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Validate Email Address | |
* | |
* @access public | |
* @param string | |
* @return bool | |
*/ | |
function validate_email($email) | |
{ | |
if ( ! is_array($email)) | |
{ | |
$this->_set_error_message('email_must_be_array'); | |
return FALSE; | |
} | |
foreach ($email as $val) | |
{ | |
if ( ! $this->valid_email($val)) | |
{ | |
$this->_set_error_message('email_invalid_address', $val); | |
return FALSE; | |
} | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Email Validation | |
* | |
* @access public | |
* @param string | |
* @return bool | |
*/ | |
function valid_email($address) | |
{ | |
return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Clean Extended Email Address: Joe Smith <[email protected]> | |
* | |
* @access public | |
* @param string | |
* @return string | |
*/ | |
function clean_email($email) | |
{ | |
if ( ! is_array($email)) | |
{ | |
if (preg_match('/\<(.*)\>/', $email, $match)) | |
{ | |
return $match['1']; | |
} | |
else | |
{ | |
return $email; | |
} | |
} | |
$clean_email = array(); | |
foreach ($email as $addy) | |
{ | |
if (preg_match( '/\<(.*)\>/', $addy, $match)) | |
{ | |
$clean_email[] = $match['1']; | |
} | |
else | |
{ | |
$clean_email[] = $addy; | |
} | |
} | |
return $clean_email; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Build alternative plain text message | |
* | |
* This function provides the raw message for use | |
* in plain-text headers of HTML-formatted emails. | |
* If the user hasn't specified his own alternative message | |
* it creates one by stripping the HTML | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_alt_message() | |
{ | |
if ($this->alt_message != "") | |
{ | |
return $this->word_wrap($this->alt_message, '76'); | |
} | |
if (preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match)) | |
{ | |
$body = $match['1']; | |
} | |
else | |
{ | |
$body = $this->_body; | |
} | |
$body = trim(strip_tags($body)); | |
$body = preg_replace( '#<!--(.*)--\>#', "", $body); | |
$body = str_replace("\t", "", $body); | |
for ($i = 20; $i >= 3; $i--) | |
{ | |
$n = ""; | |
for ($x = 1; $x <= $i; $x ++) | |
{ | |
$n .= "\n"; | |
} | |
$body = str_replace($n, "\n\n", $body); | |
} | |
return $this->word_wrap($body, '76'); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Word Wrap | |
* | |
* @access public | |
* @param string | |
* @param integer | |
* @return string | |
*/ | |
function word_wrap($str, $charlim = '') | |
{ | |
// Se the character limit | |
if ($charlim == '') | |
{ | |
$charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars; | |
} | |
// Reduce multiple spaces | |
$str = preg_replace("| +|", " ", $str); | |
// Standardize newlines | |
if (strpos($str, "\r") !== FALSE) | |
{ | |
$str = str_replace(array("\r\n", "\r"), "\n", $str); | |
} | |
// If the current word is surrounded by {unwrap} tags we'll | |
// strip the entire chunk and replace it with a marker. | |
$unwrap = array(); | |
if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches)) | |
{ | |
for ($i = 0; $i < count($matches['0']); $i++) | |
{ | |
$unwrap[] = $matches['1'][$i]; | |
$str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str); | |
} | |
} | |
// Use PHP's native function to do the initial wordwrap. | |
// We set the cut flag to FALSE so that any individual words that are | |
// too long get left alone. In the next step we'll deal with them. | |
$str = wordwrap($str, $charlim, "\n", FALSE); | |
// Split the string into individual lines of text and cycle through them | |
$output = ""; | |
foreach (explode("\n", $str) as $line) | |
{ | |
// Is the line within the allowed character count? | |
// If so we'll join it to the output and continue | |
if (strlen($line) <= $charlim) | |
{ | |
$output .= $line.$this->newline; | |
continue; | |
} | |
$temp = ''; | |
while((strlen($line)) > $charlim) | |
{ | |
// If the over-length word is a URL we won't wrap it | |
if (preg_match("!\[url.+\]|://|wwww.!", $line)) | |
{ | |
break; | |
} | |
// Trim the word down | |
$temp .= substr($line, 0, $charlim-1); | |
$line = substr($line, $charlim-1); | |
} | |
// If $temp contains data it means we had to split up an over-length | |
// word into smaller chunks so we'll add it back to our current line | |
if ($temp != '') | |
{ | |
$output .= $temp.$this->newline.$line; | |
} | |
else | |
{ | |
$output .= $line; | |
} | |
$output .= $this->newline; | |
} | |
// Put our markers back | |
if (count($unwrap) > 0) | |
{ | |
foreach ($unwrap as $key => $val) | |
{ | |
$output = str_replace("{{unwrapped".$key."}}", $val, $output); | |
} | |
} | |
return $output; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Build final headers | |
* | |
* @access private | |
* @param string | |
* @return string | |
*/ | |
function _build_headers() | |
{ | |
$this->_set_header('X-Sender', $this->clean_email($this->_headers['From'])); | |
$this->_set_header('X-Mailer', $this->useragent); | |
$this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]); | |
$this->_set_header('Message-ID', $this->_get_message_id()); | |
$this->_set_header('Mime-Version', '1.0'); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Write Headers as a string | |
* | |
* @access private | |
* @return void | |
*/ | |
function _write_headers() | |
{ | |
if ($this->protocol == 'mail') | |
{ | |
$this->_subject = $this->_headers['Subject']; | |
unset($this->_headers['Subject']); | |
} | |
reset($this->_headers); | |
$this->_header_str = ""; | |
foreach($this->_headers as $key => $val) | |
{ | |
$val = trim($val); | |
if ($val != "") | |
{ | |
$this->_header_str .= $key.": ".$val.$this->newline; | |
} | |
} | |
if ($this->_get_protocol() == 'mail') | |
{ | |
$this->_header_str = rtrim($this->_header_str); | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Build Final Body and attachments | |
* | |
* @access private | |
* @return void | |
*/ | |
function _build_message() | |
{ | |
if ($this->wordwrap === TRUE AND $this->mailtype != 'html') | |
{ | |
$this->_body = $this->word_wrap($this->_body); | |
} | |
$this->_set_boundaries(); | |
$this->_write_headers(); | |
$hdr = ($this->_get_protocol() == 'mail') ? $this->newline : ''; | |
// hdr2 is the set of inline headers in MIME-multipart content. | |
// The division here is necessary because of a change in behavior regarding | |
// PHP's mail() function which disallowed putting the MIME multipart | |
// stuff in the $header argument to mail() - it was a bad practice in the | |
// first place and we're basically shimming it back to sanity with minimal | |
// footprint. :/ | |
$hdr2 = ''; | |
switch ($this->_get_content_type()) | |
{ | |
case 'plain' : | |
$hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; | |
$hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding(); | |
if ($this->_get_protocol() == 'mail') | |
{ | |
$this->_header_str .= $hdr; | |
$this->_finalbody = $this->_body; | |
return; | |
} | |
$this->_header_str .= $hdr . $this->newline . $this->newline; | |
$this->_finalbody = $this->_body; | |
return; | |
break; | |
case 'html' : | |
if ($this->send_multipart === FALSE) | |
{ | |
$hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline; | |
$hdr .= "Content-Transfer-Encoding: quoted-printable"; | |
} | |
else | |
{ | |
$hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\""; | |
$hdr2 .= $this->newline . $this->newline . $this->_get_mime_message() . $this->newline . $this->newline; | |
$hdr2 .= "--" . $this->_alt_boundary . $this->newline; | |
$hdr2 .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; | |
$hdr2 .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline; | |
$hdr2 .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline; | |
$hdr2 .= "Content-Type: text/html; charset=" . $this->charset . $this->newline; | |
$hdr2 .= "Content-Transfer-Encoding: quoted-printable"; | |
} | |
$this->_body = $this->_prep_quoted_printable($this->_body); | |
$hdr2 .= $this->newline . $this->newline; | |
if ($this->_get_protocol() == 'mail') | |
{ | |
$this->_header_str .= $hdr; | |
$this->_finalbody = $hdr2 . $this->_body . $this->newline . $this->newline; | |
if ($this->send_multipart !== FALSE) | |
{ | |
$this->_finalbody .= "--" . $this->_alt_boundary . "--"; | |
} | |
return; | |
} | |
$this->_header_str .= $hdr . $this->newline . $this->newline; | |
$hdr2 .= $this->_body . $this->newline . $this->newline; | |
if ($this->send_multipart !== FALSE) | |
{ | |
$hdr2 .= "--" . $this->_alt_boundary . "--"; | |
} | |
$this->_finalbody = $hdr2; | |
return; | |
break; | |
case 'plain-attach' : | |
$hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\""; | |
$hdr2 .= $this->newline . $this->newline . $this->_get_mime_message() . $this->newline . $this->newline; | |
$hdr2 .= "--" . $this->_atc_boundary . $this->newline; | |
$hdr2 .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; | |
$hdr2 .= "Content-Transfer-Encoding: " . $this->_get_encoding(); | |
$hdr2 .= $this->newline . $this->newline; | |
$hdr2 .= $this->_body . $this->newline . $this->newline; | |
if ($this->_get_protocol() != 'mail') { | |
$hdr .= $this->newline . $this->newline; | |
} | |
$this->_header_str .= $hdr; | |
$body = $hdr2; | |
break; | |
case 'html-attach' : | |
$hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\""; | |
$hdr2 .= $this->newline . $this->newline . $this->_get_mime_message() . $this->newline . $this->newline; | |
$hdr2 .= "--" . $this->_atc_boundary . $this->newline; | |
$hdr2 .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline; | |
$hdr2 .= "--" . $this->_alt_boundary . $this->newline; | |
$hdr2 .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline; | |
$hdr2 .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline; | |
$hdr2 .= $this->_get_alt_message() . $this->newline . $this->newline; | |
$hdr2 .= "--" . $this->_alt_boundary . $this->newline; | |
$hdr2 .= "Content-Type: text/html; charset=" . $this->charset . $this->newline; | |
$hdr2 .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline; | |
$this->_body = $this->_prep_quoted_printable($this->_body); | |
$hdr2 .= $this->_body . $this->newline . $this->newline; | |
$hdr2 .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline; | |
if ($this->_get_protocol() != 'mail') { | |
$hdr .= $this->newline . $this->newline; | |
} | |
$this->_header_str .= $hdr; | |
$body = $hdr2; | |
break; | |
} | |
$attachment = array(); | |
$z = 0; | |
for ($i=0; $i < count($this->_attach_name); $i++) | |
{ | |
$filename = $this->_attach_name[$i]; | |
$basename = basename($filename); | |
$ctype = $this->_attach_type[$i]; | |
if ( ! file_exists($filename)) | |
{ | |
$this->_set_error_message('email_attachment_missing', $filename); | |
return FALSE; | |
} | |
$h = "--".$this->_atc_boundary.$this->newline; | |
$h .= "Content-type: ".$ctype."; "; | |
$h .= "name=\"".$basename."\"".$this->newline; | |
$h .= "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline; | |
$h .= "Content-Transfer-Encoding: base64".$this->newline; | |
$attachment[$z++] = $h; | |
$file = filesize($filename) +1; | |
if ( ! $fp = fopen($filename, FOPEN_READ)) | |
{ | |
$this->_set_error_message('email_attachment_unreadable', $filename); | |
return FALSE; | |
} | |
$attachment[$z++] = chunk_split(base64_encode(fread($fp, $file))); | |
fclose($fp); | |
} | |
if ($this->_get_protocol() == 'mail') | |
{ | |
$this->_finalbody = $body . implode($this->newline, $attachment).$this->newline."--" . $this->_atc_boundary."--"; | |
return; | |
} | |
$this->_finalbody = $body . implode($this->newline, $attachment) . $this->newline."--" . $this->_atc_boundary."--"; | |
return; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Prep Quoted Printable | |
* | |
* Prepares string for Quoted-Printable Content-Transfer-Encoding | |
* Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt | |
* | |
* @access private | |
* @param string | |
* @param integer | |
* @return string | |
*/ | |
function _prep_quoted_printable($str, $charlim = '') | |
{ | |
// Set the character limit | |
// Don't allow over 76, as that will make servers and MUAs barf | |
// all over quoted-printable data | |
if ($charlim == '' OR $charlim > '76') | |
{ | |
$charlim = '76'; | |
} | |
// Reduce multiple spaces | |
$str = preg_replace("| +|", " ", $str); | |
// kill nulls | |
$str = preg_replace('/\x00+/', '', $str); | |
// Standardize newlines | |
if (strpos($str, "\r") !== FALSE) | |
{ | |
$str = str_replace(array("\r\n", "\r"), "\n", $str); | |
} | |
// We are intentionally wrapping so mail servers will encode characters | |
// properly and MUAs will behave, so {unwrap} must go! | |
$str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str); | |
// Break into an array of lines | |
$lines = explode("\n", $str); | |
$escape = '='; | |
$output = ''; | |
foreach ($lines as $line) | |
{ | |
$length = strlen($line); | |
$temp = ''; | |
// Loop through each character in the line to add soft-wrap | |
// characters at the end of a line " =\r\n" and add the newly | |
// processed line(s) to the output (see comment on $crlf class property) | |
for ($i = 0; $i < $length; $i++) | |
{ | |
// Grab the next character | |
$char = substr($line, $i, 1); | |
$ascii = ord($char); | |
// Convert spaces and tabs but only if it's the end of the line | |
if ($i == ($length - 1)) | |
{ | |
$char = ($ascii == '32' OR $ascii == '9') ? $escape.sprintf('%02s', dechex($ascii)) : $char; | |
} | |
// encode = signs | |
if ($ascii == '61') | |
{ | |
$char = $escape.strtoupper(sprintf('%02s', dechex($ascii))); // =3D | |
} | |
// If we're at the character limit, add the line to the output, | |
// reset our temp variable, and keep on chuggin' | |
if ((strlen($temp) + strlen($char)) >= $charlim) | |
{ | |
$output .= $temp.$escape.$this->crlf; | |
$temp = ''; | |
} | |
// Add the character to our temporary line | |
$temp .= $char; | |
} | |
// Add our completed line to the output | |
$output .= $temp.$this->crlf; | |
} | |
// get rid of extra CRLF tacked onto the end | |
$output = substr($output, 0, strlen($this->crlf) * -1); | |
return $output; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Prep Q Encoding | |
* | |
* Performs "Q Encoding" on a string for use in email headers. It's related | |
* but not identical to quoted-printable, so it has its own method | |
* | |
* @access public | |
* @param str | |
* @param bool // set to TRUE for processing From: headers | |
* @return str | |
*/ | |
function _prep_q_encoding($str, $from = FALSE) | |
{ | |
$str = str_replace(array("\r", "\n"), array('', ''), $str); | |
// Line length must not exceed 76 characters, so we adjust for | |
// a space, 7 extra characters =??Q??=, and the charset that we will add to each line | |
$limit = 75 - 7 - strlen($this->charset); | |
// these special characters must be converted too | |
$convert = array('_', '=', '?'); | |
if ($from === TRUE) | |
{ | |
$convert[] = ','; | |
$convert[] = ';'; | |
} | |
$output = ''; | |
$temp = ''; | |
for ($i = 0, $length = strlen($str); $i < $length; $i++) | |
{ | |
// Grab the next character | |
$char = substr($str, $i, 1); | |
$ascii = ord($char); | |
// convert ALL non-printable ASCII characters and our specials | |
if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert)) | |
{ | |
$char = '='.dechex($ascii); | |
} | |
// handle regular spaces a bit more compactly than =20 | |
if ($ascii == 32) | |
{ | |
$char = '_'; | |
} | |
// If we're at the character limit, add the line to the output, | |
// reset our temp variable, and keep on chuggin' | |
if ((strlen($temp) + strlen($char)) >= $limit) | |
{ | |
$output .= $temp.$this->crlf; | |
$temp = ''; | |
} | |
// Add the character to our temporary line | |
$temp .= $char; | |
} | |
$str = $output.$temp; | |
// wrap each line with the shebang, charset, and transfer encoding | |
// the preceding space on successive lines is required for header "folding" | |
$str = trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $str)); | |
return $str; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Send Email | |
* | |
* @access public | |
* @return bool | |
*/ | |
function send() | |
{ | |
if ($this->_replyto_flag == FALSE) | |
{ | |
$this->reply_to($this->_headers['From']); | |
} | |
if (( ! isset($this->_recipients) AND ! isset($this->_headers['To'])) AND | |
( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND | |
( ! isset($this->_headers['Cc']))) | |
{ | |
$this->_set_error_message('email_no_recipients'); | |
return FALSE; | |
} | |
$this->_build_headers(); | |
if ($this->bcc_batch_mode AND count($this->_bcc_array) > 0) | |
{ | |
if (count($this->_bcc_array) > $this->bcc_batch_size) | |
return $this->batch_bcc_send(); | |
} | |
$this->_build_message(); | |
if ( ! $this->_spool_email()) | |
{ | |
return FALSE; | |
} | |
else | |
{ | |
return TRUE; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Batch Bcc Send. Sends groups of BCCs in batches | |
* | |
* @access public | |
* @return bool | |
*/ | |
function batch_bcc_send() | |
{ | |
$float = $this->bcc_batch_size -1; | |
$set = ""; | |
$chunk = array(); | |
for ($i = 0; $i < count($this->_bcc_array); $i++) | |
{ | |
if (isset($this->_bcc_array[$i])) | |
{ | |
$set .= ", ".$this->_bcc_array[$i]; | |
} | |
if ($i == $float) | |
{ | |
$chunk[] = substr($set, 1); | |
$float = $float + $this->bcc_batch_size; | |
$set = ""; | |
} | |
if ($i == count($this->_bcc_array)-1) | |
{ | |
$chunk[] = substr($set, 1); | |
} | |
} | |
for ($i = 0; $i < count($chunk); $i++) | |
{ | |
unset($this->_headers['Bcc']); | |
unset($bcc); | |
$bcc = $this->_str_to_array($chunk[$i]); | |
$bcc = $this->clean_email($bcc); | |
if ($this->protocol != 'smtp') | |
{ | |
$this->_set_header('Bcc', implode(", ", $bcc)); | |
} | |
else | |
{ | |
$this->_bcc_array = $bcc; | |
} | |
$this->_build_message(); | |
$this->_spool_email(); | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Unwrap special elements | |
* | |
* @access private | |
* @return void | |
*/ | |
function _unwrap_specials() | |
{ | |
$this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Strip line-breaks via callback | |
* | |
* @access private | |
* @return string | |
*/ | |
function _remove_nl_callback($matches) | |
{ | |
if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE) | |
{ | |
$matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]); | |
} | |
return $matches[1]; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Spool mail to the mail server | |
* | |
* @access private | |
* @return bool | |
*/ | |
function _spool_email() | |
{ | |
$this->_unwrap_specials(); | |
switch ($this->_get_protocol()) | |
{ | |
case 'mail' : | |
if ( ! $this->_send_with_mail()) | |
{ | |
$this->_set_error_message('email_send_failure_phpmail'); | |
return FALSE; | |
} | |
break; | |
case 'sendmail' : | |
if ( ! $this->_send_with_sendmail()) | |
{ | |
$this->_set_error_message('email_send_failure_sendmail'); | |
return FALSE; | |
} | |
break; | |
case 'smtp' : | |
if ( ! $this->_send_with_smtp()) | |
{ | |
$this->_set_error_message('email_send_failure_smtp'); | |
return FALSE; | |
} | |
break; | |
} | |
$this->_set_error_message('email_sent', $this->_get_protocol()); | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Send using mail() | |
* | |
* @access private | |
* @return bool | |
*/ | |
function _send_with_mail() | |
{ | |
if ($this->_safe_mode == TRUE) | |
{ | |
if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str)) | |
{ | |
return FALSE; | |
} | |
else | |
{ | |
return TRUE; | |
} | |
} | |
else | |
{ | |
// most documentation of sendmail using the "-f" flag lacks a space after it, however | |
// we've encountered servers that seem to require it to be in place. | |
if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From']))) | |
{ | |
return FALSE; | |
} | |
else | |
{ | |
return TRUE; | |
} | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Send using Sendmail | |
* | |
* @access private | |
* @return bool | |
*/ | |
function _send_with_sendmail() | |
{ | |
$fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w'); | |
if ($fp === FALSE OR $fp === NULL) | |
{ | |
// server probably has popen disabled, so nothing we can do to get a verbose error. | |
return FALSE; | |
} | |
fputs($fp, $this->_header_str); | |
fputs($fp, $this->_finalbody); | |
$status = pclose($fp); | |
if (version_compare(PHP_VERSION, '4.2.3') == -1) | |
{ | |
$status = $status >> 8 & 0xFF; | |
} | |
if ($status != 0) | |
{ | |
$this->_set_error_message('email_exit_status', $status); | |
$this->_set_error_message('email_no_socket'); | |
return FALSE; | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Send using SMTP | |
* | |
* @access private | |
* @return bool | |
*/ | |
function _send_with_smtp() | |
{ | |
if ($this->smtp_host == '') | |
{ | |
$this->_set_error_message('email_no_hostname'); | |
return FALSE; | |
} | |
$this->_smtp_connect(); | |
$this->_smtp_authenticate(); | |
$this->_send_command('from', $this->clean_email($this->_headers['From'])); | |
foreach($this->_recipients as $val) | |
{ | |
$this->_send_command('to', $val); | |
} | |
if (count($this->_cc_array) > 0) | |
{ | |
foreach($this->_cc_array as $val) | |
{ | |
if ($val != "") | |
{ | |
$this->_send_command('to', $val); | |
} | |
} | |
} | |
if (count($this->_bcc_array) > 0) | |
{ | |
foreach($this->_bcc_array as $val) | |
{ | |
if ($val != "") | |
{ | |
$this->_send_command('to', $val); | |
} | |
} | |
} | |
$this->_send_command('data'); | |
// perform dot transformation on any lines that begin with a dot | |
$this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody)); | |
$this->_send_data('.'); | |
$reply = $this->_get_smtp_data(); | |
$this->_set_error_message($reply); | |
if (strncmp($reply, '250', 3) != 0) | |
{ | |
$this->_set_error_message('email_smtp_error', $reply); | |
return FALSE; | |
} | |
$this->_send_command('quit'); | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* SMTP Connect | |
* | |
* @access private | |
* @param string | |
* @return string | |
*/ | |
function _smtp_connect() | |
{ | |
$this->_smtp_connect = fsockopen($this->smtp_host, | |
$this->smtp_port, | |
$errno, | |
$errstr, | |
$this->smtp_timeout); | |
if( ! is_resource($this->_smtp_connect)) | |
{ | |
$this->_set_error_message('email_smtp_error', $errno." ".$errstr); | |
return FALSE; | |
} | |
$this->_set_error_message($this->_get_smtp_data()); | |
return $this->_send_command('hello'); | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Send SMTP command | |
* | |
* @access private | |
* @param string | |
* @param string | |
* @return string | |
*/ | |
function _send_command($cmd, $data = '') | |
{ | |
switch ($cmd) | |
{ | |
case 'hello' : | |
if ($this->_smtp_auth OR $this->_get_encoding() == '8bit') | |
$this->_send_data('EHLO '.$this->_get_hostname()); | |
else | |
$this->_send_data('HELO '.$this->_get_hostname()); | |
$resp = 250; | |
break; | |
case 'from' : | |
$this->_send_data('MAIL FROM:<'.$data.'>'); | |
$resp = 250; | |
break; | |
case 'to' : | |
$this->_send_data('RCPT TO:<'.$data.'>'); | |
$resp = 250; | |
break; | |
case 'data' : | |
$this->_send_data('DATA'); | |
$resp = 354; | |
break; | |
case 'quit' : | |
$this->_send_data('QUIT'); | |
$resp = 221; | |
break; | |
} | |
$reply = $this->_get_smtp_data(); | |
$this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>"; | |
if (substr($reply, 0, 3) != $resp) | |
{ | |
$this->_set_error_message('email_smtp_error', $reply); | |
return FALSE; | |
} | |
if ($cmd == 'quit') | |
{ | |
fclose($this->_smtp_connect); | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* SMTP Authenticate | |
* | |
* @access private | |
* @return bool | |
*/ | |
function _smtp_authenticate() | |
{ | |
if ( ! $this->_smtp_auth) | |
{ | |
return TRUE; | |
} | |
if ($this->smtp_user == "" AND $this->smtp_pass == "") | |
{ | |
$this->_set_error_message('email_no_smtp_unpw'); | |
return FALSE; | |
} | |
$this->_send_data('AUTH LOGIN'); | |
$reply = $this->_get_smtp_data(); | |
if (strncmp($reply, '334', 3) != 0) | |
{ | |
$this->_set_error_message('email_failed_smtp_login', $reply); | |
return FALSE; | |
} | |
$this->_send_data(base64_encode($this->smtp_user)); | |
$reply = $this->_get_smtp_data(); | |
if (strncmp($reply, '334', 3) != 0) | |
{ | |
$this->_set_error_message('email_smtp_auth_un', $reply); | |
return FALSE; | |
} | |
$this->_send_data(base64_encode($this->smtp_pass)); | |
$reply = $this->_get_smtp_data(); | |
if (strncmp($reply, '235', 3) != 0) | |
{ | |
$this->_set_error_message('email_smtp_auth_pw', $reply); | |
return FALSE; | |
} | |
return TRUE; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Send SMTP data | |
* | |
* @access private | |
* @return bool | |
*/ | |
function _send_data($data) | |
{ | |
if ( ! fwrite($this->_smtp_connect, $data . $this->newline)) | |
{ | |
$this->_set_error_message('email_smtp_data_failure', $data); | |
return FALSE; | |
} | |
else | |
{ | |
return TRUE; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get SMTP data | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_smtp_data() | |
{ | |
$data = ""; | |
while ($str = fgets($this->_smtp_connect, 512)) | |
{ | |
$data .= $str; | |
if (substr($str, 3, 1) == " ") | |
{ | |
break; | |
} | |
} | |
return $data; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get Hostname | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_hostname() | |
{ | |
return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain'; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get IP | |
* | |
* @access private | |
* @return string | |
*/ | |
function _get_ip() | |
{ | |
if ($this->_IP !== FALSE) | |
{ | |
return $this->_IP; | |
} | |
$cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE; | |
$rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE; | |
$fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE; | |
if ($cip && $rip) $this->_IP = $cip; | |
elseif ($rip) $this->_IP = $rip; | |
elseif ($cip) $this->_IP = $cip; | |
elseif ($fip) $this->_IP = $fip; | |
if (strstr($this->_IP, ',')) | |
{ | |
$x = explode(',', $this->_IP); | |
$this->_IP = end($x); | |
} | |
if ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $this->_IP)) | |
{ | |
$this->_IP = '0.0.0.0'; | |
} | |
unset($cip); | |
unset($rip); | |
unset($fip); | |
return $this->_IP; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Get Debug Message | |
* | |
* @access public | |
* @return string | |
*/ | |
function print_debugger() | |
{ | |
$msg = ''; | |
if (count($this->_debug_msg) > 0) | |
{ | |
foreach ($this->_debug_msg as $val) | |
{ | |
$msg .= $val; | |
} | |
} | |
$msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>'; | |
return $msg; | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Set Message | |
* | |
* @access private | |
* @param string | |
* @return string | |
*/ | |
function _set_error_message($msg, $val = '') | |
{ | |
$CI =& get_instance(); | |
$CI->lang->load('email'); | |
if (FALSE === ($line = $CI->lang->line($msg))) | |
{ | |
$this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />"; | |
} | |
else | |
{ | |
$this->_debug_msg[] = str_replace('%s', $val, $line)."<br />"; | |
} | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* Mime Types | |
* | |
* @access private | |
* @param string | |
* @return string | |
*/ | |
function _mime_types($ext = "") | |
{ | |
$mimes = array( 'hqx' => 'application/mac-binhex40', | |
'cpt' => 'application/mac-compactpro', | |
'doc' => 'application/msword', | |
'bin' => 'application/macbinary', | |
'dms' => 'application/octet-stream', | |
'lha' => 'application/octet-stream', | |
'lzh' => 'application/octet-stream', | |
'exe' => 'application/octet-stream', | |
'class' => 'application/octet-stream', | |
'psd' => 'application/octet-stream', | |
'so' => 'application/octet-stream', | |
'sea' => 'application/octet-stream', | |
'dll' => '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', | |
'php' => 'application/x-httpd-php', | |
'php4' => 'application/x-httpd-php', | |
'php3' => 'application/x-httpd-php', | |
'phtml' => 'application/x-httpd-php', | |
'phps' => 'application/x-httpd-php-source', | |
'js' => 'application/x-javascript', | |
'swf' => 'application/x-shockwave-flash', | |
'sit' => 'application/x-stuffit', | |
'tar' => 'application/x-tar', | |
'tgz' => 'application/x-tar', | |
'xhtml' => 'application/xhtml+xml', | |
'xht' => 'application/xhtml+xml', | |
'zip' => 'application/zip', | |
'mid' => 'audio/midi', | |
'midi' => 'audio/midi', | |
'mpga' => 'audio/mpeg', | |
'mp2' => 'audio/mpeg', | |
'mp3' => 'audio/mpeg', | |
'aif' => 'audio/x-aiff', | |
'aiff' => 'audio/x-aiff', | |
'aifc' => 'audio/x-aiff', | |
'ram' => 'audio/x-pn-realaudio', | |
'rm' => 'audio/x-pn-realaudio', | |
'rpm' => 'audio/x-pn-realaudio-plugin', | |
'ra' => 'audio/x-realaudio', | |
'rv' => 'video/vnd.rn-realvideo', | |
'wav' => 'audio/x-wav', | |
'bmp' => 'image/bmp', | |
'gif' => 'image/gif', | |
'jpeg' => 'image/jpeg', | |
'jpg' => 'image/jpeg', | |
'jpe' => 'image/jpeg', | |
'png' => 'image/png', | |
'tiff' => 'image/tiff', | |
'tif' => 'image/tiff', | |
'css' => 'text/css', | |
'html' => 'text/html', | |
'htm' => 'text/html', | |
'shtml' => 'text/html', | |
'txt' => 'text/plain', | |
'text' => 'text/plain', | |
'log' => 'text/plain', | |
'rtx' => 'text/richtext', | |
'rtf' => 'text/rtf', | |
'xml' => 'text/xml', | |
'xsl' => 'text/xml', | |
'mpeg' => 'video/mpeg', | |
'mpg' => 'video/mpeg', | |
'mpe' => 'video/mpeg', | |
'qt' => 'video/quicktime', | |
'mov' => 'video/quicktime', | |
'avi' => 'video/x-msvideo', | |
'movie' => 'video/x-sgi-movie', | |
'doc' => 'application/msword', | |
'word' => 'application/msword', | |
'xl' => 'application/excel', | |
'eml' => 'message/rfc822' | |
); | |
return ( ! isset($mimes[strtolower($ext)])) ? "application/x-unknown-content-type" : $mimes[strtolower($ext)]; | |
} | |
} | |
// END CI_Email class | |
/* End of file Email.php */ | |
/* Location: ./system/libraries/Email.php */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class EmailTest extends TestCase { | |
private $protocols = ['mail', 'sendmail', 'smtp']; | |
public function setUp() { | |
parent::setUp(); | |
require_once(BASEPATH . 'libraries/Email.php'); | |
// Some of these can take a little while....... We just prevent time from | |
// drifting from between when a mock call matcher is generated, to the time | |
// when it's called with a value from strtotime() | |
MockTime::$now = time(); | |
$this->startFramework(); | |
$this->ci = $this->noController(); | |
$this->email = \Mockery::mock('CI_Email[_send_with_mail,_send_with_sendmail,_send_with_smtp]', function($mock) { | |
$this->emailMock = $mock; | |
}); | |
DI::addInstance('CI_Email', $this->email); | |
$this->ci->load->library('email'); | |
$this->email = $this->ci->email; | |
$this->tempfile = tempnam(sys_get_temp_dir(), 'unit'); | |
@unlink($this->tempfile); | |
$this->tempfile .= ".txt"; | |
file_put_contents($this->tempfile, "attachment content here"); | |
} | |
public function tearDown() { | |
parent::tearDown(); | |
@unlink($this->tempfile); | |
} | |
private function _send() { | |
$this->email->from('Israel Shirk', '[email protected]'); | |
$this->email->to('[email protected]'); | |
$this->email->cc('[email protected]'); | |
$this->email->bcc('[email protected]'); | |
$this->email->subject('Hello there'); | |
$this->email->message('some message <div></span>'); | |
$this->email->send(); | |
$this->email->clear(true); | |
} | |
public function _headerMatcher($mailtype, $multipart, $protocol, $attachmentCount) { | |
$endHeaders = ""; | |
$to = ""; | |
$subject = ""; | |
$cc = "Cc: [email protected]\\r?\n"; | |
$bcc = "Bcc: [email protected]\\r?\n"; | |
if ($protocol === "sendmail" || $protocol === "smtp") { | |
// For sendmail and smtp we manually end the headers | |
$endHeaders = "\\r?\n\\r?\n"; | |
// sendmail and smtp expect this stuff in the headers, mail() likes | |
// to do it for you | |
$to = "To: [email protected]\\r?\n"; | |
$subject = preg_quote("Subject: =?utf-8?Q?Hello_there?=") . "\\r?\n"; | |
} | |
if ($protocol === "smtp") { | |
$bcc = ""; | |
} | |
if ($attachmentCount) { | |
$contentType = "Content-Type: multipart/mixed; boundary=\"B_ATC_[\w\d]+\""; | |
} elseif ($mailtype !== "text" && $multipart) { | |
$contentType = "Content-Type: multipart/alternative; boundary=\"B_ALT_[\w\d]+\""; | |
} elseif ($mailtype === "text") { | |
$contentType = | |
"Content-Type: text/plain; charset=utf-8\\r?\n" . | |
"Content-Transfer-Encoding: 8bit"; | |
} | |
return | |
"{^" . | |
"User-Agent: CodeIgniter\\r?\n" . | |
"Date: .+\\r?\n" . | |
"From: \"[email protected]\" <Israel Shirk>\\r?\n" . | |
"Return-Path: <Israel Shirk>\\r?\n" . // This looks wrong to me. Past scope? Unsure. Assuming gmail compensates. | |
$to . | |
$cc . | |
$bcc . | |
$subject . | |
"Reply-To: \"Israel Shirk\" <Israel Shirk>\\r?\n" . | |
"X-Sender: Israel Shirk\\r?\n" . | |
"X-Mailer: CodeIgniter\\r?\n" . | |
"X-Priority: 3 \(Normal\)\\r?\n" . | |
"Message-ID: <[\w\d]+>\\r?\n" . | |
"Mime-Version: 1.0\\r?\n" . | |
$contentType . | |
$endHeaders . | |
"$}"; | |
} | |
public function _bodyMatcher($mailtype, $multipart, $protocol, $attachmentCount) { | |
$prefix = ""; | |
$suffix = ""; | |
$attachments = ""; | |
$html = ""; | |
$alternative = ""; | |
$endAlternative = ""; | |
if ($attachmentCount && $mailtype === "html") { | |
$outerSeparator = "(--B_ATC_[\w\d]+)"; | |
$innerSeparator = "(--B_ALT_[\w\d]+)"; | |
} elseif ($attachmentCount) { | |
$outerSeparator = "(--B_ATC_[\w\d]+)"; | |
$innerSeparator = "(--B_ATC_[\w\d]+)"; | |
} else { | |
$outerSeparator = "(--B_ALT_[\w\d]+)"; | |
$innerSeparator = "(--B_ALT_[\w\d]+)"; | |
} | |
if ($mailtype === "text") { | |
$plainContent = "some message <div></span>\\r?\n"; | |
} else { | |
$plainContent = "some message\\r?\n"; | |
} | |
$plain = | |
"$innerSeparator\\r?\n" . | |
"Content-Type: text/plain; charset=utf-8\\r?\n" . | |
"Content-Transfer-Encoding: 8bit\\r?\n" . | |
"\\r?\n" . | |
$plainContent . | |
"\\r?\n" . | |
"\\r?\n"; | |
if (($mailtype === "text" && !$attachmentCount) || !$multipart) { | |
return '{^' . $prefix . 'some message <div></span>' . $suffix . '$}'; | |
} | |
if ($mailtype === "html") { | |
$html = | |
"$innerSeparator\\r?\n" . | |
"Content-Type: text/html; charset=utf-8\\r?\n" . | |
"Content-Transfer-Encoding: quoted-printable\\r?\n" . | |
"\\r?\n" . | |
"some message <div></span>\\r?\n" . | |
"\\r?\n"; | |
} | |
if ($mailtype === "html" && $attachmentCount) { | |
$alternative = | |
"$outerSeparator\\r?\n" . | |
"Content-Type: multipart/alternative; boundary=\"B_ALT_[\w\d]+\"\\r?\n" . | |
"\\r?\n"; | |
$endAlternative = | |
"$innerSeparator--\\r?\n" . | |
"\\r?\n"; | |
} | |
if ($attachmentCount) { | |
$attachments = | |
"$outerSeparator\\r?\n" . | |
"Content-type: text/plain; name=\"unit[\w\d]+.txt\"\\r?\n" . | |
"Content-Disposition: attachment;\\r?\n" . | |
"Content-Transfer-Encoding: base64\\r?\n" . | |
"\\r?\n" . | |
"YXR0YWNobWVudCBjb250ZW50IGhlcmU=\\r?\n" . | |
"\\r?\n"; | |
} | |
return | |
'{^' . | |
"\\r?\n" . | |
"\\r?\n" . | |
"This is a multi-part message in MIME format.\\r?\n" . | |
"Your email application may not support this format.\\r?\n" . | |
"\\r?\n" . | |
$alternative . | |
$plain . | |
$html . | |
$endAlternative . | |
$attachments . | |
"$outerSeparator--" . | |
'$' . | |
'}'; | |
} | |
public function validateEmail() { | |
$mailtype = $this->email->mailtype; | |
$protocol = $this->email->protocol; | |
$sendMultipart = $this->email->send_multipart; | |
$attachmentCount = count($this->email->_attach_name); | |
$recipients = $this->email->_recipients; | |
$subject = $this->email->_subject; | |
$finalbody = $this->email->_finalbody; | |
$headers = $this->email->_header_str; | |
$from = $this->email->_headers['From']; | |
$headerMatcher = $this->_headerMatcher($mailtype, $sendMultipart, $protocol, $attachmentCount); | |
$bodyMatcher = $this->_bodyMatcher($mailtype, $sendMultipart, $protocol, $attachmentCount); | |
$this->assertTrue(in_array($protocol, ['mail', 'sendmail', 'smtp'])); | |
if ($protocol === 'mail' || $protocol === 'sendmail') { | |
$this->assertSame('[email protected]', $recipients, "On mailtype $mailtype, protocol $protocol, sendMultipart $sendMultipart, destination should be [email protected]"); | |
} else { | |
$this->assertSame(['[email protected]'], $recipients, "On mailtype $mailtype, protocol $protocol, sendMultipart $sendMultipart, destination should be [[email protected]]"); | |
} | |
if ($protocol === 'mail') { | |
$this->assertSame('=?utf-8?Q?Hello_there?=', $subject, "On mailtype $mailtype, protocol $protocol, sendMultipart $sendMultipart, subject should be sane"); | |
} | |
$this->assertSame('"[email protected]" <Israel Shirk>', $from, "On mailtype $mailtype, protocol $protocol, sendMultipart $sendMultipart, from should match"); | |
$this->assertSame(preg_match($bodyMatcher, $finalbody), 1, "On mailtype $mailtype, protocol $protocol, sendMultipart $sendMultipart, Body '$finalbody' should match expression '$bodyMatcher'"); | |
$this->assertSame(preg_match($headerMatcher, $headers), 1, "On mailtype $mailtype, protocol $protocol, sendMultipart $sendMultipart, Headers '$headers' should match expression '$headerMatcher'"); | |
if ($protocol === "sendmail") { | |
$this->assertSame('/usr/sbin/sendmail', $this->email->mailpath, "mailpath should be /usr/sbin/sendmail"); | |
} | |
} | |
public function testSending() { | |
$mailTypes = [ | |
'plain', | |
'html', | |
]; | |
$this->emailMock->shouldReceive('_send_with_mail')->times(count($mailTypes))->with()->andReturnUsing([$this, 'validateEmail']); | |
$this->emailMock->shouldReceive('_send_with_sendmail')->times(count($mailTypes))->with()->andReturnUsing([$this, 'validateEmail']); | |
$this->emailMock->shouldReceive('_send_with_smtp')->times(count($mailTypes))->with()->andReturnUsing([$this, 'validateEmail']); | |
foreach ($mailTypes as $mailType) { | |
foreach ($this->protocols as $protocol) { | |
$this->email->initialize(['mailtype' => $mailType, 'wordwrap' => true, 'protocol' => $protocol]); | |
$this->email->set_protocol($protocol); | |
$this->_send(); | |
} | |
} | |
} | |
public function testSendingWithAttachments() { | |
$mailTypes = [ | |
'plain', | |
'html', | |
]; | |
$this->emailMock->shouldReceive('_send_with_mail')->times(count($mailTypes))->with()->andReturnUsing([$this, 'validateEmail']); | |
$this->emailMock->shouldReceive('_send_with_sendmail')->times(count($mailTypes))->with()->andReturnUsing([$this, 'validateEmail']); | |
$this->emailMock->shouldReceive('_send_with_smtp')->times(count($mailTypes))->with()->andReturnUsing([$this, 'validateEmail']); | |
foreach ($mailTypes as $mailType) { | |
foreach ($this->protocols as $protocol) { | |
$this->email->initialize(['mailtype' => $mailType, 'wordwrap' => true, 'protocol' => $protocol]); | |
$this->email->set_protocol($protocol); | |
$this->email->attach($this->tempfile); | |
$this->_send(); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<phpunit backupGlobals="false" | |
backupStaticAttributes="false" | |
bootstrap="tests/bootstrap.php" | |
colors="true" | |
convertErrorsToExceptions="true" | |
convertNoticesToExceptions="true" | |
convertWarningsToExceptions="true" | |
processIsolation="true" | |
stopOnFailure="false" | |
syntaxCheck="true"> | |
<testsuites> | |
<testsuite name="App test suite"> | |
<directory>./tests/</directory> | |
</testsuite> | |
</testsuites> | |
<php> | |
<env name="APP_ENV" value="testing" /> | |
<env name="CACHE_DRIVER" value="array" /> | |
<env name="SMTP_PRETEND" value="true" /> | |
</php> | |
</phpunit> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* There are a bunch of assertions on error reporting here; one of the bad patterns present in | |
* the codebase is that it shuts off errors in lots of important places - like everywhere. :/ | |
**/ | |
abstract class TestCase extends PHPUnit_Framework_TestCase { | |
private $baseStuff = array(); | |
private $frameworkStarted = false; | |
private function loadBaseLibraries() { | |
$this->baseStuff['BM'] = null; | |
$this->baseStuff['EXT'] = null; | |
$this->baseStuff['CFG'] = null; | |
$this->baseStuff['URI'] = null; | |
$this->baseStuff['RTR'] = null; | |
$this->baseStuff['OUT'] = null; | |
$this->baseStuff['IN'] = null; | |
$this->baseStuff['LANG'] = null; | |
error_reporting(E_ALL); | |
if (!defined('CI_VERSION')) { | |
define('CI_VERSION', '1.7.3'); | |
} | |
require_once(BASEPATH.'codeigniter/Common'.EXT); | |
require_once(BASEPATH.'codeigniter/Compat'.EXT); | |
require_once(APPPATH.'config/constants'.EXT); | |
} | |
protected function startFramework() { | |
$this->frameworkStarted = true; | |
$this->baseStuff['BM'] =& load_class('Benchmark'); | |
$this->baseStuff['BM']->mark('total_execution_time_start'); | |
$this->baseStuff['BM']->mark('loading_time_base_classes_start'); | |
$this->baseStuff['EXT'] =& load_class('Hooks'); | |
$this->baseStuff['EXT']->_call_hook('pre_system'); | |
$this->baseStuff['CFG'] =& load_class('Config'); | |
$this->baseStuff['URI'] =& load_class('URI'); | |
$this->baseStuff['RTR'] =& load_class('Router'); | |
$this->baseStuff['OUT'] =& load_class('Output'); | |
if ($this->baseStuff['EXT']->_call_hook('cache_override') === FALSE) | |
{ | |
if ($this->baseStuff['OUT']->_display_cache($this->baseStuff['CFG'], $this->baseStuff['URI']) == TRUE) | |
{ | |
exit; | |
} | |
} | |
$this->baseStuff['IN'] =& load_class('Input'); | |
$this->baseStuff['LANG'] =& load_class('Language'); | |
require_once(BASEPATH.'codeigniter/Base5'.EXT); | |
load_class('Controller', FALSE); | |
if ( ! file_exists(APPPATH.'controllers/'.$this->baseStuff['RTR']->fetch_directory().$this->baseStuff['RTR']->fetch_class().EXT)) | |
{ | |
throw new Exception('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'); | |
} | |
include(APPPATH.'controllers/'.$this->baseStuff['RTR']->fetch_directory().$this->baseStuff['RTR']->fetch_class().EXT); | |
// Set a mark point for benchmarking | |
$this->baseStuff['BM']->mark('loading_time_base_classes_end'); | |
} | |
protected function noController() { | |
$class = 'Controller'; | |
$this->assertTrue(class_exists($class)); | |
$this->assertSame(error_reporting(), E_ALL); | |
$this->baseStuff['EXT']->_call_hook('pre_controller'); | |
$this->baseStuff['BM']->mark('controller_execution_time_( nothing )_start'); | |
$this->baseStuff['CI'] = new $class(); | |
return $this->baseStuff['CI']; | |
} | |
protected function runController() { | |
$class = $this->baseStuff['RTR']->fetch_class(); | |
$method = $this->baseStuff['RTR']->fetch_method(); | |
if ( ! class_exists($class) | |
OR $method == 'controller' | |
OR strncmp($method, '_', 1) == 0 | |
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('Controller'))) | |
) | |
{ | |
show_404("{$class}/{$method}"); | |
} | |
$this->assertSame(error_reporting(), E_ALL); | |
$this->baseStuff['EXT']->_call_hook('pre_controller'); | |
$this->baseStuff['BM']->mark('controller_execution_time_( '.$class.' / '.$method.' )_start'); | |
$this->baseStuff['CI'] = new $class(); | |
$this->applyFrameworkTweaks(); | |
$this->assertSame(error_reporting(), E_ALL); | |
if ($this->baseStuff['RTR']->scaffolding_request === TRUE) | |
{ | |
if ($this->baseStuff['EXT']->_call_hook('scaffolding_override') === FALSE) | |
{ | |
$this->baseStuff['CI']->_ci_scaffolding(); | |
} | |
} | |
else | |
{ | |
$this->baseStuff['EXT']->_call_hook('post_controller_constructor'); | |
if (method_exists($this->baseStuff['CI'], '_remap')) | |
{ | |
$this->baseStuff['CI']->_remap($method); | |
} | |
else | |
{ | |
if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($this->baseStuff['CI'])))) | |
{ | |
show_404("{$class}/{$method}"); | |
} | |
call_user_func_array(array(&$this->baseStuff['CI'], $method), array_slice($this->baseStuff['URI']->rsegments, 2)); | |
} | |
} | |
$this->assertSame(error_reporting(), E_ALL); | |
$this->baseStuff['BM']->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); | |
$this->baseStuff['EXT']->_call_hook('post_controller'); | |
$this->assertSame(error_reporting(), E_ALL); | |
return $this->baseStuff['OUT']->get_output(); | |
} | |
protected function makeRequest($path) { | |
$this->assertSame(error_reporting(), E_ALL); | |
$_SERVER['QUERY_STRING'] = $path; | |
if (!$this->frameworkStarted) { | |
$this->startFramework(); | |
} | |
ob_start(); | |
$output = $this->runController(); | |
$stdout = ob_get_clean(); | |
return [$output, $stdout]; | |
} | |
private function shutDown() { | |
if ($this->baseStuff['EXT']) { | |
$this->baseStuff['EXT']->_call_hook('post_system'); | |
} | |
if (class_exists('CI_DB') AND isset($this->baseStuff['CI']->db)) | |
{ | |
$this->baseStuff['CI']->db->close(); | |
} | |
} | |
protected function applyFrameworkTweaks() { | |
// Default email sending stub, swap at will | |
CI_Email::$emailWatcher = function($email) { throw new Exception("Unchecked email was sent"); }; | |
} | |
public function randomString($length = 10) { | |
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; | |
$charactersLength = strlen($characters); | |
$randomString = ''; | |
for ($i = 0; $i < $length; $i++) { | |
$randomString .= $characters[rand(0, $charactersLength - 1)]; | |
} | |
return $randomString; | |
} | |
public function setUp() { | |
// Make rand() nice and repeatable so you can debug things... | |
srand(1); | |
MockTime::$now = null; | |
$this->loadBaseLibraries(); | |
$_SERVER['HTTP_HOST'] = 'test.dev'; | |
$_SERVER['REMOTE_ADDR'] = '127.0.0.1'; | |
error_reporting(E_ALL); | |
} | |
public function makeInsertValidator($fieldsToMatch, $allowEmpty = false) { | |
return function($table, $rowData) use ($fieldsToMatch, $allowEmpty) { | |
foreach ($fieldsToMatch as $field => $value) { | |
$this->assertEquals($value, $rowData['batch_id']); | |
} | |
foreach ($rowData as $field => $value) { | |
$this->assertTrue(is_scalar($value)); | |
if (!$allowEmpty) { | |
$this->assertNotEmpty($value); | |
} | |
} | |
}; | |
} | |
public function tearDown() { | |
\Mockery::close(); | |
$this->assertSame(error_reporting(), E_ALL); | |
$this->shutDown(); | |
DI::clear(); | |
if (class_exists('CI_Email')) { | |
CI_Email::$emailWatcher = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment