summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Allard <derek.allard@ellislab.com>2008-11-06 14:36:44 +0100
committerDerek Allard <derek.allard@ellislab.com>2008-11-06 14:36:44 +0100
commitb5ce5aa366937163da47074ac1da430953d34660 (patch)
treeebb0c0f8ae039fc9f2d3ca4dfc6196ddaf7b5e67
parent5f02da0fccd2123b82dc79053e6c86c2918cf37b (diff)
corrected a few docblock comments to accurately reflect return values
removed some unneeded whitespace
-rw-r--r--system/libraries/Email.php3906
-rw-r--r--system/libraries/Ftp.php1234
-rw-r--r--system/libraries/Hooks.php450
-rw-r--r--system/libraries/Image_lib.php3092
-rw-r--r--system/libraries/Language.php245
-rw-r--r--system/libraries/Session.php1514
-rw-r--r--user_guide/changelog.html3
7 files changed, 5224 insertions, 5220 deletions
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index e9a5344fe..ac9688247 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -1,1953 +1,1955 @@
-<?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, 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));
- }
-
- if ($name != '' && strncmp($name, '"', 1) != 0)
- {
- $name = '"'.$name.'"';
- }
-
- $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)
- {
- if (strpos($subject, "\r") !== FALSE OR strpos($subject, "\n") !== FALSE)
- {
- $subject = str_replace(array("\r\n", "\r", "\n"), '', $subject);
- }
-
- if (strpos($subject, "\t"))
- {
- $subject = str_replace("\t", ' ', $subject);
- }
-
- $this->_set_header('Subject', trim($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 string
- */
- function attach($filename, $disposition = 'attachment')
- {
- $this->_attach_name[] = $filename;
- $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
- $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;
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * 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 <joe@smith.com>
- *
- * @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 = substr($this->_header_str, 0, -1);
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * 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 : '';
-
- 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;
- }
-
- $hdr .= $this->newline . $this->newline . $this->_body;
-
- $this->_finalbody = $hdr;
- 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 . "\"" . $this->newline;
- $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
- $hdr .= "--" . $this->_alt_boundary . $this->newline;
-
- $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
- $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
- $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
-
- $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
- $hdr .= "Content-Transfer-Encoding: quoted-printable";
- }
-
- $this->_body = $this->_prep_quoted_printable($this->_body);
-
- if ($this->_get_protocol() == 'mail')
- {
- $this->_header_str .= $hdr;
- $this->_finalbody = $this->_body . $this->newline . $this->newline;
-
- if ($this->send_multipart !== FALSE)
- {
- $this->_finalbody .= "--" . $this->_alt_boundary . "--";
- }
-
- return;
- }
-
- $hdr .= $this->newline . $this->newline;
- $hdr .= $this->_body . $this->newline . $this->newline;
-
- if ($this->send_multipart !== FALSE)
- {
- $hdr .= "--" . $this->_alt_boundary . "--";
- }
-
- $this->_finalbody = $hdr;
- return;
-
- break;
- case 'plain-attach' :
-
- $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
- $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
- $hdr .= "--" . $this->_atc_boundary . $this->newline;
-
- $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;
-
- $body = $this->_body . $this->newline . $this->newline;
- }
-
- $hdr .= $this->newline . $this->newline;
- $hdr .= $this->_body . $this->newline . $this->newline;
-
- break;
- case 'html-attach' :
-
- $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
- $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
- $hdr .= "--" . $this->_atc_boundary . $this->newline;
-
- $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
- $hdr .= "--" . $this->_alt_boundary . $this->newline;
-
- $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
- $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
- $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
-
- $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
- $hdr .= "Content-Transfer-Encoding: quoted-printable";
-
- $this->_body = $this->_prep_quoted_printable($this->_body);
-
- if ($this->_get_protocol() == 'mail')
- {
- $this->_header_str .= $hdr;
-
- $body = $this->_body . $this->newline . $this->newline;
- $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
- }
-
- $hdr .= $this->newline . $this->newline;
- $hdr .= $this->_body . $this->newline . $this->newline;
- $hdr .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
-
- 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 = $hdr.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;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * 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 ( ! is_resource($fp))
- {
- $this->_set_error_message('email_no_socket');
- return FALSE;
- }
-
- fputs($fp, $this->_header_str);
- fputs($fp, $this->_finalbody);
- pclose($fp) >> 8 & 0xFF;
-
- 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 */
+<?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, 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));
+ }
+
+ if ($name != '' && strncmp($name, '"', 1) != 0)
+ {
+ $name = '"'.$name.'"';
+ }
+
+ $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)
+ {
+ if (strpos($subject, "\r") !== FALSE OR strpos($subject, "\n") !== FALSE)
+ {
+ $subject = str_replace(array("\r\n", "\r", "\n"), '', $subject);
+ }
+
+ if (strpos($subject, "\t"))
+ {
+ $subject = str_replace("\t", ' ', $subject);
+ }
+
+ $this->_set_header('Subject', trim($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;
+ $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
+ $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 <joe@smith.com>
+ *
+ * @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 = substr($this->_header_str, 0, -1);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 : '';
+
+ 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;
+ }
+
+ $hdr .= $this->newline . $this->newline . $this->_body;
+
+ $this->_finalbody = $hdr;
+ 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 . "\"" . $this->newline;
+ $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
+ $hdr .= "--" . $this->_alt_boundary . $this->newline;
+
+ $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
+ $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
+ $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
+
+ $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
+ $hdr .= "Content-Transfer-Encoding: quoted-printable";
+ }
+
+ $this->_body = $this->_prep_quoted_printable($this->_body);
+
+ if ($this->_get_protocol() == 'mail')
+ {
+ $this->_header_str .= $hdr;
+ $this->_finalbody = $this->_body . $this->newline . $this->newline;
+
+ if ($this->send_multipart !== FALSE)
+ {
+ $this->_finalbody .= "--" . $this->_alt_boundary . "--";
+ }
+
+ return;
+ }
+
+ $hdr .= $this->newline . $this->newline;
+ $hdr .= $this->_body . $this->newline . $this->newline;
+
+ if ($this->send_multipart !== FALSE)
+ {
+ $hdr .= "--" . $this->_alt_boundary . "--";
+ }
+
+ $this->_finalbody = $hdr;
+ return;
+
+ break;
+ case 'plain-attach' :
+
+ $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
+ $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
+ $hdr .= "--" . $this->_atc_boundary . $this->newline;
+
+ $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;
+
+ $body = $this->_body . $this->newline . $this->newline;
+ }
+
+ $hdr .= $this->newline . $this->newline;
+ $hdr .= $this->_body . $this->newline . $this->newline;
+
+ break;
+ case 'html-attach' :
+
+ $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline;
+ $hdr .= $this->_get_mime_message() . $this->newline . $this->newline;
+ $hdr .= "--" . $this->_atc_boundary . $this->newline;
+
+ $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
+ $hdr .= "--" . $this->_alt_boundary . $this->newline;
+
+ $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
+ $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
+ $hdr .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
+
+ $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
+ $hdr .= "Content-Transfer-Encoding: quoted-printable";
+
+ $this->_body = $this->_prep_quoted_printable($this->_body);
+
+ if ($this->_get_protocol() == 'mail')
+ {
+ $this->_header_str .= $hdr;
+
+ $body = $this->_body . $this->newline . $this->newline;
+ $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
+ }
+
+ $hdr .= $this->newline . $this->newline;
+ $hdr .= $this->_body . $this->newline . $this->newline;
+ $hdr .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
+
+ 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 = $hdr.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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 ( ! is_resource($fp))
+ {
+ $this->_set_error_message('email_no_socket');
+ return FALSE;
+ }
+
+ fputs($fp, $this->_header_str);
+ fputs($fp, $this->_finalbody);
+ pclose($fp) >> 8 & 0xFF;
+
+ 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 */ \ No newline at end of file
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index 0e3dd5ef9..ec84eb0a7 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -1,618 +1,618 @@
-<?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, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
- * @filesource
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * FTP Class
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Libraries
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/libraries/ftp.html
- */
-class CI_FTP {
-
- var $hostname = '';
- var $username = '';
- var $password = '';
- var $port = 21;
- var $passive = TRUE;
- var $debug = FALSE;
- var $conn_id = FALSE;
-
-
- /**
- * Constructor - Sets Preferences
- *
- * The constructor can be passed an array of config values
- */
- function CI_FTP($config = array())
- {
- if (count($config) > 0)
- {
- $this->initialize($config);
- }
-
- log_message('debug', "FTP Class Initialized");
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Initialize preferences
- *
- * @access public
- * @param array
- * @return void
- */
- function initialize($config = array())
- {
- foreach ($config as $key => $val)
- {
- if (isset($this->$key))
- {
- $this->$key = $val;
- }
- }
-
- // Prep the hostname
- $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * FTP Connect
- *
- * @access public
- * @param array the connection values
- * @return bool
- */
- function connect($config = array())
- {
- if (count($config) > 0)
- {
- $this->initialize($config);
- }
-
- if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_connect');
- }
- return FALSE;
- }
-
- if ( ! $this->_login())
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_login');
- }
- return FALSE;
- }
-
- // Set passive mode if needed
- if ($this->passive == TRUE)
- {
- ftp_pasv($this->conn_id, TRUE);
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * FTP Login
- *
- * @access private
- * @return bool
- */
- function _login()
- {
- return @ftp_login($this->conn_id, $this->username, $this->password);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Validates the connection ID
- *
- * @access private
- * @return bool
- */
- function _is_conn()
- {
- if ( ! is_resource($this->conn_id))
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_no_connection');
- }
- return FALSE;
- }
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Change direcotry
- *
- * The second parameter lets us momentarily turn off debugging so that
- * this function can be used to test for the existance of a folder
- * without throwing an error. There's no FTP equivalent to is_dir()
- * so we do it by trying to change to a particular directory.
- * Internally, this paramter is only used by the "mirror" function below.
- *
- * @access public
- * @param string
- * @param bool
- * @return bool
- */
- function changedir($path = '', $supress_debug = FALSE)
- {
- if ($path == '' OR ! $this->_is_conn())
- {
- return FALSE;
- }
-
- $result = @ftp_chdir($this->conn_id, $path);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE AND $supress_debug == FALSE)
- {
- $this->_error('ftp_unable_to_changedir');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create a directory
- *
- * @access public
- * @param string
- * @return bool
- */
- function mkdir($path = '', $permissions = NULL)
- {
- if ($path == '' OR ! $this->_is_conn())
- {
- return FALSE;
- }
-
- $result = @ftp_mkdir($this->conn_id, $path);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_makdir');
- }
- return FALSE;
- }
-
- // Set file permissions if needed
- if ( ! is_null($permissions))
- {
- $this->chmod($path, (int)$permissions);
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Upload a file to the server
- *
- * @access public
- * @param string
- * @param string
- * @param string
- * @return bool
- */
- function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- if ( ! file_exists($locpath))
- {
- $this->_error('ftp_no_source_file');
- return FALSE;
- }
-
- // Set the mode if not specified
- if ($mode == 'auto')
- {
- // Get the file extension so we can set the upload type
- $ext = $this->_getext($locpath);
- $mode = $this->_settype($ext);
- }
-
- $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
-
- $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_upload');
- }
- return FALSE;
- }
-
- // Set file permissions if needed
- if ( ! is_null($permissions))
- {
- $this->chmod($rempath, (int)$permissions);
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Rename (or move) a file
- *
- * @access public
- * @param string
- * @param string
- * @param bool
- * @return bool
- */
- function rename($old_file, $new_file, $move = FALSE)
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- $result = @ftp_rename($this->conn_id, $old_file, $new_file);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE)
- {
- $msg = ($move == FALSE) ? 'ftp_unable_to_rename' : 'ftp_unable_to_move';
-
- $this->_error($msg);
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Move a file
- *
- * @access public
- * @param string
- * @param string
- * @return bool
- */
- function move($old_file, $new_file)
- {
- return $this->rename($old_file, $new_file, TRUE);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Rename (or move) a file
- *
- * @access public
- * @param string
- * @return bool
- */
- function delete_file($filepath)
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- $result = @ftp_delete($this->conn_id, $filepath);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_delete');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete a folder and recursively delete everything (including sub-folders)
- * containted within it.
- *
- * @access public
- * @param string
- * @return bool
- */
- function delete_dir($filepath)
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- // Add a trailing slash to the file path if needed
- $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
-
- $list = $this->list_files($filepath);
-
- if ($list !== FALSE AND count($list) > 0)
- {
- foreach ($list as $item)
- {
- // If we can't delete the item it's probaly a folder so
- // we'll recursively call delete_dir()
- if ( ! @ftp_delete($this->conn_id, $item))
- {
- $this->delete_dir($item);
- }
- }
- }
-
- $result = @ftp_rmdir($this->conn_id, $filepath);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_delete');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Set file permissions
- *
- * @access public
- * @param string the file path
- * @param string the permissions
- * @return bool
- */
- function chmod($path, $perm)
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- // Permissions can only be set when running PHP 5
- if ( ! function_exists('ftp_chmod'))
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_chmod');
- }
- return FALSE;
- }
-
- $result = @ftp_chmod($this->conn_id, $perm, $path);
-
- if ($result === FALSE)
- {
- if ($this->debug == TRUE)
- {
- $this->_error('ftp_unable_to_chmod');
- }
- return FALSE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * FTP List files in the specified directory
- *
- * @access public
- * @return array
- */
- function list_files($path = '.')
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- return ftp_nlist($this->conn_id, $path);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Read a directory and recreate it remotely
- *
- * This function recursively reads a folder and everything it contains (including
- * sub-folders) and creates a mirror via FTP based on it. Whatever the directory structure
- * of the original file path will be recreated on the server.
- *
- * @access public
- * @param string path to source with trailing slash
- * @param string path to destination - include the base folder with trailing slash
- * @return bool
- */
- function mirror($locpath, $rempath)
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- // Open the local file path
- if ($fp = @opendir($locpath))
- {
- // Attempt to open the remote file path.
- if ( ! $this->changedir($rempath, TRUE))
- {
- // If it doesn't exist we'll attempt to create the direcotory
- if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
- {
- return FALSE;
- }
- }
-
- // Recursively read the local directory
- while (FALSE !== ($file = readdir($fp)))
- {
- if (@is_dir($locpath.$file) && substr($file, 0, 1) != '.')
- {
- $this->mirror($locpath.$file."/", $rempath.$file."/");
- }
- elseif (substr($file, 0, 1) != ".")
- {
- // Get the file extension so we can se the upload type
- $ext = $this->_getext($file);
- $mode = $this->_settype($ext);
-
- $this->upload($locpath.$file, $rempath.$file, $mode);
- }
- }
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- // --------------------------------------------------------------------
-
- /**
- * Extract the file extension
- *
- * @access private
- * @param string
- * @return string
- */
- function _getext($filename)
- {
- if (FALSE === strpos($filename, '.'))
- {
- return 'txt';
- }
-
- $x = explode('.', $filename);
- return end($x);
- }
-
-
- // --------------------------------------------------------------------
-
- /**
- * Set the upload type
- *
- * @access private
- * @param string
- * @return string
- */
- function _settype($ext)
- {
- $text_types = array(
- 'txt',
- 'text',
- 'php',
- 'phps',
- 'php4',
- 'js',
- 'css',
- 'htm',
- 'html',
- 'phtml',
- 'shtml',
- 'log',
- 'xml'
- );
-
-
- return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Close the connection
- *
- * @access public
- * @param string path to source
- * @param string path to destination
- * @return bool
- */
- function close()
- {
- if ( ! $this->_is_conn())
- {
- return FALSE;
- }
-
- @ftp_close($this->conn_id);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Display error message
- *
- * @access private
- * @param string
- * @return bool
- */
- function _error($line)
- {
- $CI =& get_instance();
- $CI->lang->load('ftp');
- show_error($CI->lang->line($line));
- }
-
-
-}
-// END FTP Class
-
-/* End of file Ftp.php */
+<?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, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * FTP Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author ExpressionEngine Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/ftp.html
+ */
+class CI_FTP {
+
+ var $hostname = '';
+ var $username = '';
+ var $password = '';
+ var $port = 21;
+ var $passive = TRUE;
+ var $debug = FALSE;
+ var $conn_id = FALSE;
+
+
+ /**
+ * Constructor - Sets Preferences
+ *
+ * The constructor can be passed an array of config values
+ */
+ function CI_FTP($config = array())
+ {
+ if (count($config) > 0)
+ {
+ $this->initialize($config);
+ }
+
+ log_message('debug', "FTP Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize preferences
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function initialize($config = array())
+ {
+ foreach ($config as $key => $val)
+ {
+ if (isset($this->$key))
+ {
+ $this->$key = $val;
+ }
+ }
+
+ // Prep the hostname
+ $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FTP Connect
+ *
+ * @access public
+ * @param array the connection values
+ * @return bool
+ */
+ function connect($config = array())
+ {
+ if (count($config) > 0)
+ {
+ $this->initialize($config);
+ }
+
+ if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_connect');
+ }
+ return FALSE;
+ }
+
+ if ( ! $this->_login())
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_login');
+ }
+ return FALSE;
+ }
+
+ // Set passive mode if needed
+ if ($this->passive == TRUE)
+ {
+ ftp_pasv($this->conn_id, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FTP Login
+ *
+ * @access private
+ * @return bool
+ */
+ function _login()
+ {
+ return @ftp_login($this->conn_id, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Validates the connection ID
+ *
+ * @access private
+ * @return bool
+ */
+ function _is_conn()
+ {
+ if ( ! is_resource($this->conn_id))
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_no_connection');
+ }
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Change direcotry
+ *
+ * The second parameter lets us momentarily turn off debugging so that
+ * this function can be used to test for the existance of a folder
+ * without throwing an error. There's no FTP equivalent to is_dir()
+ * so we do it by trying to change to a particular directory.
+ * Internally, this paramter is only used by the "mirror" function below.
+ *
+ * @access public
+ * @param string
+ * @param bool
+ * @return bool
+ */
+ function changedir($path = '', $supress_debug = FALSE)
+ {
+ if ($path == '' OR ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ $result = @ftp_chdir($this->conn_id, $path);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE AND $supress_debug == FALSE)
+ {
+ $this->_error('ftp_unable_to_changedir');
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create a directory
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function mkdir($path = '', $permissions = NULL)
+ {
+ if ($path == '' OR ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ $result = @ftp_mkdir($this->conn_id, $path);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_makdir');
+ }
+ return FALSE;
+ }
+
+ // Set file permissions if needed
+ if ( ! is_null($permissions))
+ {
+ $this->chmod($path, (int)$permissions);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Upload a file to the server
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @param string
+ * @return bool
+ */
+ function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ if ( ! file_exists($locpath))
+ {
+ $this->_error('ftp_no_source_file');
+ return FALSE;
+ }
+
+ // Set the mode if not specified
+ if ($mode == 'auto')
+ {
+ // Get the file extension so we can set the upload type
+ $ext = $this->_getext($locpath);
+ $mode = $this->_settype($ext);
+ }
+
+ $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
+
+ $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_upload');
+ }
+ return FALSE;
+ }
+
+ // Set file permissions if needed
+ if ( ! is_null($permissions))
+ {
+ $this->chmod($rempath, (int)$permissions);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rename (or move) a file
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @param bool
+ * @return bool
+ */
+ function rename($old_file, $new_file, $move = FALSE)
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ $result = @ftp_rename($this->conn_id, $old_file, $new_file);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE)
+ {
+ $msg = ($move == FALSE) ? 'ftp_unable_to_rename' : 'ftp_unable_to_move';
+
+ $this->_error($msg);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Move a file
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return bool
+ */
+ function move($old_file, $new_file)
+ {
+ return $this->rename($old_file, $new_file, TRUE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rename (or move) a file
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function delete_file($filepath)
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ $result = @ftp_delete($this->conn_id, $filepath);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_delete');
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete a folder and recursively delete everything (including sub-folders)
+ * containted within it.
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function delete_dir($filepath)
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ // Add a trailing slash to the file path if needed
+ $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
+
+ $list = $this->list_files($filepath);
+
+ if ($list !== FALSE AND count($list) > 0)
+ {
+ foreach ($list as $item)
+ {
+ // If we can't delete the item it's probaly a folder so
+ // we'll recursively call delete_dir()
+ if ( ! @ftp_delete($this->conn_id, $item))
+ {
+ $this->delete_dir($item);
+ }
+ }
+ }
+
+ $result = @ftp_rmdir($this->conn_id, $filepath);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_delete');
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set file permissions
+ *
+ * @access public
+ * @param string the file path
+ * @param string the permissions
+ * @return bool
+ */
+ function chmod($path, $perm)
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ // Permissions can only be set when running PHP 5
+ if ( ! function_exists('ftp_chmod'))
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_chmod');
+ }
+ return FALSE;
+ }
+
+ $result = @ftp_chmod($this->conn_id, $perm, $path);
+
+ if ($result === FALSE)
+ {
+ if ($this->debug == TRUE)
+ {
+ $this->_error('ftp_unable_to_chmod');
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FTP List files in the specified directory
+ *
+ * @access public
+ * @return array
+ */
+ function list_files($path = '.')
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ return ftp_nlist($this->conn_id, $path);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Read a directory and recreate it remotely
+ *
+ * This function recursively reads a folder and everything it contains (including
+ * sub-folders) and creates a mirror via FTP based on it. Whatever the directory structure
+ * of the original file path will be recreated on the server.
+ *
+ * @access public
+ * @param string path to source with trailing slash
+ * @param string path to destination - include the base folder with trailing slash
+ * @return bool
+ */
+ function mirror($locpath, $rempath)
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ // Open the local file path
+ if ($fp = @opendir($locpath))
+ {
+ // Attempt to open the remote file path.
+ if ( ! $this->changedir($rempath, TRUE))
+ {
+ // If it doesn't exist we'll attempt to create the direcotory
+ if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
+ {
+ return FALSE;
+ }
+ }
+
+ // Recursively read the local directory
+ while (FALSE !== ($file = readdir($fp)))
+ {
+ if (@is_dir($locpath.$file) && substr($file, 0, 1) != '.')
+ {
+ $this->mirror($locpath.$file."/", $rempath.$file."/");
+ }
+ elseif (substr($file, 0, 1) != ".")
+ {
+ // Get the file extension so we can se the upload type
+ $ext = $this->_getext($file);
+ $mode = $this->_settype($ext);
+
+ $this->upload($locpath.$file, $rempath.$file, $mode);
+ }
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Extract the file extension
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _getext($filename)
+ {
+ if (FALSE === strpos($filename, '.'))
+ {
+ return 'txt';
+ }
+
+ $x = explode('.', $filename);
+ return end($x);
+ }
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the upload type
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _settype($ext)
+ {
+ $text_types = array(
+ 'txt',
+ 'text',
+ 'php',
+ 'phps',
+ 'php4',
+ 'js',
+ 'css',
+ 'htm',
+ 'html',
+ 'phtml',
+ 'shtml',
+ 'log',
+ 'xml'
+ );
+
+
+ return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Close the connection
+ *
+ * @access public
+ * @param string path to source
+ * @param string path to destination
+ * @return bool
+ */
+ function close()
+ {
+ if ( ! $this->_is_conn())
+ {
+ return FALSE;
+ }
+
+ @ftp_close($this->conn_id);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Display error message
+ *
+ * @access private
+ * @param string
+ * @return bool
+ */
+ function _error($line)
+ {
+ $CI =& get_instance();
+ $CI->lang->load('ftp');
+ show_error($CI->lang->line($line));
+ }
+
+
+}
+// END FTP Class
+
+/* End of file Ftp.php */
/* Location: ./system/libraries/Ftp.php */ \ No newline at end of file
diff --git a/system/libraries/Hooks.php b/system/libraries/Hooks.php
index 34dd98fda..46f3ac478 100644
--- a/system/libraries/Hooks.php
+++ b/system/libraries/Hooks.php
@@ -1,226 +1,226 @@
-<?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, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
- * @filesource
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * CodeIgniter Hooks Class
- *
- * Provides a mechanism to extend the base system without hacking. Most of
- * this class is borrowed from Paul's Extension class in ExpressionEngine.
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Libraries
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/libraries/encryption.html
- */
-class CI_Hooks {
-
- var $enabled = FALSE;
- var $hooks = array();
- var $in_progress = FALSE;
-
- /**
- * Constructor
- *
- */
- function CI_Hooks()
- {
- $this->_initialize();
- log_message('debug', "Hooks Class Initialized");
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Initialize the Hooks Preferences
- *
- * @access private
- * @return void
- */
- function _initialize()
- {
- $CFG =& load_class('Config');
-
- // If hooks are not enabled in the config file
- // there is nothing else to do
-
- if ($CFG->item('enable_hooks') == FALSE)
- {
- return;
- }
-
- // Grab the "hooks" definition file.
- // If there are no hooks, we're done.
-
- @include(APPPATH.'config/hooks'.EXT);
-
- if ( ! isset($hook) OR ! is_array($hook))
- {
- return;
- }
-
- $this->hooks =& $hook;
- $this->enabled = TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Call Hook
- *
- * Calls a particular hook
- *
- * @access private
- * @param string the hook name
- * @return mixed
- */
- function _call_hook($which = '')
- {
- if ( ! $this->enabled OR ! isset($this->hooks[$which]))
- {
- return FALSE;
- }
-
- if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0]))
- {
- foreach ($this->hooks[$which] as $val)
- {
- $this->_run_hook($val);
- }
- }
- else
- {
- $this->_run_hook($this->hooks[$which]);
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Run Hook
- *
- * Runs a particular hook
- *
- * @access private
- * @param array the hook details
- * @return bool
- */
- function _run_hook($data)
- {
- if ( ! is_array($data))
- {
- return FALSE;
- }
-
- // -----------------------------------
- // Safety - Prevents run-away loops
- // -----------------------------------
-
- // If the script being called happens to have the same
- // hook call within it a loop can happen
-
- if ($this->in_progress == TRUE)
- {
- return;
- }
-
- // -----------------------------------
- // Set file path
- // -----------------------------------
-
- if ( ! isset($data['filepath']) OR ! isset($data['filename']))
- {
- return FALSE;
- }
-
- $filepath = APPPATH.$data['filepath'].'/'.$data['filename'];
-
- if ( ! file_exists($filepath))
- {
- return FALSE;
- }
-
- // -----------------------------------
- // Set class/function name
- // -----------------------------------
-
- $class = FALSE;
- $function = FALSE;
- $params = '';
-
- if (isset($data['class']) AND $data['class'] != '')
- {
- $class = $data['class'];
- }
-
- if (isset($data['function']))
- {
- $function = $data['function'];
- }
-
- if (isset($data['params']))
- {
- $params = $data['params'];
- }
-
- if ($class === FALSE AND $function === FALSE)
- {
- return FALSE;
- }
-
- // -----------------------------------
- // Set the in_progress flag
- // -----------------------------------
-
- $this->in_progress = TRUE;
-
- // -----------------------------------
- // Call the requested class and/or function
- // -----------------------------------
-
- if ($class !== FALSE)
- {
- if ( ! class_exists($class))
- {
- require($filepath);
- }
-
- $HOOK = new $class;
- $HOOK->$function($params);
- }
- else
- {
- if ( ! function_exists($function))
- {
- require($filepath);
- }
-
- $function($params);
- }
-
- $this->in_progress = FALSE;
- return TRUE;
- }
-
-}
-
-// END CI_Hooks class
-
-/* End of file Hooks.php */
+<?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, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CodeIgniter Hooks Class
+ *
+ * Provides a mechanism to extend the base system without hacking. Most of
+ * this class is borrowed from Paul's Extension class in ExpressionEngine.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author ExpressionEngine Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/encryption.html
+ */
+class CI_Hooks {
+
+ var $enabled = FALSE;
+ var $hooks = array();
+ var $in_progress = FALSE;
+
+ /**
+ * Constructor
+ *
+ */
+ function CI_Hooks()
+ {
+ $this->_initialize();
+ log_message('debug', "Hooks Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize the Hooks Preferences
+ *
+ * @access private
+ * @return void
+ */
+ function _initialize()
+ {
+ $CFG =& load_class('Config');
+
+ // If hooks are not enabled in the config file
+ // there is nothing else to do
+
+ if ($CFG->item('enable_hooks') == FALSE)
+ {
+ return;
+ }
+
+ // Grab the "hooks" definition file.
+ // If there are no hooks, we're done.
+
+ @include(APPPATH.'config/hooks'.EXT);
+
+ if ( ! isset($hook) OR ! is_array($hook))
+ {
+ return;
+ }
+
+ $this->hooks =& $hook;
+ $this->enabled = TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Call Hook
+ *
+ * Calls a particular hook
+ *
+ * @access private
+ * @param string the hook name
+ * @return mixed
+ */
+ function _call_hook($which = '')
+ {
+ if ( ! $this->enabled OR ! isset($this->hooks[$which]))
+ {
+ return FALSE;
+ }
+
+ if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0]))
+ {
+ foreach ($this->hooks[$which] as $val)
+ {
+ $this->_run_hook($val);
+ }
+ }
+ else
+ {
+ $this->_run_hook($this->hooks[$which]);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Run Hook
+ *
+ * Runs a particular hook
+ *
+ * @access private
+ * @param array the hook details
+ * @return bool
+ */
+ function _run_hook($data)
+ {
+ if ( ! is_array($data))
+ {
+ return FALSE;
+ }
+
+ // -----------------------------------
+ // Safety - Prevents run-away loops
+ // -----------------------------------
+
+ // If the script being called happens to have the same
+ // hook call within it a loop can happen
+
+ if ($this->in_progress == TRUE)
+ {
+ return;
+ }
+
+ // -----------------------------------
+ // Set file path
+ // -----------------------------------
+
+ if ( ! isset($data['filepath']) OR ! isset($data['filename']))
+ {
+ return FALSE;
+ }
+
+ $filepath = APPPATH.$data['filepath'].'/'.$data['filename'];
+
+ if ( ! file_exists($filepath))
+ {
+ return FALSE;
+ }
+
+ // -----------------------------------
+ // Set class/function name
+ // -----------------------------------
+
+ $class = FALSE;
+ $function = FALSE;
+ $params = '';
+
+ if (isset($data['class']) AND $data['class'] != '')
+ {
+ $class = $data['class'];
+ }
+
+ if (isset($data['function']))
+ {
+ $function = $data['function'];
+ }
+
+ if (isset($data['params']))
+ {
+ $params = $data['params'];
+ }
+
+ if ($class === FALSE AND $function === FALSE)
+ {
+ return FALSE;
+ }
+
+ // -----------------------------------
+ // Set the in_progress flag
+ // -----------------------------------
+
+ $this->in_progress = TRUE;
+
+ // -----------------------------------
+ // Call the requested class and/or function
+ // -----------------------------------
+
+ if ($class !== FALSE)
+ {
+ if ( ! class_exists($class))
+ {
+ require($filepath);
+ }
+
+ $HOOK = new $class;
+ $HOOK->$function($params);
+ }
+ else
+ {
+ if ( ! function_exists($function))
+ {
+ require($filepath);
+ }
+
+ $function($params);
+ }
+
+ $this->in_progress = FALSE;
+ return TRUE;
+ }
+
+}
+
+// END CI_Hooks class
+
+/* End of file Hooks.php */
/* Location: ./system/libraries/Hooks.php */ \ No newline at end of file
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 67b73096b..16201ee9e 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -1,1546 +1,1548 @@
-<?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, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
- * @filesource
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Image Manipulation class
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Image_lib
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/libraries/image_lib.html
- */
-class CI_Image_lib {
-
- var $image_library = 'gd2'; // Can be: imagemagick, netpbm, gd, gd2
- var $library_path = '';
- var $dynamic_output = FALSE; // Whether to send to browser or write to disk
- var $source_image = '';
- var $new_image = '';
- var $width = '';
- var $height = '';
- var $quality = '90';
- var $create_thumb = FALSE;
- var $thumb_marker = '_thumb';
- var $maintain_ratio = TRUE; // Whether to maintain aspect ratio when resizing or use hard values
- var $master_dim = 'auto'; // auto, height, or width. Determines what to use as the master dimension
- var $rotation_angle = '';
- var $x_axis = '';
- var $y_axis = '';
-
- // Watermark Vars
- var $wm_text = ''; // Watermark text if graphic is not used
- var $wm_type = 'text'; // Type of watermarking. Options: text/overlay
- var $wm_x_transp = 4;
- var $wm_y_transp = 4;
- var $wm_overlay_path = ''; // Watermark image path
- var $wm_font_path = ''; // TT font
- var $wm_font_size = 17; // Font size (different versions of GD will either use points or pixels)
- var $wm_vrt_alignment = 'B'; // Vertical alignment: T M B
- var $wm_hor_alignment = 'C'; // Horizontal alignment: L R C
- var $wm_padding = 0; // Padding around text
- var $wm_hor_offset = 0; // Lets you push text to the right
- var $wm_vrt_offset = 0; // Lets you push text down
- var $wm_font_color = '#ffffff'; // Text color
- var $wm_shadow_color = ''; // Dropshadow color
- var $wm_shadow_distance = 2; // Dropshadow distance
- var $wm_opacity = 50; // Image opacity: 1 - 100 Only works with image
-
- // Private Vars
- var $source_folder = '';
- var $dest_folder = '';
- var $mime_type = '';
- var $orig_width = '';
- var $orig_height = '';
- var $image_type = '';
- var $size_str = '';
- var $full_src_path = '';
- var $full_dst_path = '';
- var $create_fnc = 'imagecreatetruecolor';
- var $copy_fnc = 'imagecopyresampled';
- var $error_msg = array();
- var $wm_use_drop_shadow = FALSE;
- var $wm_use_truetype = FALSE;
-
- /**
- * Constructor
- *
- * @access public
- * @param string
- * @return void
- */
- function CI_Image_lib($props = array())
- {
- if (count($props) > 0)
- {
- $this->initialize($props);
- }
-
- log_message('debug', "Image Lib Class Initialized");
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Initialize image properties
- *
- * Resets values in case this class is used in a loop
- *
- * @access public
- * @return void
- */
- function clear()
- {
- $props = array('source_folder', 'dest_folder', 'source_image', 'full_src_path', 'full_dst_path', 'new_image', 'image_type', 'size_str', 'quality', 'orig_width', 'orig_height', 'rotation_angle', 'x_axis', 'y_axis', 'create_fnc', 'copy_fnc', 'wm_overlay_path', 'wm_use_truetype', 'dynamic_output', 'wm_font_size', 'wm_text', 'wm_vrt_alignment', 'wm_hor_alignment', 'wm_padding', 'wm_hor_offset', 'wm_vrt_offset', 'wm_font_color', 'wm_use_drop_shadow', 'wm_shadow_color', 'wm_shadow_distance', 'wm_opacity');
-
- foreach ($props as $val)
- {
- $this->$val = '';
- }
-
- // special consideration for master_dim
- $this->master_dim = 'auto';
- }
-
- // --------------------------------------------------------------------
-
- /**
- * initialize image preferences
- *
- * @access public
- * @param array
- * @return void
- */
- function initialize($props = array())
- {
- /*
- * Convert array elements into class variables
- */
- if (count($props) > 0)
- {
- foreach ($props as $key => $val)
- {
- $this->$key = $val;
- }
- }
-
- /*
- * Is there a source image?
- *
- * If not, there's no reason to continue
- *
- */
- if ($this->source_image == '')
- {
- $this->set_error('imglib_source_image_required');
- return FALSE;
- }
-
- /*
- * Is getimagesize() Available?
- *
- * We use it to determine the image properties (width/height).
- * Note: We need to figure out how to determine image
- * properties using ImageMagick and NetPBM
- *
- */
- if ( ! function_exists('getimagesize'))
- {
- $this->set_error('imglib_gd_required_for_props');
- return FALSE;
- }
-
- $this->image_library = strtolower($this->image_library);
-
- /*
- * Set the full server path
- *
- * The source image may or may not contain a path.
- * Either way, we'll try use realpath to generate the
- * full server path in order to more reliably read it.
- *
- */
- if (function_exists('realpath') AND @realpath($this->source_image) !== FALSE)
- {
- $full_source_path = str_replace("\\", "/", realpath($this->source_image));
- }
- else
- {
- $full_source_path = $this->source_image;
- }
-
- $x = explode('/', $full_source_path);
- $this->source_image = end($x);
- $this->source_folder = str_replace($this->source_image, '', $full_source_path);
-
- // Set the Image Properties
- if ( ! $this->get_image_properties($this->source_folder.$this->source_image))
- {
- return FALSE;
- }
-
- /*
- * Assign the "new" image name/path
- *
- * If the user has set a "new_image" name it means
- * we are making a copy of the source image. If not
- * it means we are altering the original. We'll
- * set the destination filename and path accordingly.
- *
- */
- if ($this->new_image == '')
- {
- $this->dest_image = $this->source_image;
- $this->dest_folder = $this->source_folder;
- }
- else
- {
- if (strpos($this->new_image, '/') === FALSE)
- {
- $this->dest_folder = $this->source_folder;
- $this->dest_image = $this->new_image;
- }
- else
- {
- if (function_exists('realpath') AND @realpath($this->new_image) !== FALSE)
- {
- $full_dest_path = str_replace("\\", "/", realpath($this->new_image));
- }
- else
- {
- $full_dest_path = $this->new_image;
- }
-
- // Is there a file name?
- if ( ! preg_match("#\.(jpg|jpeg|gif|png)$#i", $full_dest_path))
- {
- $this->dest_folder = $full_dest_path.'/';
- $this->dest_image = $this->source_image;
- }
- else
- {
- $x = explode('/', $full_dest_path);
- $this->dest_image = end($x);
- $this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);
- }
- }
- }
-
- /*
- * Compile the finalized filenames/paths
- *
- * We'll create two master strings containing the
- * full server path to the source image and the
- * full server path to the destination image.
- * We'll also split the destination image name
- * so we can insert the thumbnail marker if needed.
- *
- */
- if ($this->create_thumb === FALSE OR $this->thumb_marker == '')
- {
- $this->thumb_marker = '';
- }
-
- $xp = $this->explode_name($this->dest_image);
-
- $filename = $xp['name'];
- $file_ext = $xp['ext'];
-
- $this->full_src_path = $this->source_folder.$this->source_image;
- $this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
-
- /*
- * Should we maintain image proportions?
- *
- * When creating thumbs or copies, the target width/height
- * might not be in correct proportion with the source
- * image's width/height. We'll recalculate it here.
- *
- */
- if ($this->maintain_ratio === TRUE && ($this->width != '' AND $this->height != ''))
- {
- $this->image_reproportion();
- }
-
- /*
- * Was a width and height specified?
- *
- * If the destination width/height was
- * not submitted we will use the values
- * from the actual file
- *
- */
- if ($this->width == '')
- $this->width = $this->orig_width;
-
- if ($this->height == '')
- $this->height = $this->orig_height;
-
- // Set the quality
- $this->quality = trim(str_replace("%", "", $this->quality));
-
- if ($this->quality == '' OR $this->quality == 0 OR ! is_numeric($this->quality))
- $this->quality = 90;
-
- // Set the x/y coordinates
- $this->x_axis = ($this->x_axis == '' OR ! is_numeric($this->x_axis)) ? 0 : $this->x_axis;
- $this->y_axis = ($this->y_axis == '' OR ! is_numeric($this->y_axis)) ? 0 : $this->y_axis;
-
- // Watermark-related Stuff...
- if ($this->wm_font_color != '')
- {
- if (strlen($this->wm_font_color) == 6)
- {
- $this->wm_font_color = '#'.$this->wm_font_color;
- }
- }
-
- if ($this->wm_shadow_color != '')
- {
- if (strlen($this->wm_shadow_color) == 6)
- {
- $this->wm_shadow_color = '#'.$this->wm_shadow_color;
- }
- }
-
- if ($this->wm_overlay_path != '')
- {
- $this->wm_overlay_path = str_replace("\\", "/", realpath($this->wm_overlay_path));
- }
-
- if ($this->wm_shadow_color != '')
- {
- $this->wm_use_drop_shadow = TRUE;
- }
-
- if ($this->wm_font_path != '')
- {
- $this->wm_use_truetype = TRUE;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Resize
- *
- * This is a wrapper function that chooses the proper
- * resize function based on the protocol specified
- *
- * @access public
- * @return bool
- */
- function resize()
- {
- $protocol = 'image_process_'.$this->image_library;
-
- if (eregi("gd2$", $protocol))
- {
- $protocol = 'image_process_gd';
- }
-
- return $this->$protocol('resize');
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Crop
- *
- * This is a wrapper function that chooses the proper
- * cropping function based on the protocol specified
- *
- * @access public
- * @return bool
- */
- function crop()
- {
- $protocol = 'image_process_'.$this->image_library;
-
- if (eregi("gd2$", $protocol))
- {
- $protocol = 'image_process_gd';
- }
-
- return $this->$protocol('crop');
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Rotate
- *
- * This is a wrapper function that chooses the proper
- * rotation function based on the protocol specified
- *
- * @access public
- * @return bool
- */
- function rotate()
- {
- // Allowed rotation values
- $degs = array(90, 180, 270, 'vrt', 'hor');
-
- if ($this->rotation_angle == '' OR ! in_array($this->rotation_angle, $degs, TRUE))
- {
- $this->set_error('imglib_rotation_angle_required');
- return FALSE;
- }
-
- // Reassign the width and height
- if ($this->rotation_angle == 90 OR $this->rotation_angle == 270)
- {
- $this->width = $this->orig_height;
- $this->height = $this->orig_width;
- }
- else
- {
- $this->width = $this->orig_width;
- $this->height = $this->orig_height;
- }
-
-
- // Choose resizing function
- if ($this->image_library == 'imagemagick' OR $this->image_library == 'netpbm')
- {
- $protocol = 'image_process_'.$this->image_library;
-
- return $this->$protocol('rotate');
- }
-
- if ($this->rotation_angle == 'hor' OR $this->rotation_angle == 'vrt')
- {
- return $this->image_mirror_gd();
- }
- else
- {
- return $this->image_rotate_gd();
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Process Using GD/GD2
- *
- * This function will resize or crop
- *
- * @access public
- * @param string
- * @return bool
- */
- function image_process_gd($action = 'resize')
- {
- $v2_override = FALSE;
-
- // If the target width/height match the source, AND if the new file name is not equal to the old file name
- // we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
- if ($this->dynamic_output === FALSE)
- {
- if ($this->orig_width == $this->width AND $this->orig_height == $this->height)
- {
- if ($this->source_image != $this->new_image)
- {
- if (@copy($this->full_src_path, $this->full_dst_path))
- {
- @chmod($this->full_dst_path, DIR_WRITE_MODE);
- }
- }
-
- return TRUE;
- }
- }
-
- // Let's set up our values based on the action
- if ($action == 'crop')
- {
- // Reassign the source width/height if cropping
- $this->orig_width = $this->width;
- $this->orig_height = $this->height;
-
- // GD 2.0 has a cropping bug so we'll test for it
- if ($this->gd_version() !== FALSE)
- {
- $gd_version = str_replace('0', '', $this->gd_version());
- $v2_override = ($gd_version == 2) ? TRUE : FALSE;
- }
- }
- else
- {
- // If resizing the x/y axis must be zero
- $this->x_axis = 0;
- $this->y_axis = 0;
- }
-
- // Create the image handle
- if ( ! ($src_img = $this->image_create_gd()))
- {
- return FALSE;
- }
-
- // Create The Image
- //
- // old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
- // it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
- // below should that ever prove inaccurate.
- //
- // if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor') AND $v2_override == FALSE)
- if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor'))
- {
- $create = 'imagecreatetruecolor';
- $copy = 'imagecopyresampled';
- }
- else
- {
- $create = 'imagecreate';
- $copy = 'imagecopyresized';
- }
-
- $dst_img = $create($this->width, $this->height);
- $copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
-
- // Show the image
- if ($this->dynamic_output == TRUE)
- {
- $this->image_display_gd($dst_img);
- }
- else
- {
- // Or save it
- if ( ! $this->image_save_gd($dst_img))
- {
- return FALSE;
- }
- }
-
- // Kill the file handles
- imagedestroy($dst_img);
- imagedestroy($src_img);
-
- // Set the file to 777
- @chmod($this->full_dst_path, DIR_WRITE_MODE);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Process Using ImageMagick
- *
- * This function will resize, crop or rotate
- *
- * @access public
- * @param string
- * @return bool
- */
- function image_process_imagemagick($action = 'resize')
- {
- // Do we have a vaild library path?
- if ($this->library_path == '')
- {
- $this->set_error('imglib_libpath_invalid');
- return FALSE;
- }
-
- if ( ! eregi("convert$", $this->library_path))
- {
- if ( ! eregi("/$", $this->library_path)) $this->library_path .= "/";
-
- $this->library_path .= 'convert';
- }
-
- // Execute the command
- $cmd = $this->library_path." -quality ".$this->quality;
-
- if ($action == 'crop')
- {
- $cmd .= " -crop ".$this->width."x".$this->height."+".$this->x_axis."+".$this->y_axis." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
- }
- elseif ($action == 'rotate')
- {
- switch ($this->rotation_angle)
- {
- case 'hor' : $angle = '-flop';
- break;
- case 'vrt' : $angle = '-flip';
- break;
- default : $angle = '-rotate '.$this->rotation_angle;
- break;
- }
-
- $cmd .= " ".$angle." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
- }
- else // Resize
- {
- $cmd .= " -resize ".$this->width."x".$this->height." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
- }
-
- $retval = 1;
-
- @exec($cmd, $output, $retval);
-
- // Did it work?
- if ($retval > 0)
- {
- $this->set_error('imglib_image_process_failed');
- return FALSE;
- }
-
- // Set the file to 777
- @chmod($this->full_dst_path, DIR_WRITE_MODE);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Process Using NetPBM
- *
- * This function will resize, crop or rotate
- *
- * @access public
- * @param string
- * @return bool
- */
- function image_process_netpbm($action = 'resize')
- {
- if ($this->library_path == '')
- {
- $this->set_error('imglib_libpath_invalid');
- return FALSE;
- }
-
- // Build the resizing command
- switch ($this->image_type)
- {
- case 1 :
- $cmd_in = 'giftopnm';
- $cmd_out = 'ppmtogif';
- break;
- case 2 :
- $cmd_in = 'jpegtopnm';
- $cmd_out = 'ppmtojpeg';
- break;
- case 3 :
- $cmd_in = 'pngtopnm';
- $cmd_out = 'ppmtopng';
- break;
- }
-
- if ($action == 'crop')
- {
- $cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
- }
- elseif ($action == 'rotate')
- {
- switch ($this->rotation_angle)
- {
- case 90 : $angle = 'r270';
- break;
- case 180 : $angle = 'r180';
- break;
- case 270 : $angle = 'r90';
- break;
- case 'vrt' : $angle = 'tb';
- break;
- case 'hor' : $angle = 'lr';
- break;
- }
-
- $cmd_inner = 'pnmflip -'.$angle.' ';
- }
- else // Resize
- {
- $cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
- }
-
- $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
-
- $retval = 1;
-
- @exec($cmd, $output, $retval);
-
- // Did it work?
- if ($retval > 0)
- {
- $this->set_error('imglib_image_process_failed');
- return FALSE;
- }
-
- // With NetPBM we have to create a temporary image.
- // If you try manipulating the original it fails so
- // we have to rename the temp file.
- copy ($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
- unlink ($this->dest_folder.'netpbm.tmp');
- @chmod($this->full_dst_path, DIR_WRITE_MODE);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Rotate Using GD
- *
- * @access public
- * @return bool
- */
- function image_rotate_gd()
- {
- // Is Image Rotation Supported?
- // this function is only supported as of PHP 4.3
- if ( ! function_exists('imagerotate'))
- {
- $this->set_error('imglib_rotate_unsupported');
- return FALSE;
- }
-
- // Create the image handle
- if ( ! ($src_img = $this->image_create_gd()))
- {
- return FALSE;
- }
-
- // Set the background color
- // This won't work with transparent PNG files so we are
- // going to have to figure out how to determine the color
- // of the alpha channel in a future release.
-
- $white = imagecolorallocate($src_img, 255, 255, 255);
-
- // Rotate it!
- $dst_img = imagerotate($src_img, $this->rotation_angle, $white);
-
- // Save the Image
- if ($this->dynamic_output == TRUE)
- {
- $this->image_display_gd($dst_img);
- }
- else
- {
- // Or save it
- if ( ! $this->image_save_gd($dst_img))
- {
- return FALSE;
- }
- }
-
- // Kill the file handles
- imagedestroy($dst_img);
- imagedestroy($src_img);
-
- // Set the file to 777
-
- @chmod($this->full_dst_path, DIR_WRITE_MODE);
-
- return true;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create Mirror Image using GD
- *
- * This function will flip horizontal or vertical
- *
- * @access public
- * @return bool
- */
- function image_mirror_gd()
- {
- if ( ! $src_img = $this->image_create_gd())
- {
- return FALSE;
- }
-
- $width = $this->orig_width;
- $height = $this->orig_height;
-
- if ($this->rotation_angle == 'hor')
- {
- for ($i = 0; $i < $height; $i++)
- {
- $left = 0;
- $right = $width-1;
-
- while ($left < $right)
- {
- $cl = imagecolorat($src_img, $left, $i);
- $cr = imagecolorat($src_img, $right, $i);
-
- imagesetpixel($src_img, $left, $i, $cr);
- imagesetpixel($src_img, $right, $i, $cl);
-
- $left++;
- $right--;
- }
- }
- }
- else
- {
- for ($i = 0; $i < $width; $i++)
- {
- $top = 0;
- $bot = $height-1;
-
- while ($top < $bot)
- {
- $ct = imagecolorat($src_img, $i, $top);
- $cb = imagecolorat($src_img, $i, $bot);
-
- imagesetpixel($src_img, $i, $top, $cb);
- imagesetpixel($src_img, $i, $bot, $ct);
-
- $top++;
- $bot--;
- }
- }
- }
-
- // Show the image
- if ($this->dynamic_output == TRUE)
- {
- $this->image_display_gd($src_img);
- }
- else
- {
- // Or save it
- if ( ! $this->image_save_gd($src_img))
- {
- return FALSE;
- }
- }
-
- // Kill the file handles
- imagedestroy($src_img);
-
- // Set the file to 777
- @chmod($this->full_dst_path, DIR_WRITE_MODE);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Image Watermark
- *
- * This is a wrapper function that chooses the type
- * of watermarking based on the specified preference.
- *
- * @access public
- * @param string
- * @return bool
- */
- function watermark()
- {
- if ($this->wm_type == 'overlay')
- {
- return $this->overlay_watermark();
- }
- else
- {
- return $this->text_watermark();
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Watermark - Graphic Version
- *
- * @access public
- * @return bool
- */
- function overlay_watermark()
- {
- if ( ! function_exists('imagecolortransparent'))
- {
- $this->set_error('imglib_gd_required');
- return FALSE;
- }
-
- // Fetch source image properties
- $this->get_image_properties();
-
- // Fetch watermark image properties
- $props = $this->get_image_properties($this->wm_overlay_path, TRUE);
- $wm_img_type = $props['image_type'];
- $wm_width = $props['width'];
- $wm_height = $props['height'];
-
- // Create two image resources
- $wm_img = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);
- $src_img = $this->image_create_gd($this->full_src_path);
-
- // Reverse the offset if necessary
- // When the image is positioned at the bottom
- // we don't want the vertical offset to push it
- // further down. We want the reverse, so we'll
- // invert the offset. Same with the horizontal
- // offset when the image is at the right
-
- $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
- $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
-
- if ($this->wm_vrt_alignment == 'B')
- $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
-
- if ($this->wm_hor_alignment == 'R')
- $this->wm_hor_offset = $this->wm_hor_offset * -1;
-
- // Set the base x and y axis values
- $x_axis = $this->wm_hor_offset + $this->wm_padding;
- $y_axis = $this->wm_vrt_offset + $this->wm_padding;
-
- // Set the vertical position
- switch ($this->wm_vrt_alignment)
- {
- case 'T':
- break;
- case 'M': $y_axis += ($this->orig_height / 2) - ($wm_height / 2);
- break;
- case 'B': $y_axis += $this->orig_height - $wm_height;
- break;
- }
-
- // Set the horizontal position
- switch ($this->wm_hor_alignment)
- {
- case 'L':
- break;
- case 'C': $x_axis += ($this->orig_width / 2) - ($wm_width / 2);
- break;
- case 'R': $x_axis += $this->orig_width - $wm_width;
- break;
- }
-
- // Build the finalized image
- if ($wm_img_type == 3 AND function_exists('imagealphablending'))
- {
- @imagealphablending($src_img, TRUE);
- }
-
- // Set RGB values for text and shadow
- $rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
- $alpha = ($rgba & 0x7F000000) >> 24;
-
- // make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
- if ($alpha > 0)
- {
- // copy the image directly, the image's alpha transparency being the sole determinant of blending
- imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
- }
- else
- {
- // set our RGB value from above to be transparent and merge the images with the specified opacity
- imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
- imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
- }
-
- // Output the image
- if ($this->dynamic_output == TRUE)
- {
- $this->image_display_gd($src_img);
- }
- else
- {
- if ( ! $this->image_save_gd($src_img))
- {
- return FALSE;
- }
- }
-
- imagedestroy($src_img);
- imagedestroy($wm_img);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Watermark - Text Version
- *
- * @access public
- * @return bool
- */
- function text_watermark()
- {
- if ( ! ($src_img = $this->image_create_gd()))
- {
- return FALSE;
- }
-
- if ($this->wm_use_truetype == TRUE AND ! file_exists($this->wm_font_path))
- {
- $this->set_error('imglib_missing_font');
- return FALSE;
- }
-
- // Fetch source image properties
- $this->get_image_properties();
-
- // Set RGB values for text and shadow
- $this->wm_font_color = str_replace('#', '', $this->wm_font_color);
- $this->wm_shadow_color = str_replace('#', '', $this->wm_shadow_color);
-
- $R1 = hexdec(substr($this->wm_font_color, 0, 2));
- $G1 = hexdec(substr($this->wm_font_color, 2, 2));
- $B1 = hexdec(substr($this->wm_font_color, 4, 2));
-
- $R2 = hexdec(substr($this->wm_shadow_color, 0, 2));
- $G2 = hexdec(substr($this->wm_shadow_color, 2, 2));
- $B2 = hexdec(substr($this->wm_shadow_color, 4, 2));
-
- $txt_color = imagecolorclosest($src_img, $R1, $G1, $B1);
- $drp_color = imagecolorclosest($src_img, $R2, $G2, $B2);
-
- // Reverse the vertical offset
- // When the image is positioned at the bottom
- // we don't want the vertical offset to push it
- // further down. We want the reverse, so we'll
- // invert the offset. Note: The horizontal
- // offset flips itself automatically
-
- if ($this->wm_vrt_alignment == 'B')
- $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
-
- if ($this->wm_hor_alignment == 'R')
- $this->wm_hor_offset = $this->wm_hor_offset * -1;
-
- // Set font width and height
- // These are calculated differently depending on
- // whether we are using the true type font or not
- if ($this->wm_use_truetype == TRUE)
- {
- if ($this->wm_font_size == '')
- $this->wm_font_size = '17';
-
- $fontwidth = $this->wm_font_size-($this->wm_font_size/4);
- $fontheight = $this->wm_font_size;
- $this->wm_vrt_offset += $this->wm_font_size;
- }
- else
- {
- $fontwidth = imagefontwidth($this->wm_font_size);
- $fontheight = imagefontheight($this->wm_font_size);
- }
-
- // Set base X and Y axis values
- $x_axis = $this->wm_hor_offset + $this->wm_padding;
- $y_axis = $this->wm_vrt_offset + $this->wm_padding;
-
- // Set verticle alignment
- if ($this->wm_use_drop_shadow == FALSE)
- $this->wm_shadow_distance = 0;
-
- $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
- $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
-
- switch ($this->wm_vrt_alignment)
- {
- case "T" :
- break;
- case "M": $y_axis += ($this->orig_height/2)+($fontheight/2);
- break;
- case "B": $y_axis += ($this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight/2));
- break;
- }
-
- $x_shad = $x_axis + $this->wm_shadow_distance;
- $y_shad = $y_axis + $this->wm_shadow_distance;
-
- // Set horizontal alignment
- switch ($this->wm_hor_alignment)
- {
- case "L":
- break;
- case "R":
- if ($this->wm_use_drop_shadow)
- $x_shad += ($this->orig_width - $fontwidth*strlen($this->wm_text));
- $x_axis += ($this->orig_width - $fontwidth*strlen($this->wm_text));
- break;
- case "C":
- if ($this->wm_use_drop_shadow)
- $x_shad += floor(($this->orig_width - $fontwidth*strlen($this->wm_text))/2);
- $x_axis += floor(($this->orig_width -$fontwidth*strlen($this->wm_text))/2);
- break;
- }
-
- // Add the text to the source image
- if ($this->wm_use_truetype)
- {
- if ($this->wm_use_drop_shadow)
- imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
- imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
- }
- else
- {
- if ($this->wm_use_drop_shadow)
- imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
- imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
- }
-
- // Output the final image
- if ($this->dynamic_output == TRUE)
- {
- $this->image_display_gd($src_img);
- }
- else
- {
- $this->image_save_gd($src_img);
- }
-
- imagedestroy($src_img);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create Image - GD
- *
- * This simply creates an image resource handle
- * based on the type of image being processed
- *
- * @access public
- * @param string
- * @return resource
- */
- function image_create_gd($path = '', $image_type = '')
- {
- if ($path == '')
- $path = $this->full_src_path;
-
- if ($image_type == '')
- $image_type = $this->image_type;
-
-
- switch ($image_type)
- {
- case 1 :
- if ( ! function_exists('imagecreatefromgif'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
- return FALSE;
- }
-
- return imagecreatefromgif($path);
- break;
- case 2 :
- if ( ! function_exists('imagecreatefromjpeg'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
- return FALSE;
- }
-
- return imagecreatefromjpeg($path);
- break;
- case 3 :
- if ( ! function_exists('imagecreatefrompng'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
- return FALSE;
- }
-
- return imagecreatefrompng($path);
- break;
-
- }
-
- $this->set_error(array('imglib_unsupported_imagecreate'));
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Write image file to disk - GD
- *
- * Takes an image resource as input and writes the file
- * to the specified destination
- *
- * @access public
- * @param resource
- * @return bool
- */
- function image_save_gd($resource)
- {
- switch ($this->image_type)
- {
- case 1 :
- if ( ! function_exists('imagegif'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
- return FALSE;
- }
-
- @imagegif($resource, $this->full_dst_path);
- break;
- case 2 :
- if ( ! function_exists('imagejpeg'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
- return FALSE;
- }
-
- if (phpversion() == '4.4.1')
- {
- @touch($this->full_dst_path); // PHP 4.4.1 bug #35060 - workaround
- }
-
- @imagejpeg($resource, $this->full_dst_path, $this->quality);
- break;
- case 3 :
- if ( ! function_exists('imagepng'))
- {
- $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
- return FALSE;
- }
-
- @imagepng($resource, $this->full_dst_path);
- break;
- default :
- $this->set_error(array('imglib_unsupported_imagecreate'));
- return FALSE;
- break;
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Dynamically outputs an image
- *
- * @access public
- * @param resource
- * @return void
- */
- function image_display_gd($resource)
- {
- header("Content-Disposition: filename={$this->source_image};");
- header("Content-Type: {$this->mime_type}");
- header('Content-Transfer-Encoding: binary');
- header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
-
- switch ($this->image_type)
- {
- case 1 : imagegif($resource);
- break;
- case 2 : imagejpeg($resource, '', $this->quality);
- break;
- case 3 : imagepng($resource);
- break;
- default : echo 'Unable to display the image';
- break;
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Re-proportion Image Width/Height
- *
- * When creating thumbs, the desired width/height
- * can end up warping the image due to an incorrect
- * ratio between the full-sized image and the thumb.
- *
- * This function lets us re-proportion the width/height
- * if users choose to maintain the aspect ratio when resizing.
- *
- * @access public
- * @return void
- */
- function image_reproportion()
- {
- if ( ! is_numeric($this->width) OR ! is_numeric($this->height) OR $this->width == 0 OR $this->height == 0)
- return;
-
- if ( ! is_numeric($this->orig_width) OR ! is_numeric($this->orig_height) OR $this->orig_width == 0 OR $this->orig_height == 0)
- return;
-
- $new_width = ceil($this->orig_width*$this->height/$this->orig_height);
- $new_height = ceil($this->width*$this->orig_height/$this->orig_width);
-
- $ratio = (($this->orig_height/$this->orig_width) - ($this->height/$this->width));
-
- if ($this->master_dim != 'width' AND $this->master_dim != 'height')
- {
- $this->master_dim = ($ratio < 0) ? 'width' : 'height';
- }
-
- if (($this->width != $new_width) AND ($this->height != $new_height))
- {
- if ($this->master_dim == 'height')
- {
- $this->width = $new_width;
- }
- else
- {
- $this->height = $new_height;
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Get image properties
- *
- * A helper function that gets info about the file
- *
- * @access public
- * @param string
- * @return mixed
- */
- function get_image_properties($path = '', $return = FALSE)
- {
- // For now we require GD but we should
- // find a way to determine this using IM or NetPBM
-
- if ($path == '')
- $path = $this->full_src_path;
-
- if ( ! file_exists($path))
- {
- $this->set_error('imglib_invalid_path');
- return FALSE;
- }
-
- $vals = @getimagesize($path);
-
- $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
-
- $mime = (isset($types[$vals['2']])) ? 'image/'.$types[$vals['2']] : 'image/jpg';
-
- if ($return == TRUE)
- {
- $v['width'] = $vals['0'];
- $v['height'] = $vals['1'];
- $v['image_type'] = $vals['2'];
- $v['size_str'] = $vals['3'];
- $v['mime_type'] = $mime;
-
- return $v;
- }
-
- $this->orig_width = $vals['0'];
- $this->orig_height = $vals['1'];
- $this->image_type = $vals['2'];
- $this->size_str = $vals['3'];
- $this->mime_type = $mime;
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Size calculator
- *
- * This function takes a known width x height and
- * recalculates it to a new size. Only one
- * new variable needs to be known
- *
- * $props = array(
- * 'width' => $width,
- * 'height' => $height,
- * 'new_width' => 40,
- * 'new_height' => ''
- * );
- *
- * @access public
- * @param array
- * @return array
- */
- function size_calculator($vals)
- {
- if ( ! is_array($vals))
- return;
-
- $allowed = array('new_width', 'new_height', 'width', 'height');
-
- foreach ($allowed as $item)
- {
- if ( ! isset($vals[$item]) OR $vals[$item] == '')
- $vals[$item] = 0;
- }
-
- if ($vals['width'] == 0 OR $vals['height'] == 0)
- {
- return $vals;
- }
-
- if ($vals['new_width'] == 0)
- {
- $vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
- }
- elseif ($vals['new_height'] == 0)
- {
- $vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
- }
-
- return $vals;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Explode source_image
- *
- * This is a helper function that extracts the extension
- * from the source_image. This function lets us deal with
- * source_images with multiple periods, like: my.cool.jpg
- * It returns an associative array with two elements:
- * $array['ext'] = '.jpg';
- * $array['name'] = 'my.cool';
- *
- * @access public
- * @param array
- * @return array
- */
- function explode_name($source_image)
- {
- $x = explode('.', $source_image);
- $ret['ext'] = '.'.end($x);
-
- $name = '';
-
- $ct = count($x)-1;
-
- for ($i = 0; $i < $ct; $i++)
- {
- $name .= $x[$i];
-
- if ($i < ($ct - 1))
- {
- $name .= '.';
- }
- }
-
- $ret['name'] = $name;
-
- return $ret;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Is GD Installed?
- *
- * @access public
- * @return bool
- */
- function gd_loaded()
- {
- if ( ! extension_loaded('gd'))
- {
- if ( ! dl('gd.so'))
- {
- return FALSE;
- }
- }
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Get GD version
- *
- * @access public
- * @return mixed
- */
- function gd_version()
- {
- if (function_exists('gd_info'))
- {
- $gd_version = @gd_info();
- $gd_version = preg_replace("/\D/", "", $gd_version['GD Version']);
-
- return $gd_version;
- }
-
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Set error message
- *
- * @access public
- * @param string
- * @return void
- */
- function set_error($msg)
- {
- $CI =& get_instance();
- $CI->lang->load('imglib');
-
- if (is_array($msg))
- {
- foreach ($msg as $val)
- {
-
- $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
- $this->error_msg[] = $msg;
- log_message('error', $msg);
- }
- }
- else
- {
- $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
- $this->error_msg[] = $msg;
- log_message('error', $msg);
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Show error messages
- *
- * @access public
- * @param string
- * @return string
- */
- function display_errors($open = '<p>', $close = '</p>')
- {
- $str = '';
- foreach ($this->error_msg as $val)
- {
- $str .= $open.$val.$close;
- }
-
- return $str;
- }
-
-}
-// END Image_lib Class
-
-/* End of file Image_lib.php */
+<?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, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Image Manipulation class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Image_lib
+ * @author ExpressionEngine Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/image_lib.html
+ */
+class CI_Image_lib {
+
+ var $image_library = 'gd2'; // Can be: imagemagick, netpbm, gd, gd2
+ var $library_path = '';
+ var $dynamic_output = FALSE; // Whether to send to browser or write to disk
+ var $source_image = '';
+ var $new_image = '';
+ var $width = '';
+ var $height = '';
+ var $quality = '90';
+ var $create_thumb = FALSE;
+ var $thumb_marker = '_thumb';
+ var $maintain_ratio = TRUE; // Whether to maintain aspect ratio when resizing or use hard values
+ var $master_dim = 'auto'; // auto, height, or width. Determines what to use as the master dimension
+ var $rotation_angle = '';
+ var $x_axis = '';
+ var $y_axis = '';
+
+ // Watermark Vars
+ var $wm_text = ''; // Watermark text if graphic is not used
+ var $wm_type = 'text'; // Type of watermarking. Options: text/overlay
+ var $wm_x_transp = 4;
+ var $wm_y_transp = 4;
+ var $wm_overlay_path = ''; // Watermark image path
+ var $wm_font_path = ''; // TT font
+ var $wm_font_size = 17; // Font size (different versions of GD will either use points or pixels)
+ var $wm_vrt_alignment = 'B'; // Vertical alignment: T M B
+ var $wm_hor_alignment = 'C'; // Horizontal alignment: L R C
+ var $wm_padding = 0; // Padding around text
+ var $wm_hor_offset = 0; // Lets you push text to the right
+ var $wm_vrt_offset = 0; // Lets you push text down
+ var $wm_font_color = '#ffffff'; // Text color
+ var $wm_shadow_color = ''; // Dropshadow color
+ var $wm_shadow_distance = 2; // Dropshadow distance
+ var $wm_opacity = 50; // Image opacity: 1 - 100 Only works with image
+
+ // Private Vars
+ var $source_folder = '';
+ var $dest_folder = '';
+ var $mime_type = '';
+ var $orig_width = '';
+ var $orig_height = '';
+ var $image_type = '';
+ var $size_str = '';
+ var $full_src_path = '';
+ var $full_dst_path = '';
+ var $create_fnc = 'imagecreatetruecolor';
+ var $copy_fnc = 'imagecopyresampled';
+ var $error_msg = array();
+ var $wm_use_drop_shadow = FALSE;
+ var $wm_use_truetype = FALSE;
+
+ /**
+ * Constructor
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function CI_Image_lib($props = array())
+ {
+ if (count($props) > 0)
+ {
+ $this->initialize($props);
+ }
+
+ log_message('debug', "Image Lib Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize image properties
+ *
+ * Resets values in case this class is used in a loop
+ *
+ * @access public
+ * @return void
+ */
+ function clear()
+ {
+ $props = array('source_folder', 'dest_folder', 'source_image', 'full_src_path', 'full_dst_path', 'new_image', 'image_type', 'size_str', 'quality', 'orig_width', 'orig_height', 'rotation_angle', 'x_axis', 'y_axis', 'create_fnc', 'copy_fnc', 'wm_overlay_path', 'wm_use_truetype', 'dynamic_output', 'wm_font_size', 'wm_text', 'wm_vrt_alignment', 'wm_hor_alignment', 'wm_padding', 'wm_hor_offset', 'wm_vrt_offset', 'wm_font_color', 'wm_use_drop_shadow', 'wm_shadow_color', 'wm_shadow_distance', 'wm_opacity');
+
+ foreach ($props as $val)
+ {
+ $this->$val = '';
+ }
+
+ // special consideration for master_dim
+ $this->master_dim = 'auto';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * initialize image preferences
+ *
+ * @access public
+ * @param array
+ * @return bool
+ */
+ function initialize($props = array())
+ {
+ /*
+ * Convert array elements into class variables
+ */
+ if (count($props) > 0)
+ {
+ foreach ($props as $key => $val)
+ {
+ $this->$key = $val;
+ }
+ }
+
+ /*
+ * Is there a source image?
+ *
+ * If not, there's no reason to continue
+ *
+ */
+ if ($this->source_image == '')
+ {
+ $this->set_error('imglib_source_image_required');
+ return FALSE;
+ }
+
+ /*
+ * Is getimagesize() Available?
+ *
+ * We use it to determine the image properties (width/height).
+ * Note: We need to figure out how to determine image
+ * properties using ImageMagick and NetPBM
+ *
+ */
+ if ( ! function_exists('getimagesize'))
+ {
+ $this->set_error('imglib_gd_required_for_props');
+ return FALSE;
+ }
+
+ $this->image_library = strtolower($this->image_library);
+
+ /*
+ * Set the full server path
+ *
+ * The source image may or may not contain a path.
+ * Either way, we'll try use realpath to generate the
+ * full server path in order to more reliably read it.
+ *
+ */
+ if (function_exists('realpath') AND @realpath($this->source_image) !== FALSE)
+ {
+ $full_source_path = str_replace("\\", "/", realpath($this->source_image));
+ }
+ else
+ {
+ $full_source_path = $this->source_image;
+ }
+
+ $x = explode('/', $full_source_path);
+ $this->source_image = end($x);
+ $this->source_folder = str_replace($this->source_image, '', $full_source_path);
+
+ // Set the Image Properties
+ if ( ! $this->get_image_properties($this->source_folder.$this->source_image))
+ {
+ return FALSE;
+ }
+
+ /*
+ * Assign the "new" image name/path
+ *
+ * If the user has set a "new_image" name it means
+ * we are making a copy of the source image. If not
+ * it means we are altering the original. We'll
+ * set the destination filename and path accordingly.
+ *
+ */
+ if ($this->new_image == '')
+ {
+ $this->dest_image = $this->source_image;
+ $this->dest_folder = $this->source_folder;
+ }
+ else
+ {
+ if (strpos($this->new_image, '/') === FALSE)
+ {
+ $this->dest_folder = $this->source_folder;
+ $this->dest_image = $this->new_image;
+ }
+ else
+ {
+ if (function_exists('realpath') AND @realpath($this->new_image) !== FALSE)
+ {
+ $full_dest_path = str_replace("\\", "/", realpath($this->new_image));
+ }
+ else
+ {
+ $full_dest_path = $this->new_image;
+ }
+
+ // Is there a file name?
+ if ( ! preg_match("#\.(jpg|jpeg|gif|png)$#i", $full_dest_path))
+ {
+ $this->dest_folder = $full_dest_path.'/';
+ $this->dest_image = $this->source_image;
+ }
+ else
+ {
+ $x = explode('/', $full_dest_path);
+ $this->dest_image = end($x);
+ $this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);
+ }
+ }
+ }
+
+ /*
+ * Compile the finalized filenames/paths
+ *
+ * We'll create two master strings containing the
+ * full server path to the source image and the
+ * full server path to the destination image.
+ * We'll also split the destination image name
+ * so we can insert the thumbnail marker if needed.
+ *
+ */
+ if ($this->create_thumb === FALSE OR $this->thumb_marker == '')
+ {
+ $this->thumb_marker = '';
+ }
+
+ $xp = $this->explode_name($this->dest_image);
+
+ $filename = $xp['name'];
+ $file_ext = $xp['ext'];
+
+ $this->full_src_path = $this->source_folder.$this->source_image;
+ $this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
+
+ /*
+ * Should we maintain image proportions?
+ *
+ * When creating thumbs or copies, the target width/height
+ * might not be in correct proportion with the source
+ * image's width/height. We'll recalculate it here.
+ *
+ */
+ if ($this->maintain_ratio === TRUE && ($this->width != '' AND $this->height != ''))
+ {
+ $this->image_reproportion();
+ }
+
+ /*
+ * Was a width and height specified?
+ *
+ * If the destination width/height was
+ * not submitted we will use the values
+ * from the actual file
+ *
+ */
+ if ($this->width == '')
+ $this->width = $this->orig_width;
+
+ if ($this->height == '')
+ $this->height = $this->orig_height;
+
+ // Set the quality
+ $this->quality = trim(str_replace("%", "", $this->quality));
+
+ if ($this->quality == '' OR $this->quality == 0 OR ! is_numeric($this->quality))
+ $this->quality = 90;
+
+ // Set the x/y coordinates
+ $this->x_axis = ($this->x_axis == '' OR ! is_numeric($this->x_axis)) ? 0 : $this->x_axis;
+ $this->y_axis = ($this->y_axis == '' OR ! is_numeric($this->y_axis)) ? 0 : $this->y_axis;
+
+ // Watermark-related Stuff...
+ if ($this->wm_font_color != '')
+ {
+ if (strlen($this->wm_font_color) == 6)
+ {
+ $this->wm_font_color = '#'.$this->wm_font_color;
+ }
+ }
+
+ if ($this->wm_shadow_color != '')
+ {
+ if (strlen($this->wm_shadow_color) == 6)
+ {
+ $this->wm_shadow_color = '#'.$this->wm_shadow_color;
+ }
+ }
+
+ if ($this->wm_overlay_path != '')
+ {
+ $this->wm_overlay_path = str_replace("\\", "/", realpath($this->wm_overlay_path));
+ }
+
+ if ($this->wm_shadow_color != '')
+ {
+ $this->wm_use_drop_shadow = TRUE;
+ }
+
+ if ($this->wm_font_path != '')
+ {
+ $this->wm_use_truetype = TRUE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Resize
+ *
+ * This is a wrapper function that chooses the proper
+ * resize function based on the protocol specified
+ *
+ * @access public
+ * @return bool
+ */
+ function resize()
+ {
+ $protocol = 'image_process_'.$this->image_library;
+
+ if (eregi("gd2$", $protocol))
+ {
+ $protocol = 'image_process_gd';
+ }
+
+ return $this->$protocol('resize');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Crop
+ *
+ * This is a wrapper function that chooses the proper
+ * cropping function based on the protocol specified
+ *
+ * @access public
+ * @return bool
+ */
+ function crop()
+ {
+ $protocol = 'image_process_'.$this->image_library;
+
+ if (eregi("gd2$", $protocol))
+ {
+ $protocol = 'image_process_gd';
+ }
+
+ return $this->$protocol('crop');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Rotate
+ *
+ * This is a wrapper function that chooses the proper
+ * rotation function based on the protocol specified
+ *
+ * @access public
+ * @return bool
+ */
+ function rotate()
+ {
+ // Allowed rotation values
+ $degs = array(90, 180, 270, 'vrt', 'hor');
+
+ if ($this->rotation_angle == '' OR ! in_array($this->rotation_angle, $degs, TRUE))
+ {
+ $this->set_error('imglib_rotation_angle_required');
+ return FALSE;
+ }
+
+ // Reassign the width and height
+ if ($this->rotation_angle == 90 OR $this->rotation_angle == 270)
+ {
+ $this->width = $this->orig_height;
+ $this->height = $this->orig_width;
+ }
+ else
+ {
+ $this->width = $this->orig_width;
+ $this->height = $this->orig_height;
+ }
+
+
+ // Choose resizing function
+ if ($this->image_library == 'imagemagick' OR $this->image_library == 'netpbm')
+ {
+ $protocol = 'image_process_'.$this->image_library;
+
+ return $this->$protocol('rotate');
+ }
+
+ if ($this->rotation_angle == 'hor' OR $this->rotation_angle == 'vrt')
+ {
+ return $this->image_mirror_gd();
+ }
+ else
+ {
+ return $this->image_rotate_gd();
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Process Using GD/GD2
+ *
+ * This function will resize or crop
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function image_process_gd($action = 'resize')
+ {
+ $v2_override = FALSE;
+
+ // If the target width/height match the source, AND if the new file name is not equal to the old file name
+ // we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
+ if ($this->dynamic_output === FALSE)
+ {
+ if ($this->orig_width == $this->width AND $this->orig_height == $this->height)
+ {
+ if ($this->source_image != $this->new_image)
+ {
+ if (@copy($this->full_src_path, $this->full_dst_path))
+ {
+ @chmod($this->full_dst_path, DIR_WRITE_MODE);
+ }
+ }
+
+ return TRUE;
+ }
+ }
+
+ // Let's set up our values based on the action
+ if ($action == 'crop')
+ {
+ // Reassign the source width/height if cropping
+ $this->orig_width = $this->width;
+ $this->orig_height = $this->height;
+
+ // GD 2.0 has a cropping bug so we'll test for it
+ if ($this->gd_version() !== FALSE)
+ {
+ $gd_version = str_replace('0', '', $this->gd_version());
+ $v2_override = ($gd_version == 2) ? TRUE : FALSE;
+ }
+ }
+ else
+ {
+ // If resizing the x/y axis must be zero
+ $this->x_axis = 0;
+ $this->y_axis = 0;
+ }
+
+ // Create the image handle
+ if ( ! ($src_img = $this->image_create_gd()))
+ {
+ return FALSE;
+ }
+
+ // Create The Image
+ //
+ // old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
+ // it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
+ // below should that ever prove inaccurate.
+ //
+ // if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor') AND $v2_override == FALSE)
+ if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor'))
+ {
+ $create = 'imagecreatetruecolor';
+ $copy = 'imagecopyresampled';
+ }
+ else
+ {
+ $create = 'imagecreate';
+ $copy = 'imagecopyresized';
+ }
+
+ $dst_img = $create($this->width, $this->height);
+ $copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
+
+ // Show the image
+ if ($this->dynamic_output == TRUE)
+ {
+ $this->image_display_gd($dst_img);
+ }
+ else
+ {
+ // Or save it
+ if ( ! $this->image_save_gd($dst_img))
+ {
+ return FALSE;
+ }
+ }
+
+ // Kill the file handles
+ imagedestroy($dst_img);
+ imagedestroy($src_img);
+
+ // Set the file to 777
+ @chmod($this->full_dst_path, DIR_WRITE_MODE);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Process Using ImageMagick
+ *
+ * This function will resize, crop or rotate
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function image_process_imagemagick($action = 'resize')
+ {
+ // Do we have a vaild library path?
+ if ($this->library_path == '')
+ {
+ $this->set_error('imglib_libpath_invalid');
+ return FALSE;
+ }
+
+ if ( ! eregi("convert$", $this->library_path))
+ {
+ if ( ! eregi("/$", $this->library_path)) $this->library_path .= "/";
+
+ $this->library_path .= 'convert';
+ }
+
+ // Execute the command
+ $cmd = $this->library_path." -quality ".$this->quality;
+
+ if ($action == 'crop')
+ {
+ $cmd .= " -crop ".$this->width."x".$this->height."+".$this->x_axis."+".$this->y_axis." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
+ }
+ elseif ($action == 'rotate')
+ {
+ switch ($this->rotation_angle)
+ {
+ case 'hor' : $angle = '-flop';
+ break;
+ case 'vrt' : $angle = '-flip';
+ break;
+ default : $angle = '-rotate '.$this->rotation_angle;
+ break;
+ }
+
+ $cmd .= " ".$angle." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
+ }
+ else // Resize
+ {
+ $cmd .= " -resize ".$this->width."x".$this->height." \"$this->full_src_path\" \"$this->full_dst_path\" 2>&1";
+ }
+
+ $retval = 1;
+
+ @exec($cmd, $output, $retval);
+
+ // Did it work?
+ if ($retval > 0)
+ {
+ $this->set_error('imglib_image_process_failed');
+ return FALSE;
+ }
+
+ // Set the file to 777
+ @chmod($this->full_dst_path, DIR_WRITE_MODE);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Process Using NetPBM
+ *
+ * This function will resize, crop or rotate
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function image_process_netpbm($action = 'resize')
+ {
+ if ($this->library_path == '')
+ {
+ $this->set_error('imglib_libpath_invalid');
+ return FALSE;
+ }
+
+ // Build the resizing command
+ switch ($this->image_type)
+ {
+ case 1 :
+ $cmd_in = 'giftopnm';
+ $cmd_out = 'ppmtogif';
+ break;
+ case 2 :
+ $cmd_in = 'jpegtopnm';
+ $cmd_out = 'ppmtojpeg';
+ break;
+ case 3 :
+ $cmd_in = 'pngtopnm';
+ $cmd_out = 'ppmtopng';
+ break;
+ }
+
+ if ($action == 'crop')
+ {
+ $cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
+ }
+ elseif ($action == 'rotate')
+ {
+ switch ($this->rotation_angle)
+ {
+ case 90 : $angle = 'r270';
+ break;
+ case 180 : $angle = 'r180';
+ break;
+ case 270 : $angle = 'r90';
+ break;
+ case 'vrt' : $angle = 'tb';
+ break;
+ case 'hor' : $angle = 'lr';
+ break;
+ }
+
+ $cmd_inner = 'pnmflip -'.$angle.' ';
+ }
+ else // Resize
+ {
+ $cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
+ }
+
+ $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
+
+ $retval = 1;
+
+ @exec($cmd, $output, $retval);
+
+ // Did it work?
+ if ($retval > 0)
+ {
+ $this->set_error('imglib_image_process_failed');
+ return FALSE;
+ }
+
+ // With NetPBM we have to create a temporary image.
+ // If you try manipulating the original it fails so
+ // we have to rename the temp file.
+ copy ($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
+ unlink ($this->dest_folder.'netpbm.tmp');
+ @chmod($this->full_dst_path, DIR_WRITE_MODE);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Rotate Using GD
+ *
+ * @access public
+ * @return bool
+ */
+ function image_rotate_gd()
+ {
+ // Is Image Rotation Supported?
+ // this function is only supported as of PHP 4.3
+ if ( ! function_exists('imagerotate'))
+ {
+ $this->set_error('imglib_rotate_unsupported');
+ return FALSE;
+ }
+
+ // Create the image handle
+ if ( ! ($src_img = $this->image_create_gd()))
+ {
+ return FALSE;
+ }
+
+ // Set the background color
+ // This won't work with transparent PNG files so we are
+ // going to have to figure out how to determine the color
+ // of the alpha channel in a future release.
+
+ $white = imagecolorallocate($src_img, 255, 255, 255);
+
+ // Rotate it!
+ $dst_img = imagerotate($src_img, $this->rotation_angle, $white);
+
+ // Save the Image
+ if ($this->dynamic_output == TRUE)
+ {
+ $this->image_display_gd($dst_img);
+ }
+ else
+ {
+ // Or save it
+ if ( ! $this->image_save_gd($dst_img))
+ {
+ return FALSE;
+ }
+ }
+
+ // Kill the file handles
+ imagedestroy($dst_img);
+ imagedestroy($src_img);
+
+ // Set the file to 777
+
+ @chmod($this->full_dst_path, DIR_WRITE_MODE);
+
+ return true;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create Mirror Image using GD
+ *
+ * This function will flip horizontal or vertical
+ *
+ * @access public
+ * @return bool
+ */
+ function image_mirror_gd()
+ {
+ if ( ! $src_img = $this->image_create_gd())
+ {
+ return FALSE;
+ }
+
+ $width = $this->orig_width;
+ $height = $this->orig_height;
+
+ if ($this->rotation_angle == 'hor')
+ {
+ for ($i = 0; $i < $height; $i++)
+ {
+ $left = 0;
+ $right = $width-1;
+
+ while ($left < $right)
+ {
+ $cl = imagecolorat($src_img, $left, $i);
+ $cr = imagecolorat($src_img, $right, $i);
+
+ imagesetpixel($src_img, $left, $i, $cr);
+ imagesetpixel($src_img, $right, $i, $cl);
+
+ $left++;
+ $right--;
+ }
+ }
+ }
+ else
+ {
+ for ($i = 0; $i < $width; $i++)
+ {
+ $top = 0;
+ $bot = $height-1;
+
+ while ($top < $bot)
+ {
+ $ct = imagecolorat($src_img, $i, $top);
+ $cb = imagecolorat($src_img, $i, $bot);
+
+ imagesetpixel($src_img, $i, $top, $cb);
+ imagesetpixel($src_img, $i, $bot, $ct);
+
+ $top++;
+ $bot--;
+ }
+ }
+ }
+
+ // Show the image
+ if ($this->dynamic_output == TRUE)
+ {
+ $this->image_display_gd($src_img);
+ }
+ else
+ {
+ // Or save it
+ if ( ! $this->image_save_gd($src_img))
+ {
+ return FALSE;
+ }
+ }
+
+ // Kill the file handles
+ imagedestroy($src_img);
+
+ // Set the file to 777
+ @chmod($this->full_dst_path, DIR_WRITE_MODE);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Image Watermark
+ *
+ * This is a wrapper function that chooses the type
+ * of watermarking based on the specified preference.
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function watermark()
+ {
+ if ($this->wm_type == 'overlay')
+ {
+ return $this->overlay_watermark();
+ }
+ else
+ {
+ return $this->text_watermark();
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Watermark - Graphic Version
+ *
+ * @access public
+ * @return bool
+ */
+ function overlay_watermark()
+ {
+ if ( ! function_exists('imagecolortransparent'))
+ {
+ $this->set_error('imglib_gd_required');
+ return FALSE;
+ }
+
+ // Fetch source image properties
+ $this->get_image_properties();
+
+ // Fetch watermark image properties
+ $props = $this->get_image_properties($this->wm_overlay_path, TRUE);
+ $wm_img_type = $props['image_type'];
+ $wm_width = $props['width'];
+ $wm_height = $props['height'];
+
+ // Create two image resources
+ $wm_img = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);
+ $src_img = $this->image_create_gd($this->full_src_path);
+
+ // Reverse the offset if necessary
+ // When the image is positioned at the bottom
+ // we don't want the vertical offset to push it
+ // further down. We want the reverse, so we'll
+ // invert the offset. Same with the horizontal
+ // offset when the image is at the right
+
+ $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
+ $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
+
+ if ($this->wm_vrt_alignment == 'B')
+ $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
+
+ if ($this->wm_hor_alignment == 'R')
+ $this->wm_hor_offset = $this->wm_hor_offset * -1;
+
+ // Set the base x and y axis values
+ $x_axis = $this->wm_hor_offset + $this->wm_padding;
+ $y_axis = $this->wm_vrt_offset + $this->wm_padding;
+
+ // Set the vertical position
+ switch ($this->wm_vrt_alignment)
+ {
+ case 'T':
+ break;
+ case 'M': $y_axis += ($this->orig_height / 2) - ($wm_height / 2);
+ break;
+ case 'B': $y_axis += $this->orig_height - $wm_height;
+ break;
+ }
+
+ // Set the horizontal position
+ switch ($this->wm_hor_alignment)
+ {
+ case 'L':
+ break;
+ case 'C': $x_axis += ($this->orig_width / 2) - ($wm_width / 2);
+ break;
+ case 'R': $x_axis += $this->orig_width - $wm_width;
+ break;
+ }
+
+ // Build the finalized image
+ if ($wm_img_type == 3 AND function_exists('imagealphablending'))
+ {
+ @imagealphablending($src_img, TRUE);
+ }
+
+ // Set RGB values for text and shadow
+ $rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
+ $alpha = ($rgba & 0x7F000000) >> 24;
+
+ // make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
+ if ($alpha > 0)
+ {
+ // copy the image directly, the image's alpha transparency being the sole determinant of blending
+ imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
+ }
+ else
+ {
+ // set our RGB value from above to be transparent and merge the images with the specified opacity
+ imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
+ imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
+ }
+
+ // Output the image
+ if ($this->dynamic_output == TRUE)
+ {
+ $this->image_display_gd($src_img);
+ }
+ else
+ {
+ if ( ! $this->image_save_gd($src_img))
+ {
+ return FALSE;
+ }
+ }
+
+ imagedestroy($src_img);
+ imagedestroy($wm_img);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Watermark - Text Version
+ *
+ * @access public
+ * @return bool
+ */
+ function text_watermark()
+ {
+ if ( ! ($src_img = $this->image_create_gd()))
+ {
+ return FALSE;
+ }
+
+ if ($this->wm_use_truetype == TRUE AND ! file_exists($this->wm_font_path))
+ {
+ $this->set_error('imglib_missing_font');
+ return FALSE;
+ }
+
+ // Fetch source image properties
+ $this->get_image_properties();
+
+ // Set RGB values for text and shadow
+ $this->wm_font_color = str_replace('#', '', $this->wm_font_color);
+ $this->wm_shadow_color = str_replace('#', '', $this->wm_shadow_color);
+
+ $R1 = hexdec(substr($this->wm_font_color, 0, 2));
+ $G1 = hexdec(substr($this->wm_font_color, 2, 2));
+ $B1 = hexdec(substr($this->wm_font_color, 4, 2));
+
+ $R2 = hexdec(substr($this->wm_shadow_color, 0, 2));
+ $G2 = hexdec(substr($this->wm_shadow_color, 2, 2));
+ $B2 = hexdec(substr($this->wm_shadow_color, 4, 2));
+
+ $txt_color = imagecolorclosest($src_img, $R1, $G1, $B1);
+ $drp_color = imagecolorclosest($src_img, $R2, $G2, $B2);
+
+ // Reverse the vertical offset
+ // When the image is positioned at the bottom
+ // we don't want the vertical offset to push it
+ // further down. We want the reverse, so we'll
+ // invert the offset. Note: The horizontal
+ // offset flips itself automatically
+
+ if ($this->wm_vrt_alignment == 'B')
+ $this->wm_vrt_offset = $this->wm_vrt_offset * -1;
+
+ if ($this->wm_hor_alignment == 'R')
+ $this->wm_hor_offset = $this->wm_hor_offset * -1;
+
+ // Set font width and height
+ // These are calculated differently depending on
+ // whether we are using the true type font or not
+ if ($this->wm_use_truetype == TRUE)
+ {
+ if ($this->wm_font_size == '')
+ $this->wm_font_size = '17';
+
+ $fontwidth = $this->wm_font_size-($this->wm_font_size/4);
+ $fontheight = $this->wm_font_size;
+ $this->wm_vrt_offset += $this->wm_font_size;
+ }
+ else
+ {
+ $fontwidth = imagefontwidth($this->wm_font_size);
+ $fontheight = imagefontheight($this->wm_font_size);
+ }
+
+ // Set base X and Y axis values
+ $x_axis = $this->wm_hor_offset + $this->wm_padding;
+ $y_axis = $this->wm_vrt_offset + $this->wm_padding;
+
+ // Set verticle alignment
+ if ($this->wm_use_drop_shadow == FALSE)
+ $this->wm_shadow_distance = 0;
+
+ $this->wm_vrt_alignment = strtoupper(substr($this->wm_vrt_alignment, 0, 1));
+ $this->wm_hor_alignment = strtoupper(substr($this->wm_hor_alignment, 0, 1));
+
+ switch ($this->wm_vrt_alignment)
+ {
+ case "T" :
+ break;
+ case "M": $y_axis += ($this->orig_height/2)+($fontheight/2);
+ break;
+ case "B": $y_axis += ($this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight/2));
+ break;
+ }
+
+ $x_shad = $x_axis + $this->wm_shadow_distance;
+ $y_shad = $y_axis + $this->wm_shadow_distance;
+
+ // Set horizontal alignment
+ switch ($this->wm_hor_alignment)
+ {
+ case "L":
+ break;
+ case "R":
+ if ($this->wm_use_drop_shadow)
+ $x_shad += ($this->orig_width - $fontwidth*strlen($this->wm_text));
+ $x_axis += ($this->orig_width - $fontwidth*strlen($this->wm_text));
+ break;
+ case "C":
+ if ($this->wm_use_drop_shadow)
+ $x_shad += floor(($this->orig_width - $fontwidth*strlen($this->wm_text))/2);
+ $x_axis += floor(($this->orig_width -$fontwidth*strlen($this->wm_text))/2);
+ break;
+ }
+
+ // Add the text to the source image
+ if ($this->wm_use_truetype)
+ {
+ if ($this->wm_use_drop_shadow)
+ imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
+ imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
+ }
+ else
+ {
+ if ($this->wm_use_drop_shadow)
+ imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
+ imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
+ }
+
+ // Output the final image
+ if ($this->dynamic_output == TRUE)
+ {
+ $this->image_display_gd($src_img);
+ }
+ else
+ {
+ $this->image_save_gd($src_img);
+ }
+
+ imagedestroy($src_img);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create Image - GD
+ *
+ * This simply creates an image resource handle
+ * based on the type of image being processed
+ *
+ * @access public
+ * @param string
+ * @return resource
+ */
+ function image_create_gd($path = '', $image_type = '')
+ {
+ if ($path == '')
+ $path = $this->full_src_path;
+
+ if ($image_type == '')
+ $image_type = $this->image_type;
+
+
+ switch ($image_type)
+ {
+ case 1 :
+ if ( ! function_exists('imagecreatefromgif'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
+ return FALSE;
+ }
+
+ return imagecreatefromgif($path);
+ break;
+ case 2 :
+ if ( ! function_exists('imagecreatefromjpeg'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
+ return FALSE;
+ }
+
+ return imagecreatefromjpeg($path);
+ break;
+ case 3 :
+ if ( ! function_exists('imagecreatefrompng'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
+ return FALSE;
+ }
+
+ return imagecreatefrompng($path);
+ break;
+
+ }
+
+ $this->set_error(array('imglib_unsupported_imagecreate'));
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write image file to disk - GD
+ *
+ * Takes an image resource as input and writes the file
+ * to the specified destination
+ *
+ * @access public
+ * @param resource
+ * @return bool
+ */
+ function image_save_gd($resource)
+ {
+ switch ($this->image_type)
+ {
+ case 1 :
+ if ( ! function_exists('imagegif'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
+ return FALSE;
+ }
+
+ @imagegif($resource, $this->full_dst_path);
+ break;
+ case 2 :
+ if ( ! function_exists('imagejpeg'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
+ return FALSE;
+ }
+
+ if (phpversion() == '4.4.1')
+ {
+ @touch($this->full_dst_path); // PHP 4.4.1 bug #35060 - workaround
+ }
+
+ @imagejpeg($resource, $this->full_dst_path, $this->quality);
+ break;
+ case 3 :
+ if ( ! function_exists('imagepng'))
+ {
+ $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
+ return FALSE;
+ }
+
+ @imagepng($resource, $this->full_dst_path);
+ break;
+ default :
+ $this->set_error(array('imglib_unsupported_imagecreate'));
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Dynamically outputs an image
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function image_display_gd($resource)
+ {
+ header("Content-Disposition: filename={$this->source_image};");
+ header("Content-Type: {$this->mime_type}");
+ header('Content-Transfer-Encoding: binary');
+ header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
+
+ switch ($this->image_type)
+ {
+ case 1 : imagegif($resource);
+ break;
+ case 2 : imagejpeg($resource, '', $this->quality);
+ break;
+ case 3 : imagepng($resource);
+ break;
+ default : echo 'Unable to display the image';
+ break;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Re-proportion Image Width/Height
+ *
+ * When creating thumbs, the desired width/height
+ * can end up warping the image due to an incorrect
+ * ratio between the full-sized image and the thumb.
+ *
+ * This function lets us re-proportion the width/height
+ * if users choose to maintain the aspect ratio when resizing.
+ *
+ * @access public
+ * @return void
+ */
+ function image_reproportion()
+ {
+ if ( ! is_numeric($this->width) OR ! is_numeric($this->height) OR $this->width == 0 OR $this->height == 0)
+ return;
+
+ if ( ! is_numeric($this->orig_width) OR ! is_numeric($this->orig_height) OR $this->orig_width == 0 OR $this->orig_height == 0)
+ return;
+
+ $new_width = ceil($this->orig_width*$this->height/$this->orig_height);
+ $new_height = ceil($this->width*$this->orig_height/$this->orig_width);
+
+ $ratio = (($this->orig_height/$this->orig_width) - ($this->height/$this->width));
+
+ if ($this->master_dim != 'width' AND $this->master_dim != 'height')
+ {
+ $this->master_dim = ($ratio < 0) ? 'width' : 'height';
+ }
+
+ if (($this->width != $new_width) AND ($this->height != $new_height))
+ {
+ if ($this->master_dim == 'height')
+ {
+ $this->width = $new_width;
+ }
+ else
+ {
+ $this->height = $new_height;
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get image properties
+ *
+ * A helper function that gets info about the file
+ *
+ * @access public
+ * @param string
+ * @return mixed
+ */
+ function get_image_properties($path = '', $return = FALSE)
+ {
+ // For now we require GD but we should
+ // find a way to determine this using IM or NetPBM
+
+ if ($path == '')
+ $path = $this->full_src_path;
+
+ if ( ! file_exists($path))
+ {
+ $this->set_error('imglib_invalid_path');
+ return FALSE;
+ }
+
+ $vals = @getimagesize($path);
+
+ $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
+
+ $mime = (isset($types[$vals['2']])) ? 'image/'.$types[$vals['2']] : 'image/jpg';
+
+ if ($return == TRUE)
+ {
+ $v['width'] = $vals['0'];
+ $v['height'] = $vals['1'];
+ $v['image_type'] = $vals['2'];
+ $v['size_str'] = $vals['3'];
+ $v['mime_type'] = $mime;
+
+ return $v;
+ }
+
+ $this->orig_width = $vals['0'];
+ $this->orig_height = $vals['1'];
+ $this->image_type = $vals['2'];
+ $this->size_str = $vals['3'];
+ $this->mime_type = $mime;
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Size calculator
+ *
+ * This function takes a known width x height and
+ * recalculates it to a new size. Only one
+ * new variable needs to be known
+ *
+ * $props = array(
+ * 'width' => $width,
+ * 'height' => $height,
+ * 'new_width' => 40,
+ * 'new_height' => ''
+ * );
+ *
+ * @access public
+ * @param array
+ * @return array
+ */
+ function size_calculator($vals)
+ {
+ if ( ! is_array($vals))
+ {
+ return;
+ }
+
+ $allowed = array('new_width', 'new_height', 'width', 'height');
+
+ foreach ($allowed as $item)
+ {
+ if ( ! isset($vals[$item]) OR $vals[$item] == '')
+ $vals[$item] = 0;
+ }
+
+ if ($vals['width'] == 0 OR $vals['height'] == 0)
+ {
+ return $vals;
+ }
+
+ if ($vals['new_width'] == 0)
+ {
+ $vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
+ }
+ elseif ($vals['new_height'] == 0)
+ {
+ $vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
+ }
+
+ return $vals;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Explode source_image
+ *
+ * This is a helper function that extracts the extension
+ * from the source_image. This function lets us deal with
+ * source_images with multiple periods, like: my.cool.jpg
+ * It returns an associative array with two elements:
+ * $array['ext'] = '.jpg';
+ * $array['name'] = 'my.cool';
+ *
+ * @access public
+ * @param array
+ * @return array
+ */
+ function explode_name($source_image)
+ {
+ $x = explode('.', $source_image);
+ $ret['ext'] = '.'.end($x);
+
+ $name = '';
+
+ $ct = count($x)-1;
+
+ for ($i = 0; $i < $ct; $i++)
+ {
+ $name .= $x[$i];
+
+ if ($i < ($ct - 1))
+ {
+ $name .= '.';
+ }
+ }
+
+ $ret['name'] = $name;
+
+ return $ret;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Is GD Installed?
+ *
+ * @access public
+ * @return bool
+ */
+ function gd_loaded()
+ {
+ if ( ! extension_loaded('gd'))
+ {
+ if ( ! dl('gd.so'))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get GD version
+ *
+ * @access public
+ * @return mixed
+ */
+ function gd_version()
+ {
+ if (function_exists('gd_info'))
+ {
+ $gd_version = @gd_info();
+ $gd_version = preg_replace("/\D/", "", $gd_version['GD Version']);
+
+ return $gd_version;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set error message
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_error($msg)
+ {
+ $CI =& get_instance();
+ $CI->lang->load('imglib');
+
+ if (is_array($msg))
+ {
+ foreach ($msg as $val)
+ {
+
+ $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);
+ $this->error_msg[] = $msg;
+ log_message('error', $msg);
+ }
+ }
+ else
+ {
+ $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
+ $this->error_msg[] = $msg;
+ log_message('error', $msg);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show error messages
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function display_errors($open = '<p>', $close = '</p>')
+ {
+ $str = '';
+ foreach ($this->error_msg as $val)
+ {
+ $str .= $open.$val.$close;
+ }
+
+ return $str;
+ }
+
+}
+// END Image_lib Class
+
+/* End of file Image_lib.php */
/* Location: ./system/libraries/Image_lib.php */ \ No newline at end of file
diff --git a/system/libraries/Language.php b/system/libraries/Language.php
index eb4613d07..78f4143af 100644
--- a/system/libraries/Language.php
+++ b/system/libraries/Language.php
@@ -1,124 +1,123 @@
-<?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, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
- * @filesource
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Language Class
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Language
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/libraries/language.html
- */
-class CI_Language {
-
- var $language = array();
- var $is_loaded = array();
-
- /**
- * Constructor
- *
- * @access public
- */
- function CI_Language()
- {
- log_message('debug', "Language Class Initialized");
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Load a language file
- *
- * @access public
- * @param mixed the name of the language file to be loaded. Can be an array
- * @param string the language (english, etc.)
- * @return void
- */
- function load($langfile = '', $idiom = '', $return = FALSE)
- {
- $langfile = str_replace(EXT, '', str_replace('_lang.', '', $langfile)).'_lang'.EXT;
-
- if (in_array($langfile, $this->is_loaded, TRUE))
- {
- return;
- }
-
- if ($idiom == '')
- {
- $CI =& get_instance();
- $deft_lang = $CI->config->item('language');
- $idiom = ($deft_lang == '') ? 'english' : $deft_lang;
- }
-
- // Determine where the language file is and load it
- if (file_exists(APPPATH.'language/'.$idiom.'/'.$langfile))
- {
- include(APPPATH.'language/'.$idiom.'/'.$langfile);
- }
- else
- {
- if (file_exists(BASEPATH.'language/'.$idiom.'/'.$langfile))
- {
- include(BASEPATH.'language/'.$idiom.'/'.$langfile);
- }
- else
- {
- show_error('Unable to load the requested language file: language/'.$langfile);
- }
- }
-
-
- if ( ! isset($lang))
- {
- log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
- return;
- }
-
- if ($return == TRUE)
- {
- return $lang;
- }
-
- $this->is_loaded[] = $langfile;
- $this->language = array_merge($this->language, $lang);
- unset($lang);
-
- log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile);
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch a single line of text from the language array
- *
- * @access public
- * @param string $line the language line
- * @return string
- */
- function line($line = '')
- {
- $line = ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
- return $line;
- }
-
-}
-// END Language Class
-
-/* End of file Language.php */
+<?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, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Language Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Language
+ * @author ExpressionEngine Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/language.html
+ */
+class CI_Language {
+
+ var $language = array();
+ var $is_loaded = array();
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function CI_Language()
+ {
+ log_message('debug', "Language Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load a language file
+ *
+ * @access public
+ * @param mixed the name of the language file to be loaded. Can be an array
+ * @param string the language (english, etc.)
+ * @return mixed
+ */
+ function load($langfile = '', $idiom = '', $return = FALSE)
+ {
+ $langfile = str_replace(EXT, '', str_replace('_lang.', '', $langfile)).'_lang'.EXT;
+
+ if (in_array($langfile, $this->is_loaded, TRUE))
+ {
+ return;
+ }
+
+ if ($idiom == '')
+ {
+ $CI =& get_instance();
+ $deft_lang = $CI->config->item('language');
+ $idiom = ($deft_lang == '') ? 'english' : $deft_lang;
+ }
+
+ // Determine where the language file is and load it
+ if (file_exists(APPPATH.'language/'.$idiom.'/'.$langfile))
+ {
+ include(APPPATH.'language/'.$idiom.'/'.$langfile);
+ }
+ else
+ {
+ if (file_exists(BASEPATH.'language/'.$idiom.'/'.$langfile))
+ {
+ include(BASEPATH.'language/'.$idiom.'/'.$langfile);
+ }
+ else
+ {
+ show_error('Unable to load the requested language file: language/'.$langfile);
+ }
+ }
+
+ if ( ! isset($lang))
+ {
+ log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
+ return;
+ }
+
+ if ($return == TRUE)
+ {
+ return $lang;
+ }
+
+ $this->is_loaded[] = $langfile;
+ $this->language = array_merge($this->language, $lang);
+ unset($lang);
+
+ log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile);
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a single line of text from the language array
+ *
+ * @access public
+ * @param string $line the language line
+ * @return string
+ */
+ function line($line = '')
+ {
+ $line = ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
+ return $line;
+ }
+
+}
+// END Language Class
+
+/* End of file Language.php */
/* Location: ./system/libraries/Language.php */ \ No newline at end of file
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index ed5f9c3a3..660ce8f16 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -1,758 +1,758 @@
-<?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, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
- * @filesource
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Session Class
- *
- * @package CodeIgniter
- * @subpackage Libraries
- * @category Sessions
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/libraries/sessions.html
- */
-class CI_Session {
-
- var $sess_encrypt_cookie = FALSE;
- var $sess_use_database = FALSE;
- var $sess_table_name = '';
- var $sess_expiration = 7200;
- var $sess_match_ip = FALSE;
- var $sess_match_useragent = TRUE;
- var $sess_cookie_name = 'ci_session';
- var $cookie_prefix = '';
- var $cookie_path = '';
- var $cookie_domain = '';
- var $sess_time_to_update = 300;
- var $encryption_key = '';
- var $flashdata_key = 'flash';
- var $time_reference = 'time';
- var $gc_probability = 5;
- var $userdata = array();
- var $CI;
- var $now;
-
- /**
- * Session Constructor
- *
- * The constructor runs the session routines automatically
- * whenever the class is instantiated.
- */
- function CI_Session($params = array())
- {
- log_message('debug', "Session Class Initialized");
-
- // Set the super object to a local variable for use throughout the class
- $this->CI =& get_instance();
-
- // Set all the session preferences, which can either be set
- // manually via the $params array above or via the config file
- foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
- {
- $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
- }
-
- // Load the string helper so we can use the strip_slashes() function
- $this->CI->load->helper('string');
-
- // Do we need encryption? If so, load the encryption class
- if ($this->sess_encrypt_cookie == TRUE)
- {
- $this->CI->load->library('encrypt');
- }
-
- // Are we using a database? If so, load it
- if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
- {
- $this->CI->load->database();
- }
-
- // Set the "now" time. Can either be GMT or server time, based on the
- // config prefs. We use this to set the "last activity" time
- $this->now = $this->_get_time();
-
- // Set the session length. If the session expiration is
- // set to zero we'll set the expiration two years from now.
- if ($this->sess_expiration == 0)
- {
- $this->sess_expiration = (60*60*24*365*2);
- }
-
- // Set the cookie name
- $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
-
- // Run the Session routine. If a session doesn't exist we'll
- // create a new one. If it does, we'll update it.
- if ( ! $this->sess_read())
- {
- $this->sess_create();
- }
- else
- {
- $this->sess_update();
- }
-
- // Delete 'old' flashdata (from last request)
- $this->_flashdata_sweep();
-
- // Mark all new flashdata as old (data will be deleted before next request)
- $this->_flashdata_mark();
-
- // Delete expired sessions if necessary
- $this->_sess_gc();
-
- log_message('debug', "Session routines successfully run");
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch the current session data if it exists
- *
- * @access public
- * @return void
- */
- function sess_read()
- {
- // Fetch the cookie
- $session = $this->CI->input->cookie($this->sess_cookie_name);
-
- // No cookie? Goodbye cruel world!...
- if ($session === FALSE)
- {
- log_message('debug', 'A session cookie was not found.');
- return FALSE;
- }
-
- // Decrypt the cookie data
- if ($this->sess_encrypt_cookie == TRUE)
- {
- $session = $this->CI->encrypt->decode($session);
- }
- else
- {
- // encryption was not used, so we need to check the md5 hash
- $hash = substr($session, strlen($session)-32); // get last 32 chars
- $session = substr($session, 0, strlen($session)-32);
-
- // Does the md5 hash match? This is to prevent manipulation of session data in userspace
- if ($hash !== md5($session.$this->encryption_key))
- {
- log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
- $this->sess_destroy();
- return FALSE;
- }
- }
-
- // Unserialize the session array
- $session = $this->_unserialize($session);
-
- // Is the session data we unserialized an array with the correct format?
- if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Is the session current?
- if (($session['last_activity'] + $this->sess_expiration) < $this->now)
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Does the IP Match?
- if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Does the User Agent Match?
- if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50)))
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Is there a corresponding session in the DB?
- if ($this->sess_use_database === TRUE)
- {
- $this->CI->db->where('session_id', $session['session_id']);
-
- if ($this->sess_match_ip == TRUE)
- {
- $this->CI->db->where('ip_address', $session['ip_address']);
- }
-
- if ($this->sess_match_useragent == TRUE)
- {
- $this->CI->db->where('user_agent', $session['user_agent']);
- }
-
- $query = $this->CI->db->get($this->sess_table_name);
-
- // No result? Kill it!
- if ($query->num_rows() == 0)
- {
- $this->sess_destroy();
- return FALSE;
- }
-
- // Is there custom data? If so, add it to the main session array
- $row = $query->row();
- if (isset($row->user_data) AND $row->user_data != '')
- {
- $custom_data = $this->_unserialize($row->user_data);
-
- if (is_array($custom_data))
- {
- foreach ($custom_data as $key => $val)
- {
- $session[$key] = $val;
- }
- }
- }
- }
-
- // Session is valid!
- $this->userdata = $session;
- unset($session);
-
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Write the session data
- *
- * @access public
- * @return void
- */
- function sess_write()
- {
- // Are we saving custom data to the DB? If not, all we do is update the cookie
- if ($this->sess_use_database === FALSE)
- {
- $this->_set_cookie();
- return;
- }
-
- // set the custom userdata, the session data we will set in a second
- $custom_userdata = $this->userdata;
- $cookie_userdata = array();
-
- // Before continuing, we need to determine if there is any custom data to deal with.
- // Let's determine this by removing the default indexes to see if there's anything left in the array
- // and set the session data while we're at it
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- unset($custom_userdata[$val]);
- $cookie_userdata[$val] = $this->userdata[$val];
- }
-
- // Did we find any custom data? If not, we turn the empty array into a string
- // since there's no reason to serialize and store an empty array in the DB
- if (count($custom_userdata) === 0)
- {
- $custom_userdata = '';
- }
- else
- {
- // Serialize the custom data array so we can store it
- $custom_userdata = $this->_serialize($custom_userdata);
- }
-
- // Run the update query
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
-
- // Write the cookie. Notice that we manually pass the cookie data array to the
- // _set_cookie() function. Normally that function will store $this->userdata, but
- // in this case that array contains custom data, which we do not want in the cookie.
- $this->_set_cookie($cookie_userdata);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create a new session
- *
- * @access public
- * @return void
- */
- function sess_create()
- {
- $sessid = '';
- while (strlen($sessid) < 32)
- {
- $sessid .= mt_rand(0, mt_getrandmax());
- }
-
- // To make the session ID even more secure we'll combine it with the user's IP
- $sessid .= $this->CI->input->ip_address();
-
- $this->userdata = array(
- 'session_id' => md5(uniqid($sessid, TRUE)),
- 'ip_address' => $this->CI->input->ip_address(),
- 'user_agent' => substr($this->CI->input->user_agent(), 0, 50),
- 'last_activity' => $this->now
- );
-
-
- // Save the data to the DB if needed
- if ($this->sess_use_database === TRUE)
- {
- $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
- }
-
- // Write the cookie
- $this->_set_cookie();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Update an existing session
- *
- * @access public
- * @return void
- */
- function sess_update()
- {
- // We only update the session every five minutes by default
- if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
- {
- return;
- }
-
- // Save the old session id so we know which record to
- // update in the database if we need it
- $old_sessid = $this->userdata['session_id'];
- $new_sessid = '';
- while (strlen($new_sessid) < 32)
- {
- $new_sessid .= mt_rand(0, mt_getrandmax());
- }
-
- // To make the session ID even more secure we'll combine it with the user's IP
- $new_sessid .= $this->CI->input->ip_address();
-
- // Turn it into a hash
- $new_sessid = md5(uniqid($new_sessid, TRUE));
-
- // Update the session data in the session data array
- $this->userdata['session_id'] = $new_sessid;
- $this->userdata['last_activity'] = $this->now;
-
- // _set_cookie() will handle this for us if we aren't using database sessions
- // by pushing all userdata to the cookie.
- $cookie_data = NULL;
-
- // Update the session ID and last_activity field in the DB if needed
- if ($this->sess_use_database === TRUE)
- {
- // set cookie explicitly to only have our session data
- $cookie_data = array();
- foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
- {
- $cookie_data[$val] = $this->userdata[$val];
- }
-
- $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
- }
-
- // Write the cookie
- $this->_set_cookie($cookie_data);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Destroy the current session
- *
- * @access public
- * @return void
- */
- function sess_destroy()
- {
- // Kill the session DB row
- if ($this->sess_use_database === TRUE AND isset($this->userdata['session_id']))
- {
- $this->CI->db->where('session_id', $this->userdata['session_id']);
- $this->CI->db->delete($this->sess_table_name);
- }
-
- // Kill the cookie
- setcookie(
- $this->sess_cookie_name,
- addslashes(serialize(array())),
- ($this->now - 31500000),
- $this->cookie_path,
- $this->cookie_domain,
- 0
- );
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch a specific item from the session array
- *
- * @access public
- * @param string
- * @return string
- */
- function userdata($item)
- {
- return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch all session data
- *
- * @access public
- * @return mixed
- */
- function all_userdata()
- {
- return ( ! isset($this->userdata)) ? FALSE : $this->userdata;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Add or change data in the "userdata" array
- *
- * @access public
- * @param mixed
- * @param string
- * @return void
- */
- function set_userdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $this->userdata[$key] = $val;
- }
- }
-
- $this->sess_write();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete a session variable from the "userdata" array
- *
- * @access array
- * @return void
- */
- function unset_userdata($newdata = array())
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => '');
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- unset($this->userdata[$key]);
- }
- }
-
- $this->sess_write();
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Add or change flashdata, only available
- * until the next request
- *
- * @access public
- * @param mixed
- * @param string
- * @return void
- */
- function set_flashdata($newdata = array(), $newval = '')
- {
- if (is_string($newdata))
- {
- $newdata = array($newdata => $newval);
- }
-
- if (count($newdata) > 0)
- {
- foreach ($newdata as $key => $val)
- {
- $flashdata_key = $this->flashdata_key.':new:'.$key;
- $this->set_userdata($flashdata_key, $val);
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Keeps existing flashdata available to next request.
- *
- * @access public
- * @param string
- * @return void
- */
- function keep_flashdata($key)
- {
- // 'old' flashdata gets removed. Here we mark all
- // flashdata as 'new' to preserve it from _flashdata_sweep()
- // Note the function will return FALSE if the $key
- // provided cannot be found
- $old_flashdata_key = $this->flashdata_key.':old:'.$key;
- $value = $this->userdata($old_flashdata_key);
-
- $new_flashdata_key = $this->flashdata_key.':new:'.$key;
- $this->set_userdata($new_flashdata_key, $value);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Fetch a specific flashdata item from the session array
- *
- * @access public
- * @param string
- * @return string
- */
- function flashdata($key)
- {
- $flashdata_key = $this->flashdata_key.':old:'.$key;
- return $this->userdata($flashdata_key);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Identifies flashdata as 'old' for removal
- * when _flashdata_sweep() runs.
- *
- * @access private
- * @return void
- */
- function _flashdata_mark()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $name => $value)
- {
- $parts = explode(':new:', $name);
- if (is_array($parts) && count($parts) === 2)
- {
- $new_name = $this->flashdata_key.':old:'.$parts[1];
- $this->set_userdata($new_name, $value);
- $this->unset_userdata($name);
- }
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Removes all flashdata marked as 'old'
- *
- * @access private
- * @return void
- */
-
- function _flashdata_sweep()
- {
- $userdata = $this->all_userdata();
- foreach ($userdata as $key => $value)
- {
- if (strpos($key, ':old:'))
- {
- $this->unset_userdata($key);
- }
- }
-
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Get the "now" time
- *
- * @access private
- * @return string
- */
- function _get_time()
- {
- if (strtolower($this->time_reference) == 'gmt')
- {
- $now = time();
- $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
- }
- else
- {
- $time = time();
- }
-
- return $time;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Write the session cookie
- *
- * @access public
- * @return void
- */
- function _set_cookie($cookie_data = NULL)
- {
- if (is_null($cookie_data))
- {
- $cookie_data = $this->userdata;
- }
-
- // Serialize the userdata for the cookie
- $cookie_data = $this->_serialize($cookie_data);
-
- if ($this->sess_encrypt_cookie == TRUE)
- {
- $cookie_data = $this->CI->encrypt->encode($cookie_data);
- }
- else
- {
- // if encryption is not used, we provide an md5 hash to prevent userside tampering
- $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
- }
-
- // Set the cookie
- setcookie(
- $this->sess_cookie_name,
- $cookie_data,
- $this->sess_expiration + time(),
- $this->cookie_path,
- $this->cookie_domain,
- 0
- );
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Serialize an array
- *
- * This function first converts any slashes found in the array to a temporary
- * marker, so when it gets unserialized the slashes will be preserved
- *
- * @access private
- * @param array
- * @return string
- */
- function _serialize($data)
- {
- if (is_array($data))
- {
- foreach ($data as $key => $val)
- {
- $data[$key] = str_replace('\\', '{{slash}}', $val);
- }
- }
- else
- {
- $data = str_replace('\\', '{{slash}}', $data);
- }
-
- return serialize($data);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Unserialize
- *
- * This function unserializes a data string, then converts any
- * temporary slash markers back to actual slashes
- *
- * @access private
- * @param array
- * @return string
- */
- function _unserialize($data)
- {
- $data = @unserialize(strip_slashes($data));
-
- if (is_array($data))
- {
- foreach ($data as $key => $val)
- {
- $data[$key] = str_replace('{{slash}}', '\\', $val);
- }
-
- return $data;
- }
-
- return str_replace('{{slash}}', '\\', $data);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Garbage collection
- *
- * This deletes expired session rows from database
- * if the probability percentage is met
- *
- * @access public
- * @return void
- */
- function _sess_gc()
- {
- if ($this->sess_use_database != TRUE)
- {
- return;
- }
-
- srand(time());
- if ((rand() % 100) < $this->gc_probability)
- {
- $expire = $this->now - $this->sess_expiration;
-
- $this->CI->db->where("last_activity < {$expire}");
- $this->CI->db->delete($this->sess_table_name);
-
- log_message('debug', 'Session garbage collection performed.');
- }
- }
-
-
-}
-// END Session Class
-
-/* End of file Session.php */
+<?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, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Session Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author ExpressionEngine Dev Team
+ * @link http://codeigniter.com/user_guide/libraries/sessions.html
+ */
+class CI_Session {
+
+ var $sess_encrypt_cookie = FALSE;
+ var $sess_use_database = FALSE;
+ var $sess_table_name = '';
+ var $sess_expiration = 7200;
+ var $sess_match_ip = FALSE;
+ var $sess_match_useragent = TRUE;
+ var $sess_cookie_name = 'ci_session';
+ var $cookie_prefix = '';
+ var $cookie_path = '';
+ var $cookie_domain = '';
+ var $sess_time_to_update = 300;
+ var $encryption_key = '';
+ var $flashdata_key = 'flash';
+ var $time_reference = 'time';
+ var $gc_probability = 5;
+ var $userdata = array();
+ var $CI;
+ var $now;
+
+ /**
+ * Session Constructor
+ *
+ * The constructor runs the session routines automatically
+ * whenever the class is instantiated.
+ */
+ function CI_Session($params = array())
+ {
+ log_message('debug', "Session Class Initialized");
+
+ // Set the super object to a local variable for use throughout the class
+ $this->CI =& get_instance();
+
+ // Set all the session preferences, which can either be set
+ // manually via the $params array above or via the config file
+ foreach (array('sess_encrypt_cookie', 'sess_use_database', 'sess_table_name', 'sess_expiration', 'sess_match_ip', 'sess_match_useragent', 'sess_cookie_name', 'cookie_path', 'cookie_domain', 'sess_time_to_update', 'time_reference', 'cookie_prefix', 'encryption_key') as $key)
+ {
+ $this->$key = (isset($params[$key])) ? $params[$key] : $this->CI->config->item($key);
+ }
+
+ // Load the string helper so we can use the strip_slashes() function
+ $this->CI->load->helper('string');
+
+ // Do we need encryption? If so, load the encryption class
+ if ($this->sess_encrypt_cookie == TRUE)
+ {
+ $this->CI->load->library('encrypt');
+ }
+
+ // Are we using a database? If so, load it
+ if ($this->sess_use_database === TRUE AND $this->sess_table_name != '')
+ {
+ $this->CI->load->database();
+ }
+
+ // Set the "now" time. Can either be GMT or server time, based on the
+ // config prefs. We use this to set the "last activity" time
+ $this->now = $this->_get_time();
+
+ // Set the session length. If the session expiration is
+ // set to zero we'll set the expiration two years from now.
+ if ($this->sess_expiration == 0)
+ {
+ $this->sess_expiration = (60*60*24*365*2);
+ }
+
+ // Set the cookie name
+ $this->sess_cookie_name = $this->cookie_prefix.$this->sess_cookie_name;
+
+ // Run the Session routine. If a session doesn't exist we'll
+ // create a new one. If it does, we'll update it.
+ if ( ! $this->sess_read())
+ {
+ $this->sess_create();
+ }
+ else
+ {
+ $this->sess_update();
+ }
+
+ // Delete 'old' flashdata (from last request)
+ $this->_flashdata_sweep();
+
+ // Mark all new flashdata as old (data will be deleted before next request)
+ $this->_flashdata_mark();
+
+ // Delete expired sessions if necessary
+ $this->_sess_gc();
+
+ log_message('debug', "Session routines successfully run");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the current session data if it exists
+ *
+ * @access public
+ * @return bool
+ */
+ function sess_read()
+ {
+ // Fetch the cookie
+ $session = $this->CI->input->cookie($this->sess_cookie_name);
+
+ // No cookie? Goodbye cruel world!...
+ if ($session === FALSE)
+ {
+ log_message('debug', 'A session cookie was not found.');
+ return FALSE;
+ }
+
+ // Decrypt the cookie data
+ if ($this->sess_encrypt_cookie == TRUE)
+ {
+ $session = $this->CI->encrypt->decode($session);
+ }
+ else
+ {
+ // encryption was not used, so we need to check the md5 hash
+ $hash = substr($session, strlen($session)-32); // get last 32 chars
+ $session = substr($session, 0, strlen($session)-32);
+
+ // Does the md5 hash match? This is to prevent manipulation of session data in userspace
+ if ($hash !== md5($session.$this->encryption_key))
+ {
+ log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
+ $this->sess_destroy();
+ return FALSE;
+ }
+ }
+
+ // Unserialize the session array
+ $session = $this->_unserialize($session);
+
+ // Is the session data we unserialized an array with the correct format?
+ if ( ! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is the session current?
+ if (($session['last_activity'] + $this->sess_expiration) < $this->now)
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Does the IP Match?
+ if ($this->sess_match_ip == TRUE AND $session['ip_address'] != $this->CI->input->ip_address())
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Does the User Agent Match?
+ if ($this->sess_match_useragent == TRUE AND trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50)))
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is there a corresponding session in the DB?
+ if ($this->sess_use_database === TRUE)
+ {
+ $this->CI->db->where('session_id', $session['session_id']);
+
+ if ($this->sess_match_ip == TRUE)
+ {
+ $this->CI->db->where('ip_address', $session['ip_address']);
+ }
+
+ if ($this->sess_match_useragent == TRUE)
+ {
+ $this->CI->db->where('user_agent', $session['user_agent']);
+ }
+
+ $query = $this->CI->db->get($this->sess_table_name);
+
+ // No result? Kill it!
+ if ($query->num_rows() == 0)
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is there custom data? If so, add it to the main session array
+ $row = $query->row();
+ if (isset($row->user_data) AND $row->user_data != '')
+ {
+ $custom_data = $this->_unserialize($row->user_data);
+
+ if (is_array($custom_data))
+ {
+ foreach ($custom_data as $key => $val)
+ {
+ $session[$key] = $val;
+ }
+ }
+ }
+ }
+
+ // Session is valid!
+ $this->userdata = $session;
+ unset($session);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write the session data
+ *
+ * @access public
+ * @return void
+ */
+ function sess_write()
+ {
+ // Are we saving custom data to the DB? If not, all we do is update the cookie
+ if ($this->sess_use_database === FALSE)
+ {
+ $this->_set_cookie();
+ return;
+ }
+
+ // set the custom userdata, the session data we will set in a second
+ $custom_userdata = $this->userdata;
+ $cookie_userdata = array();
+
+ // Before continuing, we need to determine if there is any custom data to deal with.
+ // Let's determine this by removing the default indexes to see if there's anything left in the array
+ // and set the session data while we're at it
+ foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
+ {
+ unset($custom_userdata[$val]);
+ $cookie_userdata[$val] = $this->userdata[$val];
+ }
+
+ // Did we find any custom data? If not, we turn the empty array into a string
+ // since there's no reason to serialize and store an empty array in the DB
+ if (count($custom_userdata) === 0)
+ {
+ $custom_userdata = '';
+ }
+ else
+ {
+ // Serialize the custom data array so we can store it
+ $custom_userdata = $this->_serialize($custom_userdata);
+ }
+
+ // Run the update query
+ $this->CI->db->where('session_id', $this->userdata['session_id']);
+ $this->CI->db->update($this->sess_table_name, array('last_activity' => $this->userdata['last_activity'], 'user_data' => $custom_userdata));
+
+ // Write the cookie. Notice that we manually pass the cookie data array to the
+ // _set_cookie() function. Normally that function will store $this->userdata, but
+ // in this case that array contains custom data, which we do not want in the cookie.
+ $this->_set_cookie($cookie_userdata);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create a new session
+ *
+ * @access public
+ * @return void
+ */
+ function sess_create()
+ {
+ $sessid = '';
+ while (strlen($sessid) < 32)
+ {
+ $sessid .= mt_rand(0, mt_getrandmax());
+ }
+
+ // To make the session ID even more secure we'll combine it with the user's IP
+ $sessid .= $this->CI->input->ip_address();
+
+ $this->userdata = array(
+ 'session_id' => md5(uniqid($sessid, TRUE)),
+ 'ip_address' => $this->CI->input->ip_address(),
+ 'user_agent' => substr($this->CI->input->user_agent(), 0, 50),
+ 'last_activity' => $this->now
+ );
+
+
+ // Save the data to the DB if needed
+ if ($this->sess_use_database === TRUE)
+ {
+ $this->CI->db->query($this->CI->db->insert_string($this->sess_table_name, $this->userdata));
+ }
+
+ // Write the cookie
+ $this->_set_cookie();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update an existing session
+ *
+ * @access public
+ * @return void
+ */
+ function sess_update()
+ {
+ // We only update the session every five minutes by default
+ if (($this->userdata['last_activity'] + $this->sess_time_to_update) >= $this->now)
+ {
+ return;
+ }
+
+ // Save the old session id so we know which record to
+ // update in the database if we need it
+ $old_sessid = $this->userdata['session_id'];
+ $new_sessid = '';
+ while (strlen($new_sessid) < 32)
+ {
+ $new_sessid .= mt_rand(0, mt_getrandmax());
+ }
+
+ // To make the session ID even more secure we'll combine it with the user's IP
+ $new_sessid .= $this->CI->input->ip_address();
+
+ // Turn it into a hash
+ $new_sessid = md5(uniqid($new_sessid, TRUE));
+
+ // Update the session data in the session data array
+ $this->userdata['session_id'] = $new_sessid;
+ $this->userdata['last_activity'] = $this->now;
+
+ // _set_cookie() will handle this for us if we aren't using database sessions
+ // by pushing all userdata to the cookie.
+ $cookie_data = NULL;
+
+ // Update the session ID and last_activity field in the DB if needed
+ if ($this->sess_use_database === TRUE)
+ {
+ // set cookie explicitly to only have our session data
+ $cookie_data = array();
+ foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
+ {
+ $cookie_data[$val] = $this->userdata[$val];
+ }
+
+ $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
+ }
+
+ // Write the cookie
+ $this->_set_cookie($cookie_data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @access public
+ * @return void
+ */
+ function sess_destroy()
+ {
+ // Kill the session DB row
+ if ($this->sess_use_database === TRUE AND isset($this->userdata['session_id']))
+ {
+ $this->CI->db->where('session_id', $this->userdata['session_id']);
+ $this->CI->db->delete($this->sess_table_name);
+ }
+
+ // Kill the cookie
+ setcookie(
+ $this->sess_cookie_name,
+ addslashes(serialize(array())),
+ ($this->now - 31500000),
+ $this->cookie_path,
+ $this->cookie_domain,
+ 0
+ );
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a specific item from the session array
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function userdata($item)
+ {
+ return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch all session data
+ *
+ * @access public
+ * @return mixed
+ */
+ function all_userdata()
+ {
+ return ( ! isset($this->userdata)) ? FALSE : $this->userdata;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Add or change data in the "userdata" array
+ *
+ * @access public
+ * @param mixed
+ * @param string
+ * @return void
+ */
+ function set_userdata($newdata = array(), $newval = '')
+ {
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $this->userdata[$key] = $val;
+ }
+ }
+
+ $this->sess_write();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete a session variable from the "userdata" array
+ *
+ * @access array
+ * @return void
+ */
+ function unset_userdata($newdata = array())
+ {
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => '');
+ }
+
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ unset($this->userdata[$key]);
+ }
+ }
+
+ $this->sess_write();
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Add or change flashdata, only available
+ * until the next request
+ *
+ * @access public
+ * @param mixed
+ * @param string
+ * @return void
+ */
+ function set_flashdata($newdata = array(), $newval = '')
+ {
+ if (is_string($newdata))
+ {
+ $newdata = array($newdata => $newval);
+ }
+
+ if (count($newdata) > 0)
+ {
+ foreach ($newdata as $key => $val)
+ {
+ $flashdata_key = $this->flashdata_key.':new:'.$key;
+ $this->set_userdata($flashdata_key, $val);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Keeps existing flashdata available to next request.
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function keep_flashdata($key)
+ {
+ // 'old' flashdata gets removed. Here we mark all
+ // flashdata as 'new' to preserve it from _flashdata_sweep()
+ // Note the function will return FALSE if the $key
+ // provided cannot be found
+ $old_flashdata_key = $this->flashdata_key.':old:'.$key;
+ $value = $this->userdata($old_flashdata_key);
+
+ $new_flashdata_key = $this->flashdata_key.':new:'.$key;
+ $this->set_userdata($new_flashdata_key, $value);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Fetch a specific flashdata item from the session array
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function flashdata($key)
+ {
+ $flashdata_key = $this->flashdata_key.':old:'.$key;
+ return $this->userdata($flashdata_key);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Identifies flashdata as 'old' for removal
+ * when _flashdata_sweep() runs.
+ *
+ * @access private
+ * @return void
+ */
+ function _flashdata_mark()
+ {
+ $userdata = $this->all_userdata();
+ foreach ($userdata as $name => $value)
+ {
+ $parts = explode(':new:', $name);
+ if (is_array($parts) && count($parts) === 2)
+ {
+ $new_name = $this->flashdata_key.':old:'.$parts[1];
+ $this->set_userdata($new_name, $value);
+ $this->unset_userdata($name);
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Removes all flashdata marked as 'old'
+ *
+ * @access private
+ * @return void
+ */
+
+ function _flashdata_sweep()
+ {
+ $userdata = $this->all_userdata();
+ foreach ($userdata as $key => $value)
+ {
+ if (strpos($key, ':old:'))
+ {
+ $this->unset_userdata($key);
+ }
+ }
+
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get the "now" time
+ *
+ * @access private
+ * @return string
+ */
+ function _get_time()
+ {
+ if (strtolower($this->time_reference) == 'gmt')
+ {
+ $now = time();
+ $time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
+ }
+ else
+ {
+ $time = time();
+ }
+
+ return $time;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write the session cookie
+ *
+ * @access public
+ * @return void
+ */
+ function _set_cookie($cookie_data = NULL)
+ {
+ if (is_null($cookie_data))
+ {
+ $cookie_data = $this->userdata;
+ }
+
+ // Serialize the userdata for the cookie
+ $cookie_data = $this->_serialize($cookie_data);
+
+ if ($this->sess_encrypt_cookie == TRUE)
+ {
+ $cookie_data = $this->CI->encrypt->encode($cookie_data);
+ }
+ else
+ {
+ // if encryption is not used, we provide an md5 hash to prevent userside tampering
+ $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
+ }
+
+ // Set the cookie
+ setcookie(
+ $this->sess_cookie_name,
+ $cookie_data,
+ $this->sess_expiration + time(),
+ $this->cookie_path,
+ $this->cookie_domain,
+ 0
+ );
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Serialize an array
+ *
+ * This function first converts any slashes found in the array to a temporary
+ * marker, so when it gets unserialized the slashes will be preserved
+ *
+ * @access private
+ * @param array
+ * @return string
+ */
+ function _serialize($data)
+ {
+ if (is_array($data))
+ {
+ foreach ($data as $key => $val)
+ {
+ $data[$key] = str_replace('\\', '{{slash}}', $val);
+ }
+ }
+ else
+ {
+ $data = str_replace('\\', '{{slash}}', $data);
+ }
+
+ return serialize($data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Unserialize
+ *
+ * This function unserializes a data string, then converts any
+ * temporary slash markers back to actual slashes
+ *
+ * @access private
+ * @param array
+ * @return string
+ */
+ function _unserialize($data)
+ {
+ $data = @unserialize(strip_slashes($data));
+
+ if (is_array($data))
+ {
+ foreach ($data as $key => $val)
+ {
+ $data[$key] = str_replace('{{slash}}', '\\', $val);
+ }
+
+ return $data;
+ }
+
+ return str_replace('{{slash}}', '\\', $data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Garbage collection
+ *
+ * This deletes expired session rows from database
+ * if the probability percentage is met
+ *
+ * @access public
+ * @return void
+ */
+ function _sess_gc()
+ {
+ if ($this->sess_use_database != TRUE)
+ {
+ return;
+ }
+
+ srand(time());
+ if ((rand() % 100) < $this->gc_probability)
+ {
+ $expire = $this->now - $this->sess_expiration;
+
+ $this->CI->db->where("last_activity < {$expire}");
+ $this->CI->db->delete($this->sess_table_name);
+
+ log_message('debug', 'Session garbage collection performed.');
+ }
+ }
+
+
+}
+// END Session Class
+
+/* End of file Session.php */
/* Location: ./system/libraries/Session.php */ \ No newline at end of file
diff --git a/user_guide/changelog.html b/user_guide/changelog.html
index f690c9194..cde5f436c 100644
--- a/user_guide/changelog.html
+++ b/user_guide/changelog.html
@@ -81,9 +81,10 @@ SVN Revision: </p>
<li>Fixed a bug in the MySQLi driver when no port is specified</li>
<li>Fixed a bug (#5702), in which the field label was not being fetched properly, when "matching" one field to another.</li>
<li>Fixed a bug in which identifers were not being escaped properly when reserved characters were used.</li>
- <li>Fixed a bug with the regular expression used to protect submitted paragraph tags in auto typography.</p>
+ <li>Fixed a bug with the regular expression used to protect submitted paragraph tags in auto typography.</li>
<li>Fixed a bug where double dashes within tag attributes were being converted to em dash entities.</li>
<li>Fixed a bug where double spaces within tag attributes were being converted to non-breaking space entities.</li>
+ <li>Changed a few docblock comments to reflect actual return values.</li>
</ul>