Propset eol-style to CRLF

simplified paragraph tag cleanup regex
diff --git a/system/application/config/doctypes.php b/system/application/config/doctypes.php
index 9d510ab..2e6ac7d 100644
--- a/system/application/config/doctypes.php
+++ b/system/application/config/doctypes.php
@@ -1,15 +1,15 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-
-$_doctypes = array(
-					'xhtml11'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
-					'xhtml1-strict'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
-					'xhtml1-trans'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
-					'xhtml1-frame'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
-					'html5'			=> '<!DOCTYPE html>',
-					'html4-strict'	=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
-					'html4-trans'	=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
-					'html4-frame'	=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'
-					);
-
-/* End of file doctypes.php */
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

+

+$_doctypes = array(

+					'xhtml11'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',

+					'xhtml1-strict'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',

+					'xhtml1-trans'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',

+					'xhtml1-frame'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',

+					'html5'			=> '<!DOCTYPE html>',

+					'html4-strict'	=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',

+					'html4-trans'	=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',

+					'html4-frame'	=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'

+					);

+

+/* End of file doctypes.php */

 /* Location: application/config/doctypes.php */
\ No newline at end of file
diff --git a/system/application/config/hooks.php b/system/application/config/hooks.php
index 5e98a9b..b94edb9 100644
--- a/system/application/config/hooks.php
+++ b/system/application/config/hooks.php
@@ -1,16 +1,16 @@
-<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/*
-| -------------------------------------------------------------------------
-| Hooks
-| -------------------------------------------------------------------------
-| This file lets you define "hooks" to extend CI without hacking the core
-| files.  Please see the user guide for info:
-|
-|	http://codeigniter.com/user_guide/general/hooks.html
-|
-*/
-
-
-
-/* End of file hooks.php */
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

+/*

+| -------------------------------------------------------------------------

+| Hooks

+| -------------------------------------------------------------------------

+| This file lets you define "hooks" to extend CI without hacking the core

+| files.  Please see the user guide for info:

+|

+|	http://codeigniter.com/user_guide/general/hooks.html

+|

+*/

+

+

+

+/* End of file hooks.php */

 /* Location: ./system/application/config/hooks.php */
\ No newline at end of file
diff --git a/system/application/config/smileys.php b/system/application/config/smileys.php
index 7f3aba5..8ef424f 100644
--- a/system/application/config/smileys.php
+++ b/system/application/config/smileys.php
@@ -1,66 +1,66 @@
-<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/*
-| -------------------------------------------------------------------
-| SMILEYS
-| -------------------------------------------------------------------
-| This file contains an array of smileys for use with the emoticon helper.
-| Individual images can be used to replace multiple simileys.  For example:
-| :-) and :) use the same image replacement.
-|
-| Please see user guide for more info: 
-| http://codeigniter.com/user_guide/helpers/smiley_helper.html
-|
-*/
-
-$smileys = array(
-
-//	smiley			image name						width	height	alt
-
-	':-)'			=>	array('grin.gif',			'19',	'19',	'grin'),
-	':lol:'			=>	array('lol.gif',			'19',	'19',	'LOL'),
-	':cheese:'		=>	array('cheese.gif',			'19',	'19',	'cheese'),
-	':)'			=>	array('smile.gif',			'19',	'19',	'smile'),
-	';-)'			=>	array('wink.gif',			'19',	'19',	'wink'),
-	';)'			=>	array('wink.gif',			'19',	'19',	'wink'),
-	':smirk:'		=>	array('smirk.gif',			'19',	'19',	'smirk'),
-	':roll:'		=>	array('rolleyes.gif',		'19',	'19',	'rolleyes'),
-	':-S'			=>	array('confused.gif',		'19',	'19',	'confused'),
-	':wow:'			=>	array('surprise.gif',		'19',	'19',	'surprised'),
-	':bug:'			=>	array('bigsurprise.gif',	'19',	'19',	'big surprise'),
-	':-P'			=>	array('tongue_laugh.gif',	'19',	'19',	'tongue laugh'),
-	'%-P'			=>	array('tongue_rolleye.gif',	'19',	'19',	'tongue rolleye'),
-	';-P'			=>	array('tongue_wink.gif',	'19',	'19',	'tongue wink'),
-	':P'			=>	array('raspberry.gif',		'19',	'19',	'raspberry'),
-	':blank:'		=>	array('blank.gif',			'19',	'19',	'blank stare'),
-	':long:'		=>	array('longface.gif',		'19',	'19',	'long face'),
-	':ohh:'			=>	array('ohh.gif',			'19',	'19',	'ohh'),
-	':grrr:'		=>	array('grrr.gif',			'19',	'19',	'grrr'),
-	':gulp:'		=>	array('gulp.gif',			'19',	'19',	'gulp'),
-	'8-/'			=>	array('ohoh.gif',			'19',	'19',	'oh oh'),
-	':down:'		=>	array('downer.gif',			'19',	'19',	'downer'),
-	':red:'			=>	array('embarrassed.gif',	'19',	'19',	'red face'),
-	':sick:'		=>	array('sick.gif',			'19',	'19',	'sick'),
-	':shut:'		=>	array('shuteye.gif',		'19',	'19',	'shut eye'),
-	':-/'			=>	array('hmm.gif',			'19',	'19',	'hmmm'),
-	'>:('			=>	array('mad.gif',			'19',	'19',	'mad'),
-	':mad:'			=>	array('mad.gif',			'19',	'19',	'mad'),
-	'>:-('			=>	array('angry.gif',			'19',	'19',	'angry'),
-	':angry:'		=>	array('angry.gif',			'19',	'19',	'angry'),
-	':zip:'			=>	array('zip.gif',			'19',	'19',	'zipper'),
-	':kiss:'		=>	array('kiss.gif',			'19',	'19',	'kiss'),
-	':ahhh:'		=>	array('shock.gif',			'19',	'19',	'shock'),
-	':coolsmile:'	=>	array('shade_smile.gif',	'19',	'19',	'cool smile'),
-	':coolsmirk:'	=>	array('shade_smirk.gif',	'19',	'19',	'cool smirk'),
-	':coolgrin:'	=>	array('shade_grin.gif',		'19',	'19',	'cool grin'),
-	':coolhmm:'		=>	array('shade_hmm.gif',		'19',	'19',	'cool hmm'),
-	':coolmad:'		=>	array('shade_mad.gif',		'19',	'19',	'cool mad'),
-	':coolcheese:'	=>	array('shade_cheese.gif',	'19',	'19',	'cool cheese'),
-	':vampire:'		=>	array('vampire.gif',		'19',	'19',	'vampire'),
-	':snake:'		=>	array('snake.gif',			'19',	'19',	'snake'),
-	':exclaim:'		=>	array('exclaim.gif',		'19',	'19',	'excaim'),
-	':question:'	=>	array('question.gif',		'19',	'19',	'question') // no comma after last item
-
-		);
-
-/* End of file smileys.php */
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

+/*

+| -------------------------------------------------------------------

+| SMILEYS

+| -------------------------------------------------------------------

+| This file contains an array of smileys for use with the emoticon helper.

+| Individual images can be used to replace multiple simileys.  For example:

+| :-) and :) use the same image replacement.

+|

+| Please see user guide for more info: 

+| http://codeigniter.com/user_guide/helpers/smiley_helper.html

+|

+*/

+

+$smileys = array(

+

+//	smiley			image name						width	height	alt

+

+	':-)'			=>	array('grin.gif',			'19',	'19',	'grin'),

+	':lol:'			=>	array('lol.gif',			'19',	'19',	'LOL'),

+	':cheese:'		=>	array('cheese.gif',			'19',	'19',	'cheese'),

+	':)'			=>	array('smile.gif',			'19',	'19',	'smile'),

+	';-)'			=>	array('wink.gif',			'19',	'19',	'wink'),

+	';)'			=>	array('wink.gif',			'19',	'19',	'wink'),

+	':smirk:'		=>	array('smirk.gif',			'19',	'19',	'smirk'),

+	':roll:'		=>	array('rolleyes.gif',		'19',	'19',	'rolleyes'),

+	':-S'			=>	array('confused.gif',		'19',	'19',	'confused'),

+	':wow:'			=>	array('surprise.gif',		'19',	'19',	'surprised'),

+	':bug:'			=>	array('bigsurprise.gif',	'19',	'19',	'big surprise'),

+	':-P'			=>	array('tongue_laugh.gif',	'19',	'19',	'tongue laugh'),

+	'%-P'			=>	array('tongue_rolleye.gif',	'19',	'19',	'tongue rolleye'),

+	';-P'			=>	array('tongue_wink.gif',	'19',	'19',	'tongue wink'),

+	':P'			=>	array('raspberry.gif',		'19',	'19',	'raspberry'),

+	':blank:'		=>	array('blank.gif',			'19',	'19',	'blank stare'),

+	':long:'		=>	array('longface.gif',		'19',	'19',	'long face'),

+	':ohh:'			=>	array('ohh.gif',			'19',	'19',	'ohh'),

+	':grrr:'		=>	array('grrr.gif',			'19',	'19',	'grrr'),

+	':gulp:'		=>	array('gulp.gif',			'19',	'19',	'gulp'),

+	'8-/'			=>	array('ohoh.gif',			'19',	'19',	'oh oh'),

+	':down:'		=>	array('downer.gif',			'19',	'19',	'downer'),

+	':red:'			=>	array('embarrassed.gif',	'19',	'19',	'red face'),

+	':sick:'		=>	array('sick.gif',			'19',	'19',	'sick'),

+	':shut:'		=>	array('shuteye.gif',		'19',	'19',	'shut eye'),

+	':-/'			=>	array('hmm.gif',			'19',	'19',	'hmmm'),

+	'>:('			=>	array('mad.gif',			'19',	'19',	'mad'),

+	':mad:'			=>	array('mad.gif',			'19',	'19',	'mad'),

+	'>:-('			=>	array('angry.gif',			'19',	'19',	'angry'),

+	':angry:'		=>	array('angry.gif',			'19',	'19',	'angry'),

+	':zip:'			=>	array('zip.gif',			'19',	'19',	'zipper'),

+	':kiss:'		=>	array('kiss.gif',			'19',	'19',	'kiss'),

+	':ahhh:'		=>	array('shock.gif',			'19',	'19',	'shock'),

+	':coolsmile:'	=>	array('shade_smile.gif',	'19',	'19',	'cool smile'),

+	':coolsmirk:'	=>	array('shade_smirk.gif',	'19',	'19',	'cool smirk'),

+	':coolgrin:'	=>	array('shade_grin.gif',		'19',	'19',	'cool grin'),

+	':coolhmm:'		=>	array('shade_hmm.gif',		'19',	'19',	'cool hmm'),

+	':coolmad:'		=>	array('shade_mad.gif',		'19',	'19',	'cool mad'),

+	':coolcheese:'	=>	array('shade_cheese.gif',	'19',	'19',	'cool cheese'),

+	':vampire:'		=>	array('vampire.gif',		'19',	'19',	'vampire'),

+	':snake:'		=>	array('snake.gif',			'19',	'19',	'snake'),

+	':exclaim:'		=>	array('exclaim.gif',		'19',	'19',	'excaim'),

+	':question:'	=>	array('question.gif',		'19',	'19',	'question') // no comma after last item

+

+		);

+

+/* End of file smileys.php */

 /* Location: ./system/application/config/smileys.php */
\ No newline at end of file
diff --git a/system/application/config/user_agents.php b/system/application/config/user_agents.php
index c01b276..eabd762 100644
--- a/system/application/config/user_agents.php
+++ b/system/application/config/user_agents.php
@@ -1,175 +1,175 @@
-<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/*
-| -------------------------------------------------------------------
-| USER AGENT TYPES
-| -------------------------------------------------------------------
-| This file contains four arrays of user agent data.  It is used by the
-| User Agent Class to help identify browser, platform, robot, and
-| mobile device data.  The array keys are used to identify the device
-| and the array values are used to set the actual name of the item.
-|
-*/
-
-$platforms = array (
-					'windows nt 6.0'	=> 'Windows Longhorn',
-					'windows nt 5.2'	=> 'Windows 2003',
-					'windows nt 5.0'	=> 'Windows 2000',
-					'windows nt 5.1'	=> 'Windows XP',
-					'windows nt 4.0'	=> 'Windows NT 4.0',
-					'winnt4.0'			=> 'Windows NT 4.0',
-					'winnt 4.0'			=> 'Windows NT',
-					'winnt'				=> 'Windows NT',
-					'windows 98'		=> 'Windows 98',
-					'win98'				=> 'Windows 98',
-					'windows 95'		=> 'Windows 95',
-					'win95'				=> 'Windows 95',
-					'windows'			=> 'Unknown Windows OS',
-					'os x'				=> 'Mac OS X',
-					'ppc mac'			=> 'Power PC Mac',
-					'freebsd'			=> 'FreeBSD',
-					'ppc'				=> 'Macintosh',
-					'linux'				=> 'Linux',
-					'debian'			=> 'Debian',
-					'sunos'				=> 'Sun Solaris',
-					'beos'				=> 'BeOS',
-					'apachebench'		=> 'ApacheBench',
-					'aix'				=> 'AIX',
-					'irix'				=> 'Irix',
-					'osf'				=> 'DEC OSF',
-					'hp-ux'				=> 'HP-UX',
-					'netbsd'			=> 'NetBSD',
-					'bsdi'				=> 'BSDi',
-					'openbsd'			=> 'OpenBSD',
-					'gnu'				=> 'GNU/Linux',
-					'unix'				=> 'Unknown Unix OS'
-				);
-
-
-// The order of this array should NOT be changed. Many browsers return
-// multiple browser types so we want to identify the sub-type first.
-$browsers = array(
-					'Opera'				=> 'Opera',
-					'MSIE'				=> 'Internet Explorer',
-					'Internet Explorer'	=> 'Internet Explorer',
-					'Shiira'			=> 'Shiira',
-					'Firefox'			=> 'Firefox',
-					'Chimera'			=> 'Chimera',
-					'Phoenix'			=> 'Phoenix',
-					'Firebird'			=> 'Firebird',
-					'Camino'			=> 'Camino',
-					'Netscape'			=> 'Netscape',
-					'OmniWeb'			=> 'OmniWeb',
-					'Mozilla'			=> 'Mozilla',
-					'Safari'			=> 'Safari',
-					'Konqueror'			=> 'Konqueror',
-					'icab'				=> 'iCab',
-					'Lynx'				=> 'Lynx',
-					'Links'				=> 'Links',
-					'hotjava'			=> 'HotJava',
-					'amaya'				=> 'Amaya',
-					'IBrowse'			=> 'IBrowse'
-				);
-
-$mobiles = array(
-					// legacy array, old values commented out
-					'mobileexplorer'	=> 'Mobile Explorer',
-//					'openwave'			=> 'Open Wave',
-//					'opera mini'		=> 'Opera Mini',
-//					'operamini'			=> 'Opera Mini',
-//					'elaine'			=> 'Palm',
-					'palmsource'		=> 'Palm',
-//					'digital paths'		=> 'Palm',
-//					'avantgo'			=> 'Avantgo',
-//					'xiino'				=> 'Xiino',
-					'palmscape'			=> 'Palmscape',
-//					'nokia'				=> 'Nokia',
-//					'ericsson'			=> 'Ericsson',
-//					'blackberry'		=> 'BlackBerry',
-//					'motorola'			=> 'Motorola'
-
-					// Phones and Manufacturers
-					'motorola'			=> "Motorola",
-					'nokia'				=> "Nokia",
-					'palm'				=> "Palm",
-					'iphone'			=> "Apple iPhone",
-					'ipod'				=> "Apple iPod Touch",
-					'sony'				=> "Sony Ericsson",
-					'ericsson'			=> "Sony Ericsson",
-					'blackberry'		=> "BlackBerry",
-					'cocoon'			=> "O2 Cocoon",
-					'blazer'			=> "Treo",
-					'lg'				=> "LG",
-					'amoi'				=> "Amoi",
-					'xda'				=> "XDA",
-					'mda'				=> "MDA",
-					'vario'				=> "Vario",
-					'htc'				=> "HTC",
-					'samsung'			=> "Samsung",
-					'sharp'				=> "Sharp",
-					'sie-'				=> "Siemens",
-					'alcatel'			=> "Alcatel",
-					'benq'				=> "BenQ",
-					'ipaq'				=> "HP iPaq",
-					'mot-'				=> "Motorola",
-					'playstation portable' 	=> "PlayStation Portable",
-					'hiptop'			=> "Danger Hiptop",
-					'nec-'				=> "NEC",
-					'panasonic'			=> "Panasonic",
-					'philips'			=> "Philips",
-					'sagem'				=> "Sagem",
-					'sanyo'				=> "Sanyo",
-					'spv'				=> "SPV",
-					'zte'				=> "ZTE",
-					'sendo'				=> "Sendo",
-
-					// Operating Systems
-					'symbian'				=> "Symbian",
-					'SymbianOS'				=> "SymbianOS", 
-					'elaine'				=> "Palm",
-					'palm'					=> "Palm",
-					'series60'				=> "Symbian S60",
-					'windows ce'			=> "Windows CE",
-
-					// Browsers
-					'obigo'					=> "Obigo",
-					'netfront'				=> "Netfront Browser",
-					'openwave'				=> "Openwave Browser",
-					'mobilexplorer'			=> "Mobile Explorer",
-					'operamini'				=> "Opera Mini",
-					'opera mini'			=> "Opera Mini",
-
-					// Other
-					'digital paths'			=> "Digital Paths",
-					'avantgo'				=> "AvantGo",
-					'xiino'					=> "Xiino",
-					'novarra'				=> "Novarra Transcoder",
-					'vodafone'				=> "Vodafone",
-					'docomo'				=> "NTT DoCoMo",
-					'o2'					=> "O2",
-
-					// Fallback
-					'mobile'				=> "Generic Mobile",
-					'wireless' 				=> "Generic Mobile",
-					'j2me'					=> "Generic Mobile",
-					'midp'					=> "Generic Mobile",
-					'cldc'					=> "Generic Mobile",
-					'up.link'				=> "Generic Mobile",
-					'up.browser'			=> "Generic Mobile",
-					'smartphone'			=> "Generic Mobile",
-					'cellphone'				=> "Generic Mobile"
-				);
-
-// There are hundreds of bots but these are the most common.
-$robots = array(
-					'googlebot'			=> 'Googlebot',
-					'msnbot'			=> 'MSNBot',
-					'slurp'				=> 'Inktomi Slurp',
-					'yahoo'				=> 'Yahoo',
-					'askjeeves'			=> 'AskJeeves',
-					'fastcrawler'		=> 'FastCrawler',
-					'infoseek'			=> 'InfoSeek Robot 1.0',
-					'lycos'				=> 'Lycos'
-				);
-
-/* End of file user_agents.php */
+<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

+/*

+| -------------------------------------------------------------------

+| USER AGENT TYPES

+| -------------------------------------------------------------------

+| This file contains four arrays of user agent data.  It is used by the

+| User Agent Class to help identify browser, platform, robot, and

+| mobile device data.  The array keys are used to identify the device

+| and the array values are used to set the actual name of the item.

+|

+*/

+

+$platforms = array (

+					'windows nt 6.0'	=> 'Windows Longhorn',

+					'windows nt 5.2'	=> 'Windows 2003',

+					'windows nt 5.0'	=> 'Windows 2000',

+					'windows nt 5.1'	=> 'Windows XP',

+					'windows nt 4.0'	=> 'Windows NT 4.0',

+					'winnt4.0'			=> 'Windows NT 4.0',

+					'winnt 4.0'			=> 'Windows NT',

+					'winnt'				=> 'Windows NT',

+					'windows 98'		=> 'Windows 98',

+					'win98'				=> 'Windows 98',

+					'windows 95'		=> 'Windows 95',

+					'win95'				=> 'Windows 95',

+					'windows'			=> 'Unknown Windows OS',

+					'os x'				=> 'Mac OS X',

+					'ppc mac'			=> 'Power PC Mac',

+					'freebsd'			=> 'FreeBSD',

+					'ppc'				=> 'Macintosh',

+					'linux'				=> 'Linux',

+					'debian'			=> 'Debian',

+					'sunos'				=> 'Sun Solaris',

+					'beos'				=> 'BeOS',

+					'apachebench'		=> 'ApacheBench',

+					'aix'				=> 'AIX',

+					'irix'				=> 'Irix',

+					'osf'				=> 'DEC OSF',

+					'hp-ux'				=> 'HP-UX',

+					'netbsd'			=> 'NetBSD',

+					'bsdi'				=> 'BSDi',

+					'openbsd'			=> 'OpenBSD',

+					'gnu'				=> 'GNU/Linux',

+					'unix'				=> 'Unknown Unix OS'

+				);

+

+

+// The order of this array should NOT be changed. Many browsers return

+// multiple browser types so we want to identify the sub-type first.

+$browsers = array(

+					'Opera'				=> 'Opera',

+					'MSIE'				=> 'Internet Explorer',

+					'Internet Explorer'	=> 'Internet Explorer',

+					'Shiira'			=> 'Shiira',

+					'Firefox'			=> 'Firefox',

+					'Chimera'			=> 'Chimera',

+					'Phoenix'			=> 'Phoenix',

+					'Firebird'			=> 'Firebird',

+					'Camino'			=> 'Camino',

+					'Netscape'			=> 'Netscape',

+					'OmniWeb'			=> 'OmniWeb',

+					'Mozilla'			=> 'Mozilla',

+					'Safari'			=> 'Safari',

+					'Konqueror'			=> 'Konqueror',

+					'icab'				=> 'iCab',

+					'Lynx'				=> 'Lynx',

+					'Links'				=> 'Links',

+					'hotjava'			=> 'HotJava',

+					'amaya'				=> 'Amaya',

+					'IBrowse'			=> 'IBrowse'

+				);

+

+$mobiles = array(

+					// legacy array, old values commented out

+					'mobileexplorer'	=> 'Mobile Explorer',

+//					'openwave'			=> 'Open Wave',

+//					'opera mini'		=> 'Opera Mini',

+//					'operamini'			=> 'Opera Mini',

+//					'elaine'			=> 'Palm',

+					'palmsource'		=> 'Palm',

+//					'digital paths'		=> 'Palm',

+//					'avantgo'			=> 'Avantgo',

+//					'xiino'				=> 'Xiino',

+					'palmscape'			=> 'Palmscape',

+//					'nokia'				=> 'Nokia',

+//					'ericsson'			=> 'Ericsson',

+//					'blackberry'		=> 'BlackBerry',

+//					'motorola'			=> 'Motorola'

+

+					// Phones and Manufacturers

+					'motorola'			=> "Motorola",

+					'nokia'				=> "Nokia",

+					'palm'				=> "Palm",

+					'iphone'			=> "Apple iPhone",

+					'ipod'				=> "Apple iPod Touch",

+					'sony'				=> "Sony Ericsson",

+					'ericsson'			=> "Sony Ericsson",

+					'blackberry'		=> "BlackBerry",

+					'cocoon'			=> "O2 Cocoon",

+					'blazer'			=> "Treo",

+					'lg'				=> "LG",

+					'amoi'				=> "Amoi",

+					'xda'				=> "XDA",

+					'mda'				=> "MDA",

+					'vario'				=> "Vario",

+					'htc'				=> "HTC",

+					'samsung'			=> "Samsung",

+					'sharp'				=> "Sharp",

+					'sie-'				=> "Siemens",

+					'alcatel'			=> "Alcatel",

+					'benq'				=> "BenQ",

+					'ipaq'				=> "HP iPaq",

+					'mot-'				=> "Motorola",

+					'playstation portable' 	=> "PlayStation Portable",

+					'hiptop'			=> "Danger Hiptop",

+					'nec-'				=> "NEC",

+					'panasonic'			=> "Panasonic",

+					'philips'			=> "Philips",

+					'sagem'				=> "Sagem",

+					'sanyo'				=> "Sanyo",

+					'spv'				=> "SPV",

+					'zte'				=> "ZTE",

+					'sendo'				=> "Sendo",

+

+					// Operating Systems

+					'symbian'				=> "Symbian",

+					'SymbianOS'				=> "SymbianOS", 

+					'elaine'				=> "Palm",

+					'palm'					=> "Palm",

+					'series60'				=> "Symbian S60",

+					'windows ce'			=> "Windows CE",

+

+					// Browsers

+					'obigo'					=> "Obigo",

+					'netfront'				=> "Netfront Browser",

+					'openwave'				=> "Openwave Browser",

+					'mobilexplorer'			=> "Mobile Explorer",

+					'operamini'				=> "Opera Mini",

+					'opera mini'			=> "Opera Mini",

+

+					// Other

+					'digital paths'			=> "Digital Paths",

+					'avantgo'				=> "AvantGo",

+					'xiino'					=> "Xiino",

+					'novarra'				=> "Novarra Transcoder",

+					'vodafone'				=> "Vodafone",

+					'docomo'				=> "NTT DoCoMo",

+					'o2'					=> "O2",

+

+					// Fallback

+					'mobile'				=> "Generic Mobile",

+					'wireless' 				=> "Generic Mobile",

+					'j2me'					=> "Generic Mobile",

+					'midp'					=> "Generic Mobile",

+					'cldc'					=> "Generic Mobile",

+					'up.link'				=> "Generic Mobile",

+					'up.browser'			=> "Generic Mobile",

+					'smartphone'			=> "Generic Mobile",

+					'cellphone'				=> "Generic Mobile"

+				);

+

+// There are hundreds of bots but these are the most common.

+$robots = array(

+					'googlebot'			=> 'Googlebot',

+					'msnbot'			=> 'MSNBot',

+					'slurp'				=> 'Inktomi Slurp',

+					'yahoo'				=> 'Yahoo',

+					'askjeeves'			=> 'AskJeeves',

+					'fastcrawler'		=> 'FastCrawler',

+					'infoseek'			=> 'InfoSeek Robot 1.0',

+					'lycos'				=> 'Lycos'

+				);

+

+/* End of file user_agents.php */

 /* Location: ./system/application/config/user_agents.php */
\ No newline at end of file
diff --git a/system/application/errors/error_404.php b/system/application/errors/error_404.php
index bfe9444..cad7375 100644
--- a/system/application/errors/error_404.php
+++ b/system/application/errors/error_404.php
@@ -1,35 +1,35 @@
-<?php header("HTTP/1.1 404 Not Found"); ?>
-<html>
-<head>
-<title>404 Page Not Found</title>
-<style type="text/css">
-
-body {
-background-color:	#fff;
-margin:				40px;
-font-family:		Lucida Grande, Verdana, Sans-serif;
-font-size:			12px;
-color:				#000;
-}
-
-#content  {
-border:				#999 1px solid;
-background-color:	#fff;
-padding:			20px 20px 12px 20px;
-}
-
-h1 {
-font-weight:		normal;
-font-size:			14px;
-color:				#990000;
-margin: 			0 0 4px 0;
-}
-</style>
-</head>
-<body>
-	<div id="content">
-		<h1><?php echo $heading; ?></h1>
-		<?php echo $message; ?>
-	</div>
-</body>
+<?php header("HTTP/1.1 404 Not Found"); ?>

+<html>

+<head>

+<title>404 Page Not Found</title>

+<style type="text/css">

+

+body {

+background-color:	#fff;

+margin:				40px;

+font-family:		Lucida Grande, Verdana, Sans-serif;

+font-size:			12px;

+color:				#000;

+}

+

+#content  {

+border:				#999 1px solid;

+background-color:	#fff;

+padding:			20px 20px 12px 20px;

+}

+

+h1 {

+font-weight:		normal;

+font-size:			14px;

+color:				#990000;

+margin: 			0 0 4px 0;

+}

+</style>

+</head>

+<body>

+	<div id="content">

+		<h1><?php echo $heading; ?></h1>

+		<?php echo $message; ?>

+	</div>

+</body>

 </html>
\ No newline at end of file
diff --git a/system/application/errors/error_db.php b/system/application/errors/error_db.php
index 1ce52df..71a4b98 100644
--- a/system/application/errors/error_db.php
+++ b/system/application/errors/error_db.php
@@ -1,34 +1,34 @@
-<html>
-<head>
-<title>Database Error</title>
-<style type="text/css">
-
-body {
-background-color:	#fff;
-margin:				40px;
-font-family:		Lucida Grande, Verdana, Sans-serif;
-font-size:			12px;
-color:				#000;
-}
-
-#content  {
-border:				#999 1px solid;
-background-color:	#fff;
-padding:			20px 20px 12px 20px;
-}
-
-h1 {
-font-weight:		normal;
-font-size:			14px;
-color:				#990000;
-margin: 			0 0 4px 0;
-}
-</style>
-</head>
-<body>
-	<div id="content">
-		<h1><?php echo $heading; ?></h1>
-		<?php echo $message; ?>
-	</div>
-</body>
+<html>

+<head>

+<title>Database Error</title>

+<style type="text/css">

+

+body {

+background-color:	#fff;

+margin:				40px;

+font-family:		Lucida Grande, Verdana, Sans-serif;

+font-size:			12px;

+color:				#000;

+}

+

+#content  {

+border:				#999 1px solid;

+background-color:	#fff;

+padding:			20px 20px 12px 20px;

+}

+

+h1 {

+font-weight:		normal;

+font-size:			14px;

+color:				#990000;

+margin: 			0 0 4px 0;

+}

+</style>

+</head>

+<body>

+	<div id="content">

+		<h1><?php echo $heading; ?></h1>

+		<?php echo $message; ?>

+	</div>

+</body>

 </html>
\ No newline at end of file
diff --git a/system/application/errors/error_general.php b/system/application/errors/error_general.php
index d861070..8545286 100644
--- a/system/application/errors/error_general.php
+++ b/system/application/errors/error_general.php
@@ -1,34 +1,34 @@
-<html>
-<head>
-<title>Error</title>
-<style type="text/css">
-
-body {
-background-color:	#fff;
-margin:				40px;
-font-family:		Lucida Grande, Verdana, Sans-serif;
-font-size:			12px;
-color:				#000;
-}
-
-#content  {
-border:				#999 1px solid;
-background-color:	#fff;
-padding:			20px 20px 12px 20px;
-}
-
-h1 {
-font-weight:		normal;
-font-size:			14px;
-color:				#990000;
-margin: 			0 0 4px 0;
-}
-</style>
-</head>
-<body>
-	<div id="content">
-		<h1><?php echo $heading; ?></h1>
-		<?php echo $message; ?>
-	</div>
-</body>
+<html>

+<head>

+<title>Error</title>

+<style type="text/css">

+

+body {

+background-color:	#fff;

+margin:				40px;

+font-family:		Lucida Grande, Verdana, Sans-serif;

+font-size:			12px;

+color:				#000;

+}

+

+#content  {

+border:				#999 1px solid;

+background-color:	#fff;

+padding:			20px 20px 12px 20px;

+}

+

+h1 {

+font-weight:		normal;

+font-size:			14px;

+color:				#990000;

+margin: 			0 0 4px 0;

+}

+</style>

+</head>

+<body>

+	<div id="content">

+		<h1><?php echo $heading; ?></h1>

+		<?php echo $message; ?>

+	</div>

+</body>

 </html>
\ No newline at end of file
diff --git a/system/application/errors/error_php.php b/system/application/errors/error_php.php
index f085c20..f5941c9 100644
--- a/system/application/errors/error_php.php
+++ b/system/application/errors/error_php.php
@@ -1,10 +1,10 @@
-<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">
-
-<h4>A PHP Error was encountered</h4>
-
-<p>Severity: <?php echo $severity; ?></p>
-<p>Message:  <?php echo $message; ?></p>
-<p>Filename: <?php echo $filepath; ?></p>
-<p>Line Number: <?php echo $line; ?></p>
-
+<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">

+

+<h4>A PHP Error was encountered</h4>

+

+<p>Severity: <?php echo $severity; ?></p>

+<p>Message:  <?php echo $message; ?></p>

+<p>Filename: <?php echo $filepath; ?></p>

+<p>Line Number: <?php echo $line; ?></p>

+

 </div>
\ No newline at end of file
diff --git a/system/helpers/compatibility_helper.php b/system/helpers/compatibility_helper.php
index 3b37cea..996a6d7 100644
--- a/system/helpers/compatibility_helper.php
+++ b/system/helpers/compatibility_helper.php
@@ -1,498 +1,498 @@
-<?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 Compatibility Helpers
- *
- * This helper contains some functions based on the PEAR PHP_Compat library
- * http://pear.php.net/package/PHP_Compat
- * 
- * The PEAR compat library is a little bloated and the code doesn't harmonize
- * well with CodeIgniter, so those functions have been refactored.
- * We cheat a little and use CI's _exception_handler() to output our own PHP errors
- * so that the behavior fully mimicks the PHP 5 counterparts.  -- Derek Jones
- * 
- * @package		CodeIgniter
- * @subpackage	Helpers
- * @category	Helpers
- * @author		ExpressionEngine Dev Team
- * @link		http://codeigniter.com/user_guide/helpers/compatibility_helper.html
- */
-
-// ------------------------------------------------------------------------
-
-if ( ! defined('PHP_EOL'))
-{
-	define('PHP_EOL', (DIRECTORY_SEPARATOR == '/') ? "\n" : "\r\n");
-} 
-
-// ------------------------------------------------------------------------
-
-/**
- * file_put_contents()
- *
- * Writes a string to a file
- * http://us.php.net/manual/en/function.file_put_contents.php
- * argument 4, $context, not supported
- *
- * @access	public
- * @param	string		file name
- * @param	mixed		data to be written
- * @param	int			flags
- * @return	int			length of written string
- */
-if ( ! function_exists('file_put_contents'))
-{
-	function file_put_contents($filename, $data, $flags = NULL)
-	{
-		if (is_scalar($data))
-		{
-			settype($data, 'STRING');
-		}
-
-		if ( ! is_string($data) && ! is_array($data) && ! is_resource($data))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'file_put_contents(): the 2nd parameter should be either a string or an array', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-
-		// read stream if given a stream resource
-		if (is_resource($data))
-		{
-			if (get_resource_type($data) !== 'stream')
-			{
-				$backtrace = debug_backtrace();
-				_exception_handler(E_USER_WARNING, 'file_put_contents(): supplied resource is not a valid stream resource', $backtrace[0]['file'], $backtrace[0]['line']);
-				return FALSE;
-			}
-
-			$text = '';
-			
-			while ( ! feof($data))
-			{
-				$text .= fread($data, 4096);
-			}
-			
-			$data = $text;
-			unset($text);
-		}
-	
-		// strings only please!
-		if (is_array($data))
-		{
-			$data = implode('', $data);
-		}
-
-		// Set the appropriate mode
-		if (($flags & 8) > 0) // 8 = FILE_APPEND flag
-		{
-			$mode = FOPEN_WRITE_CREATE;
-		}
-		else
-		{
-			$mode = FOPEN_WRITE_CREATE_DESTRUCTIVE;
-		}
-	
-		// Check if we're using the include path
-		if (($flags & 1) > 0) // 1 = FILE_USE_INCLUDE_PATH flag
-		{
-			$use_include_path = TRUE;
-		}
-		else
-		{
-			$use_include_path = FALSE;
-		}
-	
-		$fp = @fopen($filename, $mode, $use_include_path);
-	
-		if ($fp === FALSE)
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') failed to open stream', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		if (($flags & LOCK_EX) > 0)
-		{
-			if ( ! flock($fp, LOCK_EX))
-			{
-				$backtrace = debug_backtrace();
-				_exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') unable to acquire an exclusive lock on file', $backtrace[0]['file'], $backtrace[0]['line']);
-				return FALSE;
-			}
-		}
-		
-		// write it
-		if (($written = @fwrite($fp, $data)) === FALSE)
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') failed to write to '.htmlentities($filename), $backtrace[0]['file'], $backtrace[0]['line']);
-		}
-	
-		// Close the handle
-		@fclose($fp);
-	
-		// Return length
-		return $written;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * fputcsv()
- *
- * Format line as CSV and write to file pointer
- * http://us.php.net/manual/en/function.fputcsv.php
- *
- * @access	public
- * @param	resource	file pointer
- * @param	array		data to be written
- * @param	string		delimiter
- * @param	string		enclosure
- * @return	int			length of written string
- */
-if ( ! function_exists('fputcsv'))
-{
-	function fputcsv($handle, $fields, $delimiter = ',', $enclosure = '"')
-	{
-		// Checking for a handle resource
-		if ( ! is_resource($handle))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 1 to be stream resource, '.gettype($handle).' given', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		// OK, it is a resource, but is it a stream?
-		if (get_resource_type($handle) !== 'stream')
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 1 to be stream resource, '.get_resource_type($handle).' given', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		// Checking for an array of fields
-		if ( ! is_array($fields))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 2 to be array, '.gettype($fields).' given', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		// validate delimiter
-		if (strlen($delimiter) > 1)
-		{
-			$delimiter = substr($delimiter, 0, 1);
-			$backtrace = debug_backtrace();
-			_exception_handler(E_NOTICE, 'fputcsv() delimiter must be one character long, "'.htmlentities($delimiter).'" used', $backtrace[0]['file'], $backtrace[0]['line']);
-		}
-	
-		// validate enclosure
-		if (strlen($enclosure) > 1)
-		{
-			$enclosure = substr($enclosure, 0, 1);
-			$backtrace = debug_backtrace();
-			_exception_handler(E_NOTICE, 'fputcsv() enclosure must be one character long, "'.htmlentities($enclosure).'" used', $backtrace[0]['file'], $backtrace[0]['line']);
-
-		}
-	
-		$out = '';
-	
-		foreach ($fields as $cell)
-		{
-			$cell = str_replace($enclosure, $enclosure.$enclosure, $cell);
-
-			if (strpos($cell, $delimiter) !== FALSE OR strpos($cell, $enclosure) !== FALSE OR strpos($cell, "\n") !== FALSE)
-			{
-				$out .= $enclosure.$cell.$enclosure.$delimiter;
-			}
-			else
-			{
-				$out .= $cell.$delimiter;
-			}
-		}
-	
-		$length = @fwrite($handle, substr($out, 0, -1)."\n");
-	
-		return $length;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * stripos()
- *
- * Find position of first occurrence of a case-insensitive string
- * http://us.php.net/manual/en/function.stripos.php
- *
- * @access	public
- * @param	string		haystack
- * @param	string		needle
- * @param	int			offset
- * @return	int			numeric position of the first occurrence of needle in the haystack
- */
-if ( ! function_exists('stripos'))
-{
-	function stripos($haystack, $needle, $offset = NULL)
-	{
-		// Cast non string scalar values
-		if (is_scalar($haystack))
-		{
-			settype($haystack, 'STRING');
-		}
-	
-		if ( ! is_string($haystack))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'stripos() expects parameter 1 to be string, '.gettype($haystack).' given', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		if ( ! is_scalar($needle))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'stripos() needle is not a string or an integer in '.$backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		if (is_float($offset))
-		{
-			$offset = (int)$offset;
-		}
-	
-		if ( ! is_int($offset) && ! is_bool($offset) && ! is_null($offset))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'stripos() expects parameter 3 to be long, '.gettype($offset).' given', $backtrace[0]['file'], $backtrace[0]['line']);
-			return NULL;
-		}
-	
-		return strpos(strtolower($haystack), strtolower($needle), $offset);
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * str_ireplace()
- *
- * Find position of first occurrence of a case-insensitive string
- * http://us.php.net/manual/en/function.str-ireplace.php
- * (parameter 4, $count, is not supported as to do so in PHP 4 would make
- * it a required parameter)
- *
- * @access	public
- * @param	mixed		search
- * @param	mixed		replace
- * @param	mixed		subject
- * @return	int			numeric position of the first occurrence of needle in the haystack
- */
-if ( ! function_exists('str_ireplace'))
-{
-	function str_ireplace($search, $replace, $subject)
-	{
-		// Nothing to do here
-		if ($search === NULL OR $subject === NULL)
-		{
-			return $subject;
-		}
-	
-		// Crazy arguments
-		if (is_scalar($search) && is_array($replace))
-		{
-			$backtrace = debug_backtrace();
-
-			if (is_object($replace))
-			{
-				show_error('Object of class '.get_class($replace).' could not be converted to string in '.$backtrace[0]['file'].' on line '.$backtrace[0]['line']);
-			}
-			else
-			{
-				_exception_handler(E_USER_NOTICE, 'Array to string conversion in '.$backtrace[0]['file'], $backtrace[0]['line']);
-			}
-		}
-	
-		// Searching for an array
-		if (is_array($search))
-		{
-			// Replacing with an array
-			if (is_array($replace))
-			{
-				$search = array_values($search);
-				$replace = array_values($replace);
-
-				if (count($search) >= count($replace))
-				{
-					$replace = array_pad($replace, count($search), '');
-				}
-				else
-				{
-					$replace = array_slice($replace, 0, count($search));
-				}
-			}
-			else
-			{
-				// Replacing with a string all positions
-				$replace = array_fill(0, count($search), $replace);
-			}
-		}
-		else
-		{
-			//Searching for a string and replacing with a string.
-			$search  = array((string)$search);
-			$replace = array((string)$replace);
-		}
-		
-		// Prepare the search array
-		foreach ($search as $search_key => $search_value)
-		{
-			$search[$search_key] = '/'.preg_quote($search_value, '/').'/i';
-		}
-		
-		// Prepare the replace array (escape backreferences)
-		foreach ($replace as $k => $v)
-		{
-			$replace[$k] = str_replace(array(chr(92), '$'), array(chr(92).chr(92), '\$'), $v);
-		}
-	
-		// do the replacement
-		$result = preg_replace($search, $replace, (array)$subject);
-	
-		// Check if subject was initially a string and return it as a string
-		if ( ! is_array($subject))
-		{
-			return current($result);
-		}
-	
-		// Otherwise, just return the array
-		return $result;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * http_build_query()
- *
- * Generate URL-encoded query string
- * http://us.php.net/manual/en/function.http-build-query.php
- *
- * @access	public
- * @param	array		form data
- * @param	string		numeric prefix
- * @param	string		argument separator
- * @return	string		URL-encoded string
- */
-if ( ! function_exists('http_build_query'))
-{
-	function http_build_query($formdata, $numeric_prefix = NULL, $separator = NULL)
-	{
-		// Check the data
-		if ( ! is_array($formdata) && ! is_object($formdata))
-		{
-			$backtrace = debug_backtrace();
-			_exception_handler(E_USER_WARNING, 'http_build_query() Parameter 1 expected to be Array or Object. Incorrect value given', $backtrace[0]['file'], $backtrace[0]['line']);
-			return FALSE;
-		}
-	
-		// Cast it as array
-		if (is_object($formdata))
-		{
-			$formdata = get_object_vars($formdata);
-		}
-	
-		// If the array is empty, return NULL
-		if (empty($formdata))
-		{
-			return NULL;
-		}
-	
-		// Argument separator
-		if ($separator === NULL)
-		{
-			$separator = ini_get('arg_separator.output');
-
-			if (strlen($separator) == 0)
-			{
-				$separator = '&';
-			}
-		}
-	
-		// Start building the query
-		$tmp = array();
-
-		foreach ($formdata as $key => $val)
-		{
-			if ($val === NULL)
-			{
-				continue;
-			}
-	
-			if (is_integer($key) && $numeric_prefix != NULL)
-			{
-				$key = $numeric_prefix.$key;
-			}
-	
-			if (is_resource($val))
-			{
-				return NULL;
-			}
-			
-			// hand it off to a recursive parser
-			$tmp[] = _http_build_query_helper($key, $val, $separator);
-		}
-	
-		return implode($separator, $tmp);
-	}
-	
-	
-	// Helper helper.  Remind anyone of college?
-	// Required to handle recursion in nested arrays.
-	// 
-	// You could shave fractions of fractions of a second by moving where
-	// the urlencoding takes place, but it's much less intuitive, and if
-	// your application has 10,000 form fields, well, you have other problems ;)
-	function _http_build_query_helper($key, $val, $separator = '&')
-	{	
-		if (is_scalar($val))
-		{
-			return urlencode($key).'='.urlencode($val);			
-		}
-		else
-		{
-			// arrays please
-			if (is_object($val))
-			{
-				$val = get_object_vars($val);
-			}
-			
-			foreach ($val as $k => $v)
-			{
-				$tmp[] = _http_build_query_helper($key.'['.$k.']', $v, $separator);
-			}
-		}
-			
-		return implode($separator, $tmp);
-	}
-}
-
-
-/* End of file compatibility_helper.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 Compatibility Helpers

+ *

+ * This helper contains some functions based on the PEAR PHP_Compat library

+ * http://pear.php.net/package/PHP_Compat

+ * 

+ * The PEAR compat library is a little bloated and the code doesn't harmonize

+ * well with CodeIgniter, so those functions have been refactored.

+ * We cheat a little and use CI's _exception_handler() to output our own PHP errors

+ * so that the behavior fully mimicks the PHP 5 counterparts.  -- Derek Jones

+ * 

+ * @package		CodeIgniter

+ * @subpackage	Helpers

+ * @category	Helpers

+ * @author		ExpressionEngine Dev Team

+ * @link		http://codeigniter.com/user_guide/helpers/compatibility_helper.html

+ */

+

+// ------------------------------------------------------------------------

+

+if ( ! defined('PHP_EOL'))

+{

+	define('PHP_EOL', (DIRECTORY_SEPARATOR == '/') ? "\n" : "\r\n");

+} 

+

+// ------------------------------------------------------------------------

+

+/**

+ * file_put_contents()

+ *

+ * Writes a string to a file

+ * http://us.php.net/manual/en/function.file_put_contents.php

+ * argument 4, $context, not supported

+ *

+ * @access	public

+ * @param	string		file name

+ * @param	mixed		data to be written

+ * @param	int			flags

+ * @return	int			length of written string

+ */

+if ( ! function_exists('file_put_contents'))

+{

+	function file_put_contents($filename, $data, $flags = NULL)

+	{

+		if (is_scalar($data))

+		{

+			settype($data, 'STRING');

+		}

+

+		if ( ! is_string($data) && ! is_array($data) && ! is_resource($data))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'file_put_contents(): the 2nd parameter should be either a string or an array', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+

+		// read stream if given a stream resource

+		if (is_resource($data))

+		{

+			if (get_resource_type($data) !== 'stream')

+			{

+				$backtrace = debug_backtrace();

+				_exception_handler(E_USER_WARNING, 'file_put_contents(): supplied resource is not a valid stream resource', $backtrace[0]['file'], $backtrace[0]['line']);

+				return FALSE;

+			}

+

+			$text = '';

+			

+			while ( ! feof($data))

+			{

+				$text .= fread($data, 4096);

+			}

+			

+			$data = $text;

+			unset($text);

+		}

+	

+		// strings only please!

+		if (is_array($data))

+		{

+			$data = implode('', $data);

+		}

+

+		// Set the appropriate mode

+		if (($flags & 8) > 0) // 8 = FILE_APPEND flag

+		{

+			$mode = FOPEN_WRITE_CREATE;

+		}

+		else

+		{

+			$mode = FOPEN_WRITE_CREATE_DESTRUCTIVE;

+		}

+	

+		// Check if we're using the include path

+		if (($flags & 1) > 0) // 1 = FILE_USE_INCLUDE_PATH flag

+		{

+			$use_include_path = TRUE;

+		}

+		else

+		{

+			$use_include_path = FALSE;

+		}

+	

+		$fp = @fopen($filename, $mode, $use_include_path);

+	

+		if ($fp === FALSE)

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') failed to open stream', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		if (($flags & LOCK_EX) > 0)

+		{

+			if ( ! flock($fp, LOCK_EX))

+			{

+				$backtrace = debug_backtrace();

+				_exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') unable to acquire an exclusive lock on file', $backtrace[0]['file'], $backtrace[0]['line']);

+				return FALSE;

+			}

+		}

+		

+		// write it

+		if (($written = @fwrite($fp, $data)) === FALSE)

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') failed to write to '.htmlentities($filename), $backtrace[0]['file'], $backtrace[0]['line']);

+		}

+	

+		// Close the handle

+		@fclose($fp);

+	

+		// Return length

+		return $written;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * fputcsv()

+ *

+ * Format line as CSV and write to file pointer

+ * http://us.php.net/manual/en/function.fputcsv.php

+ *

+ * @access	public

+ * @param	resource	file pointer

+ * @param	array		data to be written

+ * @param	string		delimiter

+ * @param	string		enclosure

+ * @return	int			length of written string

+ */

+if ( ! function_exists('fputcsv'))

+{

+	function fputcsv($handle, $fields, $delimiter = ',', $enclosure = '"')

+	{

+		// Checking for a handle resource

+		if ( ! is_resource($handle))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 1 to be stream resource, '.gettype($handle).' given', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		// OK, it is a resource, but is it a stream?

+		if (get_resource_type($handle) !== 'stream')

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 1 to be stream resource, '.get_resource_type($handle).' given', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		// Checking for an array of fields

+		if ( ! is_array($fields))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 2 to be array, '.gettype($fields).' given', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		// validate delimiter

+		if (strlen($delimiter) > 1)

+		{

+			$delimiter = substr($delimiter, 0, 1);

+			$backtrace = debug_backtrace();

+			_exception_handler(E_NOTICE, 'fputcsv() delimiter must be one character long, "'.htmlentities($delimiter).'" used', $backtrace[0]['file'], $backtrace[0]['line']);

+		}

+	

+		// validate enclosure

+		if (strlen($enclosure) > 1)

+		{

+			$enclosure = substr($enclosure, 0, 1);

+			$backtrace = debug_backtrace();

+			_exception_handler(E_NOTICE, 'fputcsv() enclosure must be one character long, "'.htmlentities($enclosure).'" used', $backtrace[0]['file'], $backtrace[0]['line']);

+

+		}

+	

+		$out = '';

+	

+		foreach ($fields as $cell)

+		{

+			$cell = str_replace($enclosure, $enclosure.$enclosure, $cell);

+

+			if (strpos($cell, $delimiter) !== FALSE OR strpos($cell, $enclosure) !== FALSE OR strpos($cell, "\n") !== FALSE)

+			{

+				$out .= $enclosure.$cell.$enclosure.$delimiter;

+			}

+			else

+			{

+				$out .= $cell.$delimiter;

+			}

+		}

+	

+		$length = @fwrite($handle, substr($out, 0, -1)."\n");

+	

+		return $length;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * stripos()

+ *

+ * Find position of first occurrence of a case-insensitive string

+ * http://us.php.net/manual/en/function.stripos.php

+ *

+ * @access	public

+ * @param	string		haystack

+ * @param	string		needle

+ * @param	int			offset

+ * @return	int			numeric position of the first occurrence of needle in the haystack

+ */

+if ( ! function_exists('stripos'))

+{

+	function stripos($haystack, $needle, $offset = NULL)

+	{

+		// Cast non string scalar values

+		if (is_scalar($haystack))

+		{

+			settype($haystack, 'STRING');

+		}

+	

+		if ( ! is_string($haystack))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'stripos() expects parameter 1 to be string, '.gettype($haystack).' given', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		if ( ! is_scalar($needle))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'stripos() needle is not a string or an integer in '.$backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		if (is_float($offset))

+		{

+			$offset = (int)$offset;

+		}

+	

+		if ( ! is_int($offset) && ! is_bool($offset) && ! is_null($offset))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'stripos() expects parameter 3 to be long, '.gettype($offset).' given', $backtrace[0]['file'], $backtrace[0]['line']);

+			return NULL;

+		}

+	

+		return strpos(strtolower($haystack), strtolower($needle), $offset);

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * str_ireplace()

+ *

+ * Find position of first occurrence of a case-insensitive string

+ * http://us.php.net/manual/en/function.str-ireplace.php

+ * (parameter 4, $count, is not supported as to do so in PHP 4 would make

+ * it a required parameter)

+ *

+ * @access	public

+ * @param	mixed		search

+ * @param	mixed		replace

+ * @param	mixed		subject

+ * @return	int			numeric position of the first occurrence of needle in the haystack

+ */

+if ( ! function_exists('str_ireplace'))

+{

+	function str_ireplace($search, $replace, $subject)

+	{

+		// Nothing to do here

+		if ($search === NULL OR $subject === NULL)

+		{

+			return $subject;

+		}

+	

+		// Crazy arguments

+		if (is_scalar($search) && is_array($replace))

+		{

+			$backtrace = debug_backtrace();

+

+			if (is_object($replace))

+			{

+				show_error('Object of class '.get_class($replace).' could not be converted to string in '.$backtrace[0]['file'].' on line '.$backtrace[0]['line']);

+			}

+			else

+			{

+				_exception_handler(E_USER_NOTICE, 'Array to string conversion in '.$backtrace[0]['file'], $backtrace[0]['line']);

+			}

+		}

+	

+		// Searching for an array

+		if (is_array($search))

+		{

+			// Replacing with an array

+			if (is_array($replace))

+			{

+				$search = array_values($search);

+				$replace = array_values($replace);

+

+				if (count($search) >= count($replace))

+				{

+					$replace = array_pad($replace, count($search), '');

+				}

+				else

+				{

+					$replace = array_slice($replace, 0, count($search));

+				}

+			}

+			else

+			{

+				// Replacing with a string all positions

+				$replace = array_fill(0, count($search), $replace);

+			}

+		}

+		else

+		{

+			//Searching for a string and replacing with a string.

+			$search  = array((string)$search);

+			$replace = array((string)$replace);

+		}

+		

+		// Prepare the search array

+		foreach ($search as $search_key => $search_value)

+		{

+			$search[$search_key] = '/'.preg_quote($search_value, '/').'/i';

+		}

+		

+		// Prepare the replace array (escape backreferences)

+		foreach ($replace as $k => $v)

+		{

+			$replace[$k] = str_replace(array(chr(92), '$'), array(chr(92).chr(92), '\$'), $v);

+		}

+	

+		// do the replacement

+		$result = preg_replace($search, $replace, (array)$subject);

+	

+		// Check if subject was initially a string and return it as a string

+		if ( ! is_array($subject))

+		{

+			return current($result);

+		}

+	

+		// Otherwise, just return the array

+		return $result;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * http_build_query()

+ *

+ * Generate URL-encoded query string

+ * http://us.php.net/manual/en/function.http-build-query.php

+ *

+ * @access	public

+ * @param	array		form data

+ * @param	string		numeric prefix

+ * @param	string		argument separator

+ * @return	string		URL-encoded string

+ */

+if ( ! function_exists('http_build_query'))

+{

+	function http_build_query($formdata, $numeric_prefix = NULL, $separator = NULL)

+	{

+		// Check the data

+		if ( ! is_array($formdata) && ! is_object($formdata))

+		{

+			$backtrace = debug_backtrace();

+			_exception_handler(E_USER_WARNING, 'http_build_query() Parameter 1 expected to be Array or Object. Incorrect value given', $backtrace[0]['file'], $backtrace[0]['line']);

+			return FALSE;

+		}

+	

+		// Cast it as array

+		if (is_object($formdata))

+		{

+			$formdata = get_object_vars($formdata);

+		}

+	

+		// If the array is empty, return NULL

+		if (empty($formdata))

+		{

+			return NULL;

+		}

+	

+		// Argument separator

+		if ($separator === NULL)

+		{

+			$separator = ini_get('arg_separator.output');

+

+			if (strlen($separator) == 0)

+			{

+				$separator = '&';

+			}

+		}

+	

+		// Start building the query

+		$tmp = array();

+

+		foreach ($formdata as $key => $val)

+		{

+			if ($val === NULL)

+			{

+				continue;

+			}

+	

+			if (is_integer($key) && $numeric_prefix != NULL)

+			{

+				$key = $numeric_prefix.$key;

+			}

+	

+			if (is_resource($val))

+			{

+				return NULL;

+			}

+			

+			// hand it off to a recursive parser

+			$tmp[] = _http_build_query_helper($key, $val, $separator);

+		}

+	

+		return implode($separator, $tmp);

+	}

+	

+	

+	// Helper helper.  Remind anyone of college?

+	// Required to handle recursion in nested arrays.

+	// 

+	// You could shave fractions of fractions of a second by moving where

+	// the urlencoding takes place, but it's much less intuitive, and if

+	// your application has 10,000 form fields, well, you have other problems ;)

+	function _http_build_query_helper($key, $val, $separator = '&')

+	{	

+		if (is_scalar($val))

+		{

+			return urlencode($key).'='.urlencode($val);			

+		}

+		else

+		{

+			// arrays please

+			if (is_object($val))

+			{

+				$val = get_object_vars($val);

+			}

+			

+			foreach ($val as $k => $v)

+			{

+				$tmp[] = _http_build_query_helper($key.'['.$k.']', $v, $separator);

+			}

+		}

+			

+		return implode($separator, $tmp);

+	}

+}

+

+

+/* End of file compatibility_helper.php */

 /* Location: ./system/helpers/compatibility_helper.php */
\ No newline at end of file
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index e552b86..cc34b65 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -1,416 +1,416 @@
-<?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 HTML Helpers
- *
- * @package		CodeIgniter
- * @subpackage	Helpers
- * @category	Helpers
- * @author		ExpressionEngine Dev Team
- * @link		http://codeigniter.com/user_guide/helpers/html_helper.html
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Heading
- *
- * Generates an HTML heading tag.  First param is the data.
- * Second param is the size of the heading tag.
- *
- * @access	public
- * @param	string
- * @param	integer
- * @return	string
- */
-if ( ! function_exists('heading'))
-{
-	function heading($data = '', $h = '1')
-	{
-		return "<h".$h.">".$data."</h".$h.">";
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Unordered List
- *
- * Generates an HTML unordered list from an single or multi-dimensional array.
- *
- * @access	public
- * @param	array
- * @param	mixed
- * @return	string
- */
-if ( ! function_exists('ul'))
-{
-	function ul($list, $attributes = '')
-	{
-		return _list('ul', $list, $attributes);
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Ordered List
- *
- * Generates an HTML ordered list from an single or multi-dimensional array.
- *
- * @access	public
- * @param	array
- * @param	mixed
- * @return	string
- */
-if ( ! function_exists('ol'))
-{
-	function ol($list, $attributes = '')
-	{
-		return _list('ol', $list, $attributes);
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Generates the list
- *
- * Generates an HTML ordered list from an single or multi-dimensional array.
- *
- * @access	private
- * @param	string
- * @param	mixed
- * @param	mixed
- * @param	intiger
- * @return	string
- */
-if ( ! function_exists('_list'))
-{
-	function _list($type = 'ul', $list, $attributes = '', $depth = 0)
-	{
-		// If an array wasn't submitted there's nothing to do...
-		if ( ! is_array($list))
-		{
-			return $list;
-		}
-
-		// Set the indentation based on the depth
-		$out = str_repeat(" ", $depth);
-
-		// Were any attributes submitted?  If so generate a string
-		if (is_array($attributes))
-		{
-			$atts = '';
-			foreach ($attributes as $key => $val)
-			{
-				$atts .= ' ' . $key . '="' . $val . '"';
-			}
-			$attributes = $atts;
-		}
-
-		// Write the opening list tag
-		$out .= "<".$type.$attributes.">\n";
-
-		// Cycle through the list elements.  If an array is
-		// encountered we will recursively call _list()
-
-		static $_last_list_item = '';
-		foreach ($list as $key => $val)
-		{
-			$_last_list_item = $key;
-
-			$out .= str_repeat(" ", $depth + 2);
-			$out .= "<li>";
-
-			if ( ! is_array($val))
-			{
-				$out .= $val;
-			}
-			else
-			{
-				$out .= $_last_list_item."\n";
-				$out .= _list($type, $val, '', $depth + 4);
-				$out .= str_repeat(" ", $depth + 2);
-			}
-
-			$out .= "</li>\n";
-		}
-
-		// Set the indentation for the closing tag
-		$out .= str_repeat(" ", $depth);
-
-		// Write the closing list tag
-		$out .= "</".$type.">\n";
-
-		return $out;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Generates HTML BR tags based on number supplied
- *
- * @access	public
- * @param	integer
- * @return	string
- */
-if ( ! function_exists('br'))
-{
-	function br($num = 1)
-	{
-		return str_repeat("<br />", $num);
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Image
- *
- * Generates an <img /> element
- *
- * @access	public
- * @param	mixed
- * @return	string
- */
-if ( ! function_exists('img'))
-{
-	function img($src = '', $index_page = FALSE)
-	{
-		if ( ! is_array($src) )
-		{
-			$src = array('src' => $src);
-		}
-
-		$img = '<img';
-
-		foreach ($src as $k=>$v)
-		{
-
-			if ($k == 'src' AND strpos($v, '://') === FALSE)
-			{
-				$CI =& get_instance();
-
-				if ($index_page === TRUE)
-				{
-					$img .= ' src="'.$CI->config->site_url($v).'" ';
-				}
-				else
-				{
-					$img .= ' src="'.$CI->config->slash_item('base_url').$v.'" ';
-				}
-			}
-			else
-			{
-				$img .= " $k=\"$v\" ";
-			}
-		}
-
-		$img .= '/>';
-
-		return $img;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Doctype
- *
- * Generates a page document type declaration
- *
- * Valid options are xhtml-11, xhtml-strict, xhtml-trans, xhtml-frame,
- * html4-strict, html4-trans, and html4-frame.  Values are saved in the
- * doctypes config file.
- *
- * @access	public
- * @param	string	type	The doctype to be generated
- * @return	string
- */
-if ( ! function_exists('doctype'))
-{
-	function doctype($type = 'xhtml-strict')
-	{
-		global $_doctypes;
-
-		if ( ! is_array($_doctypes))
-		{
-			if ( ! require_once(APPPATH.'config/doctypes.php'))
-			{
-				return FALSE;
-			}
-		}
-
-		if (isset($_doctypes[$type]))
-		{
-			return $_doctypes[$type];
-		}
-		else
-		{
-			return FALSE;
-		}
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Link
- *
- * Generates link to a CSS file
- *
- * @access	public
- * @param	mixed	stylesheet hrefs or an array
- * @param	string	rel
- * @param	string	type
- * @param	string	title
- * @param	string	media
- * @param	boolean	should index_page be added to the css path
- * @return	string
- */
-if ( ! function_exists('link_tag'))
-{
-	function link_tag($href = '', $rel = 'stylesheet', $type = 'text/css', $title = '', $media = '', $index_page = FALSE)
-	{
-		$CI =& get_instance();
-
-		$link = '<link ';
-
-		if (is_array($href))
-		{
-			foreach ($href as $k=>$v)
-			{
-				if ($k == 'href' AND strpos($v, '://') === FALSE)
-				{
-					if ($index_page === TRUE)
-					{
-						$link .= ' href="'.$CI->config->site_url($v).'" ';
-					}
-					else
-					{
-						$link .= ' href="'.$CI->config->slash_item('base_url').$v.'" ';
-					}
-				}
-				else
-				{
-					$link .= "$k=\"$v\" ";
-				}
-			}
-
-			$link .= "/>";
-		}
-		else
-		{
-			if ( strpos($href, '://') !== FALSE)
-			{
-				$link .= ' href="'.$href.'" ';
-			}
-			elseif ($index_page === TRUE)
-			{
-				$link .= ' href="'.$CI->config->site_url($href).'" ';
-			}
-			else
-			{
-				$link .= ' href="'.$CI->config->slash_item('base_url').$href.'" ';
-			}
-
-			$link .= 'rel="'.$rel.'" type="'.$type.'" ';
-
-			if ($media	!= '')
-			{
-				$link .= 'media="'.$media.'" ';
-			}
-
-			if ($title	!= '')
-			{
-				$link .= 'title="'.$title.'" ';
-			}
-
-			$link .= '/>';
-		}
-
-
-		return $link;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Generates meta tags from an array of key/values
- *
- * @access	public
- * @param	array
- * @return	string
- */
-if ( ! function_exists('meta'))
-{
-	function meta($name = '', $content = '', $type = 'name', $newline = "\n")
-	{
-		// Since we allow the data to be passes as a string, a simple array
-		// or a multidimensional one, we need to do a little prepping.
-		if ( ! is_array($name))
-		{
-			$name = array(array('name' => $name, 'content' => $content, 'type' => $type, 'newline' => $newline));
-		}
-		else
-		{
-			// Turn single array into multidimensional
-			if (isset($name['name']))
-			{
-				$name = array($name);
-			}
-		}
-
-		$str = '';
-		foreach ($name as $meta)
-		{
-			$type 		= ( ! isset($meta['type']) OR $meta['type'] == 'name') ? 'name' : 'http-equiv';
-			$name 		= ( ! isset($meta['name'])) 	? '' 	: $meta['name'];
-			$content	= ( ! isset($meta['content']))	? '' 	: $meta['content'];
-			$newline	= ( ! isset($meta['newline']))	? "\n"	: $meta['newline'];
-
-			$str .= '<meta '.$type.'="'.$name.'" content="'.$content.'" />'.$newline;
-		}
-
-		return $str;
-	}
-}
-
-// ------------------------------------------------------------------------
-
-/**
- * Generates non-breaking space entities based on number supplied
- *
- * @access	public
- * @param	integer
- * @return	string
- */
-if ( ! function_exists('nbs'))
-{
-	function nbs($num = 1)
-	{
-		return str_repeat("&nbsp;", $num);
-	}
-}
-
-
-/* End of file html_helper.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 HTML Helpers

+ *

+ * @package		CodeIgniter

+ * @subpackage	Helpers

+ * @category	Helpers

+ * @author		ExpressionEngine Dev Team

+ * @link		http://codeigniter.com/user_guide/helpers/html_helper.html

+ */

+

+// ------------------------------------------------------------------------

+

+/**

+ * Heading

+ *

+ * Generates an HTML heading tag.  First param is the data.

+ * Second param is the size of the heading tag.

+ *

+ * @access	public

+ * @param	string

+ * @param	integer

+ * @return	string

+ */

+if ( ! function_exists('heading'))

+{

+	function heading($data = '', $h = '1')

+	{

+		return "<h".$h.">".$data."</h".$h.">";

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Unordered List

+ *

+ * Generates an HTML unordered list from an single or multi-dimensional array.

+ *

+ * @access	public

+ * @param	array

+ * @param	mixed

+ * @return	string

+ */

+if ( ! function_exists('ul'))

+{

+	function ul($list, $attributes = '')

+	{

+		return _list('ul', $list, $attributes);

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Ordered List

+ *

+ * Generates an HTML ordered list from an single or multi-dimensional array.

+ *

+ * @access	public

+ * @param	array

+ * @param	mixed

+ * @return	string

+ */

+if ( ! function_exists('ol'))

+{

+	function ol($list, $attributes = '')

+	{

+		return _list('ol', $list, $attributes);

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Generates the list

+ *

+ * Generates an HTML ordered list from an single or multi-dimensional array.

+ *

+ * @access	private

+ * @param	string

+ * @param	mixed

+ * @param	mixed

+ * @param	intiger

+ * @return	string

+ */

+if ( ! function_exists('_list'))

+{

+	function _list($type = 'ul', $list, $attributes = '', $depth = 0)

+	{

+		// If an array wasn't submitted there's nothing to do...

+		if ( ! is_array($list))

+		{

+			return $list;

+		}

+

+		// Set the indentation based on the depth

+		$out = str_repeat(" ", $depth);

+

+		// Were any attributes submitted?  If so generate a string

+		if (is_array($attributes))

+		{

+			$atts = '';

+			foreach ($attributes as $key => $val)

+			{

+				$atts .= ' ' . $key . '="' . $val . '"';

+			}

+			$attributes = $atts;

+		}

+

+		// Write the opening list tag

+		$out .= "<".$type.$attributes.">\n";

+

+		// Cycle through the list elements.  If an array is

+		// encountered we will recursively call _list()

+

+		static $_last_list_item = '';

+		foreach ($list as $key => $val)

+		{

+			$_last_list_item = $key;

+

+			$out .= str_repeat(" ", $depth + 2);

+			$out .= "<li>";

+

+			if ( ! is_array($val))

+			{

+				$out .= $val;

+			}

+			else

+			{

+				$out .= $_last_list_item."\n";

+				$out .= _list($type, $val, '', $depth + 4);

+				$out .= str_repeat(" ", $depth + 2);

+			}

+

+			$out .= "</li>\n";

+		}

+

+		// Set the indentation for the closing tag

+		$out .= str_repeat(" ", $depth);

+

+		// Write the closing list tag

+		$out .= "</".$type.">\n";

+

+		return $out;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Generates HTML BR tags based on number supplied

+ *

+ * @access	public

+ * @param	integer

+ * @return	string

+ */

+if ( ! function_exists('br'))

+{

+	function br($num = 1)

+	{

+		return str_repeat("<br />", $num);

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Image

+ *

+ * Generates an <img /> element

+ *

+ * @access	public

+ * @param	mixed

+ * @return	string

+ */

+if ( ! function_exists('img'))

+{

+	function img($src = '', $index_page = FALSE)

+	{

+		if ( ! is_array($src) )

+		{

+			$src = array('src' => $src);

+		}

+

+		$img = '<img';

+

+		foreach ($src as $k=>$v)

+		{

+

+			if ($k == 'src' AND strpos($v, '://') === FALSE)

+			{

+				$CI =& get_instance();

+

+				if ($index_page === TRUE)

+				{

+					$img .= ' src="'.$CI->config->site_url($v).'" ';

+				}

+				else

+				{

+					$img .= ' src="'.$CI->config->slash_item('base_url').$v.'" ';

+				}

+			}

+			else

+			{

+				$img .= " $k=\"$v\" ";

+			}

+		}

+

+		$img .= '/>';

+

+		return $img;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Doctype

+ *

+ * Generates a page document type declaration

+ *

+ * Valid options are xhtml-11, xhtml-strict, xhtml-trans, xhtml-frame,

+ * html4-strict, html4-trans, and html4-frame.  Values are saved in the

+ * doctypes config file.

+ *

+ * @access	public

+ * @param	string	type	The doctype to be generated

+ * @return	string

+ */

+if ( ! function_exists('doctype'))

+{

+	function doctype($type = 'xhtml-strict')

+	{

+		global $_doctypes;

+

+		if ( ! is_array($_doctypes))

+		{

+			if ( ! require_once(APPPATH.'config/doctypes.php'))

+			{

+				return FALSE;

+			}

+		}

+

+		if (isset($_doctypes[$type]))

+		{

+			return $_doctypes[$type];

+		}

+		else

+		{

+			return FALSE;

+		}

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Link

+ *

+ * Generates link to a CSS file

+ *

+ * @access	public

+ * @param	mixed	stylesheet hrefs or an array

+ * @param	string	rel

+ * @param	string	type

+ * @param	string	title

+ * @param	string	media

+ * @param	boolean	should index_page be added to the css path

+ * @return	string

+ */

+if ( ! function_exists('link_tag'))

+{

+	function link_tag($href = '', $rel = 'stylesheet', $type = 'text/css', $title = '', $media = '', $index_page = FALSE)

+	{

+		$CI =& get_instance();

+

+		$link = '<link ';

+

+		if (is_array($href))

+		{

+			foreach ($href as $k=>$v)

+			{

+				if ($k == 'href' AND strpos($v, '://') === FALSE)

+				{

+					if ($index_page === TRUE)

+					{

+						$link .= ' href="'.$CI->config->site_url($v).'" ';

+					}

+					else

+					{

+						$link .= ' href="'.$CI->config->slash_item('base_url').$v.'" ';

+					}

+				}

+				else

+				{

+					$link .= "$k=\"$v\" ";

+				}

+			}

+

+			$link .= "/>";

+		}

+		else

+		{

+			if ( strpos($href, '://') !== FALSE)

+			{

+				$link .= ' href="'.$href.'" ';

+			}

+			elseif ($index_page === TRUE)

+			{

+				$link .= ' href="'.$CI->config->site_url($href).'" ';

+			}

+			else

+			{

+				$link .= ' href="'.$CI->config->slash_item('base_url').$href.'" ';

+			}

+

+			$link .= 'rel="'.$rel.'" type="'.$type.'" ';

+

+			if ($media	!= '')

+			{

+				$link .= 'media="'.$media.'" ';

+			}

+

+			if ($title	!= '')

+			{

+				$link .= 'title="'.$title.'" ';

+			}

+

+			$link .= '/>';

+		}

+

+

+		return $link;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Generates meta tags from an array of key/values

+ *

+ * @access	public

+ * @param	array

+ * @return	string

+ */

+if ( ! function_exists('meta'))

+{

+	function meta($name = '', $content = '', $type = 'name', $newline = "\n")

+	{

+		// Since we allow the data to be passes as a string, a simple array

+		// or a multidimensional one, we need to do a little prepping.

+		if ( ! is_array($name))

+		{

+			$name = array(array('name' => $name, 'content' => $content, 'type' => $type, 'newline' => $newline));

+		}

+		else

+		{

+			// Turn single array into multidimensional

+			if (isset($name['name']))

+			{

+				$name = array($name);

+			}

+		}

+

+		$str = '';

+		foreach ($name as $meta)

+		{

+			$type 		= ( ! isset($meta['type']) OR $meta['type'] == 'name') ? 'name' : 'http-equiv';

+			$name 		= ( ! isset($meta['name'])) 	? '' 	: $meta['name'];

+			$content	= ( ! isset($meta['content']))	? '' 	: $meta['content'];

+			$newline	= ( ! isset($meta['newline']))	? "\n"	: $meta['newline'];

+

+			$str .= '<meta '.$type.'="'.$name.'" content="'.$content.'" />'.$newline;

+		}

+

+		return $str;

+	}

+}

+

+// ------------------------------------------------------------------------

+

+/**

+ * Generates non-breaking space entities based on number supplied

+ *

+ * @access	public

+ * @param	integer

+ * @return	string

+ */

+if ( ! function_exists('nbs'))

+{

+	function nbs($num = 1)

+	{

+		return str_repeat("&nbsp;", $num);

+	}

+}

+

+

+/* End of file html_helper.php */

 /* Location: ./system/helpers/html_helper.php */
\ No newline at end of file
diff --git a/system/helpers/language_helper.php b/system/helpers/language_helper.php
index 2091fd4..d90fe31 100644
--- a/system/helpers/language_helper.php
+++ b/system/helpers/language_helper.php
@@ -1,58 +1,58 @@
-<?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 Language Helpers
- *
- * @package		CodeIgniter
- * @subpackage	Helpers
- * @category	Helpers
- * @author		ExpressionEngine Dev Team
- * @link		http://codeigniter.com/user_guide/helpers/language_helper.html
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Lang
- *
- * Fetches a language variable and optionally outputs a form label
- *
- * @access	public
- * @param	string	the language line
- * @param	string	the id of the form element
- * @return	string
- */	
-if ( ! function_exists('lang'))
-{
-	function lang($line, $id = '')
-	{
-		$CI =& get_instance();
-		$line = $CI->lang->line($line);
-
-		if ($id != '')
-		{
-			$line = '<label for="'.$id.'">'.$line."</label>";
-		}
-
-		return $line;
-	}
-}
-
-// ------------------------------------------------------------------------
-/* End of file language_helper.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 Language Helpers

+ *

+ * @package		CodeIgniter

+ * @subpackage	Helpers

+ * @category	Helpers

+ * @author		ExpressionEngine Dev Team

+ * @link		http://codeigniter.com/user_guide/helpers/language_helper.html

+ */

+

+// ------------------------------------------------------------------------

+

+/**

+ * Lang

+ *

+ * Fetches a language variable and optionally outputs a form label

+ *

+ * @access	public

+ * @param	string	the language line

+ * @param	string	the id of the form element

+ * @return	string

+ */	

+if ( ! function_exists('lang'))

+{

+	function lang($line, $id = '')

+	{

+		$CI =& get_instance();

+		$line = $CI->lang->line($line);

+

+		if ($id != '')

+		{

+			$line = '<label for="'.$id.'">'.$line."</label>";

+		}

+

+		return $line;

+	}

+}

+

+// ------------------------------------------------------------------------

+/* End of file language_helper.php */

 /* Location: ./system/helpers/language_helper.php */
\ No newline at end of file
diff --git a/system/language/english/profiler_lang.php b/system/language/english/profiler_lang.php
index 7c40e3f..4db5511 100644
--- a/system/language/english/profiler_lang.php
+++ b/system/language/english/profiler_lang.php
@@ -1,19 +1,19 @@
-<?php
-
-$lang['profiler_database']		  = 'DATABASE';
-$lang['profiler_controller_info'] = 'CLASS/METHOD';
-$lang['profiler_benchmarks']	= 'BENCHMARKS';
-$lang['profiler_queries']		= 'QUERIES';
-$lang['profiler_get_data']		= 'GET DATA';
-$lang['profiler_post_data']		= 'POST DATA';
-$lang['profiler_uri_string']	= 'URI STRING';
-$lang['profiler_memory_usage']	= 'MEMORY USAGE';
-$lang['profiler_no_db']			= 'Database driver is not currently loaded';
-$lang['profiler_no_queries']	= 'No queries were run';
-$lang['profiler_no_post']		= 'No POST data exists';
-$lang['profiler_no_get']		= 'No GET data exists';
-$lang['profiler_no_uri']		= 'No URI data exists';
-$lang['profiler_no_memory']		= 'Memory Usage Unavailable';
-
-/* End of file profiler_lang.php */
+<?php

+

+$lang['profiler_database']		  = 'DATABASE';

+$lang['profiler_controller_info'] = 'CLASS/METHOD';

+$lang['profiler_benchmarks']	= 'BENCHMARKS';

+$lang['profiler_queries']		= 'QUERIES';

+$lang['profiler_get_data']		= 'GET DATA';

+$lang['profiler_post_data']		= 'POST DATA';

+$lang['profiler_uri_string']	= 'URI STRING';

+$lang['profiler_memory_usage']	= 'MEMORY USAGE';

+$lang['profiler_no_db']			= 'Database driver is not currently loaded';

+$lang['profiler_no_queries']	= 'No queries were run';

+$lang['profiler_no_post']		= 'No POST data exists';

+$lang['profiler_no_get']		= 'No GET data exists';

+$lang['profiler_no_uri']		= 'No URI data exists';

+$lang['profiler_no_memory']		= 'Memory Usage Unavailable';

+

+/* End of file profiler_lang.php */

 /* Location: ./system/language/english/profiler_lang.php */
\ No newline at end of file
diff --git a/system/language/english/scaffolding_lang.php b/system/language/english/scaffolding_lang.php
index c4d54d5..7df2970 100644
--- a/system/language/english/scaffolding_lang.php
+++ b/system/language/english/scaffolding_lang.php
@@ -1,17 +1,17 @@
-<?php
-
-$lang['scaff_view_records']		= 'View Records';
-$lang['scaff_create_record']	= 'Create New Record';
-$lang['scaff_add']				= 'Add Data';
-$lang['scaff_view']				= 'View Data';
-$lang['scaff_edit']				= 'Edit';
-$lang['scaff_delete']			= 'Delete';
-$lang['scaff_view_all']			= 'View All';
-$lang['scaff_yes']				= 'Yes';
-$lang['scaff_no']				= 'No';
-$lang['scaff_no_data']			= 'No data exists for this table yet.';
-$lang['scaff_del_confirm']		= 'Are you sure you want to delete the following row:';
-
-
-/* End of file scaffolding_lang.php */
+<?php

+

+$lang['scaff_view_records']		= 'View Records';

+$lang['scaff_create_record']	= 'Create New Record';

+$lang['scaff_add']				= 'Add Data';

+$lang['scaff_view']				= 'View Data';

+$lang['scaff_edit']				= 'Edit';

+$lang['scaff_delete']			= 'Delete';

+$lang['scaff_view_all']			= 'View All';

+$lang['scaff_yes']				= 'Yes';

+$lang['scaff_no']				= 'No';

+$lang['scaff_no_data']			= 'No data exists for this table yet.';

+$lang['scaff_del_confirm']		= 'Are you sure you want to delete the following row:';

+

+

+/* End of file scaffolding_lang.php */

 /* Location: ./system/language/english/scaffolding_lang.php */
\ No newline at end of file
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index ac96882..e414d84 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -1,1955 +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	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 */
+<?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 ec84eb0..1a3ab18 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 46f3ac4..55019e4 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 16201ee..f260e76 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -1,1548 +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	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 */
+<?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/Input.php b/system/libraries/Input.php
index f26df75..fe76559 100644
--- a/system/libraries/Input.php
+++ b/system/libraries/Input.php
@@ -1,1059 +1,1059 @@
-<?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
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Input Class
- *
- * Pre-processes global input data for security
- *
- * @package		CodeIgniter
- * @subpackage	Libraries
- * @category	Input
- * @author		ExpressionEngine Dev Team
- * @link		http://codeigniter.com/user_guide/libraries/input.html
- */
-class CI_Input {
-	var $use_xss_clean		= FALSE;
-	var $xss_hash			= '';
-	var $ip_address			= FALSE;
-	var $user_agent			= FALSE;
-	var $allow_get_array	= FALSE;
-
-	/* never allowed, string replacement */
-	var $never_allowed_str = array(
-									'document.cookie'	=> '[removed]',
-									'document.write'	=> '[removed]',
-									'.parentNode'		=> '[removed]',
-									'.innerHTML'		=> '[removed]',
-									'window.location'	=> '[removed]',
-									'-moz-binding'		=> '[removed]',
-									'<!--'				=> '&lt;!--',
-									'-->'				=> '--&gt;',
-									'<![CDATA['			=> '&lt;![CDATA['
-									);
-	/* never allowed, regex replacement */
-	var $never_allowed_regex = array(
-										"javascript\s*:"	=> '[removed]',
-										"expression\s*\("	=> '[removed]', // CSS and IE
-										"Redirect\s+302"	=> '[removed]'
-									);
-
-	/**
-	* Constructor
-	*
-	* Sets whether to globally enable the XSS processing
-	* and whether to allow the $_GET array
-	*
-	* @access	public
-	*/
-	function CI_Input()
-	{
-		log_message('debug', "Input Class Initialized");
-
-		$CFG =& load_class('Config');
-		$this->use_xss_clean	= ($CFG->item('global_xss_filtering') === TRUE) ? TRUE : FALSE;
-		$this->allow_get_array	= ($CFG->item('enable_query_strings') === TRUE) ? TRUE : FALSE;
-		$this->_sanitize_globals();
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Sanitize Globals
-	*
-	* This function does the following:
-	*
-	* Unsets $_GET data (if query strings are not enabled)
-	*
-	* Unsets all globals if register_globals is enabled
-	*
-	* Standardizes newline characters to \n
-	*
-	* @access	private
-	* @return	void
-	*/
-	function _sanitize_globals()
-	{
-		// Would kind of be "wrong" to unset any of these GLOBALS
-		$protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
-							'system_folder', 'application_folder', 'BM', 'EXT', 'CFG', 'URI', 'RTR', 'OUT', 'IN');
-
-		// Unset globals for security. 
-		// This is effectively the same as register_globals = off
-		foreach (array($_GET, $_POST, $_COOKIE, $_SERVER, $_FILES, $_ENV, (isset($_SESSION) && is_array($_SESSION)) ? $_SESSION : array()) as $global)
-		{
-			if ( ! is_array($global))
-			{
-				if ( ! in_array($global, $protected))
-				{
-					unset($GLOBALS[$global]);
-				}
-			}
-			else
-			{
-				foreach ($global as $key => $val)
-				{
-					if ( ! in_array($key, $protected))
-					{
-						unset($GLOBALS[$key]);
-					}
-
-					if (is_array($val))
-					{
-						foreach($val as $k => $v)
-						{
-							if ( ! in_array($k, $protected))
-							{
-								unset($GLOBALS[$k]);
-							}
-						}
-					}
-				}
-			}
-		}
-
-		// Is $_GET data allowed? If not we'll set the $_GET to an empty array
-		if ($this->allow_get_array == FALSE)
-		{
-			$_GET = array();
-		}
-		else
-		{
-			$_GET = $this->_clean_input_data($_GET);
-		}
-
-		// Clean $_POST Data
-		$_POST = $this->_clean_input_data($_POST);
-
-		// Clean $_COOKIE Data
-		// Also get rid of specially treated cookies that might be set by a server
-		// or silly application, that are of no use to a CI application anyway
-		// but that when present will trip our 'Disallowed Key Characters' alarm
-		// http://www.ietf.org/rfc/rfc2109.txt
-		// note that the key names below are single quoted strings, and are not PHP variables
-		unset($_COOKIE['$Version']);
-		unset($_COOKIE['$Path']);
-		unset($_COOKIE['$Domain']);
-		$_COOKIE = $this->_clean_input_data($_COOKIE);
-
-		log_message('debug', "Global POST and COOKIE data sanitized");
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Clean Input Data
-	*
-	* This is a helper function. It escapes data and
-	* standardizes newline characters to \n
-	*
-	* @access	private
-	* @param	string
-	* @return	string
-	*/
-	function _clean_input_data($str)
-	{
-		if (is_array($str))
-		{
-			$new_array = array();
-			foreach ($str as $key => $val)
-			{
-				$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
-			}
-			return $new_array;
-		}
-
-		// We strip slashes if magic quotes is on to keep things consistent
-		if (get_magic_quotes_gpc())
-		{
-			$str = stripslashes($str);
-		}
-
-		// Should we filter the input data?
-		if ($this->use_xss_clean === TRUE)
-		{
-			$str = $this->xss_clean($str);
-		}
-
-		// Standardize newlines
-		if (strpos($str, "\r") !== FALSE)
-		{
-			$str = str_replace(array("\r\n", "\r"), "\n", $str);
-		}
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Clean Keys
-	*
-	* This is a helper function. To prevent malicious users
-	* from trying to exploit keys we make sure that keys are
-	* only named with alpha-numeric text and a few other items.
-	*
-	* @access	private
-	* @param	string
-	* @return	string
-	*/
-	function _clean_input_keys($str)
-	{
-		if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))
-		{
-			exit('Disallowed Key Characters.');
-		}
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch from array
-	*
-	* This is a helper function to retrieve values from global arrays
-	*
-	* @access	private
-	* @param	array
-	* @param	string
-	* @param	bool
-	* @return	string
-	*/
-	function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE)
-	{
-		if ( ! isset($array[$index]))
-		{
-			return FALSE;
-		}
-
-		if ($xss_clean === TRUE)
-		{
-			return $this->xss_clean($array[$index]);
-		}
-
-		return $array[$index];
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch an item from the GET array
-	*
-	* @access	public
-	* @param	string
-	* @param	bool
-	* @return	string
-	*/
-	function get($index = '', $xss_clean = FALSE)
-	{
-		return $this->_fetch_from_array($_GET, $index, $xss_clean);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch an item from the POST array
-	*
-	* @access	public
-	* @param	string
-	* @param	bool
-	* @return	string
-	*/
-	function post($index = '', $xss_clean = FALSE)
-	{
-		return $this->_fetch_from_array($_POST, $index, $xss_clean);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch an item from either the GET array or the POST
-	*
-	* @access	public
-	* @param	string	The index key
-	* @param	bool	XSS cleaning
-	* @return	string
-	*/
-	function get_post($index = '', $xss_clean = FALSE)
-	{
-		if ( ! isset($_POST[$index]) )
-		{
-			return $this->get($index, $xss_clean);
-		}
-		else
-		{
-			return $this->post($index, $xss_clean);
-		}
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch an item from the COOKIE array
-	*
-	* @access	public
-	* @param	string
-	* @param	bool
-	* @return	string
-	*/
-	function cookie($index = '', $xss_clean = FALSE)
-	{
-		return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch an item from the SERVER array
-	*
-	* @access	public
-	* @param	string
-	* @param	bool
-	* @return	string
-	*/
-	function server($index = '', $xss_clean = FALSE)
-	{
-		return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Fetch the IP Address
-	*
-	* @access	public
-	* @return	string
-	*/
-	function ip_address()
-	{
-		if ($this->ip_address !== FALSE)
-		{
-			return $this->ip_address;
-		}
-
-		if ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))
-		{
-			$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
-		}
-		elseif ($this->server('REMOTE_ADDR'))
-		{
-			$this->ip_address = $_SERVER['REMOTE_ADDR'];
-		}
-		elseif ($this->server('HTTP_CLIENT_IP'))
-		{
-			$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
-		}
-		elseif ($this->server('HTTP_X_FORWARDED_FOR'))
-		{
-			$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
-		}
-
-		if ($this->ip_address === FALSE)
-		{
-			$this->ip_address = '0.0.0.0';
-			return $this->ip_address;
-		}
-
-		if (strstr($this->ip_address, ','))
-		{
-			$x = explode(',', $this->ip_address);
-			$this->ip_address = end($x);
-		}
-
-		if ( ! $this->valid_ip($this->ip_address))
-		{
-			$this->ip_address = '0.0.0.0';
-		}
-
-		return $this->ip_address;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Validate IP Address
-	*
-	* Updated version suggested by Geert De Deckere
-	* 
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function valid_ip($ip)
-	{
-		$ip_segments = explode('.', $ip);
-
-		// Always 4 segments needed
-		if (count($ip_segments) != 4)
-		{
-			return FALSE;
-		}
-		// IP can not start with 0
-		if ($ip_segments[0][0] == '0')
-		{
-			return FALSE;
-		}
-		// Check each segment
-		foreach ($ip_segments as $segment)
-		{
-			// IP segments must be digits and can not be 
-			// longer than 3 digits or greater then 255
-			if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3)
-			{
-				return FALSE;
-			}
-		}
-
-		return TRUE;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* User Agent
-	*
-	* @access	public
-	* @return	string
-	*/
-	function user_agent()
-	{
-		if ($this->user_agent !== FALSE)
-		{
-			return $this->user_agent;
-		}
-
-		$this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];
-
-		return $this->user_agent;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Filename Security
-	*
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function filename_security($str)
-	{
-		$bad = array(
-						"../",
-						"./",
-						"<!--",
-						"-->",
-						"<",
-						">",
-						"'",
-						'"',
-						'&',
-						'$',
-						'#',
-						'{',
-						'}',
-						'[',
-						']',
-						'=',
-						';',
-						'?',
-						"%20",
-						"%22",
-						"%3c",		// <
-						"%253c", 	// <
-						"%3e", 		// >
-						"%0e", 		// >
-						"%28", 		// (  
-						"%29", 		// ) 
-						"%2528", 	// (
-						"%26", 		// &
-						"%24", 		// $
-						"%3f", 		// ?
-						"%3b", 		// ;
-						"%3d"		// =
-					);
-
-		return stripslashes(str_replace($bad, '', $str));
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* XSS Clean
-	*
-	* Sanitizes data so that Cross Site Scripting Hacks can be
-	* prevented.  This function does a fair amount of work but
-	* it is extremely thorough, designed to prevent even the
-	* most obscure XSS attempts.  Nothing is ever 100% foolproof,
-	* of course, but I haven't been able to get anything passed
-	* the filter.
-	*
-	* Note: This function should only be used to deal with data
-	* upon submission.  It's not something that should
-	* be used for general runtime processing.
-	*
-	* This function was based in part on some code and ideas I
-	* got from Bitflux: http://blog.bitflux.ch/wiki/XSS_Prevention
-	*
-	* To help develop this script I used this great list of
-	* vulnerabilities along with a few other hacks I've
-	* harvested from examining vulnerabilities in other programs:
-	* http://ha.ckers.org/xss.html
-	*
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function xss_clean($str, $is_image = FALSE)
-	{
-		/*
-		* Is the string an array?
-		*
-		*/
-		if (is_array($str))
-		{
-			while (list($key) = each($str))
-			{
-				$str[$key] = $this->xss_clean($str[$key]);
-			}
-
-			return $str;
-		}
-
-		/*
-		* Remove Invisible Characters
-		*/
-		$str = $this->_remove_invisible_characters($str);
-
-		/*
-		* Protect GET variables in URLs
-		*/
-
-		// 901119URL5918AMP18930PROTECT8198
-
-		$str = preg_replace('|\&([a-z\_0-9]+)\=([a-z\_0-9]+)|i', $this->xss_hash()."\\1=\\2", $str);
-
-		/*
-		* Validate standard character entities
-		*
-		* Add a semicolon if missing.  We do this to enable
-		* the conversion of entities to ASCII later.
-		*
-		*/
-		$str = preg_replace('#(&\#?[0-9a-z]{2,})[\x00-\x20]*;?#i', "\\1;", $str);
-
-		/*
-		* Validate UTF16 two byte encoding (x00) 
-		*
-		* Just as above, adds a semicolon if missing.
-		*
-		*/
-		$str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$str);
-
-		/*
-		* Un-Protect GET variables in URLs
-		*/
-		$str = str_replace($this->xss_hash(), '&', $str);
-
-		/*
-		* URL Decode
-		*
-		* Just in case stuff like this is submitted:
-		*
-		* <a href="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">Google</a>
-		*
-		* Note: Use rawurldecode() so it does not remove plus signs
-		*
-		*/
-		$str = rawurldecode($str);
-
-		/*
-		* Convert character entities to ASCII 
-		*
-		* This permits our tests below to work reliably.
-		* We only convert entities that are within tags since
-		* these are the ones that will pose security problems.
-		*
-		*/
-
-		$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
-
-		$str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_html_entity_decode_callback'), $str);
-
-		/*
-		* Remove Invisible Characters Again!
-		*/
-		$str = $this->_remove_invisible_characters($str);
-
-		/*
-		* Convert all tabs to spaces
-		*
-		* This prevents strings like this: ja	vascript
-		* NOTE: we deal with spaces between characters later.
-		* NOTE: preg_replace was found to be amazingly slow here on large blocks of data,
-		* so we use str_replace.
-		*
-		*/
-
- 		if (strpos($str, "\t") !== FALSE)
-		{
-			$str = str_replace("\t", ' ', $str);
-		}
-
-		/*
-		* Capture converted string for later comparison
-		*/
-		$converted_string = $str;
-
-		/*
-		* Not Allowed Under Any Conditions
-		*/
-
-		foreach ($this->never_allowed_str as $key => $val)
-		{
-			$str = str_replace($key, $val, $str);   
-		}
-
-		foreach ($this->never_allowed_regex as $key => $val)
-		{
-			$str = preg_replace("#".$key."#i", $val, $str);   
-		}
-
-		/*
-		* Makes PHP tags safe
-		*
-		*  Note: XML tags are inadvertently replaced too:
-		*
-		*	<?xml
-		*
-		* But it doesn't seem to pose a problem.
-		*
-		*/
-		if ($is_image === TRUE)
-		{
-			// Images have a tendency to have the PHP short opening and closing tags every so often
-			// so we skip those and only do the long opening tags.
-			$str = str_replace(array('<?php', '<?PHP'),  array('&lt;?php', '&lt;?PHP'), $str);
-		}
-		else
-		{
-			$str = str_replace(array('<?php', '<?PHP', '<?', '?'.'>'),  array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
-		}
-
-		/*
-		* Compact any exploded words
-		*
-		* This corrects words like:  j a v a s c r i p t
-		* These words are compacted back to their correct state.
-		*
-		*/
-		$words = array('javascript', 'expression', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window');
-		foreach ($words as $word)
-		{
-			$temp = '';
-
-			for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++)
-			{
-				$temp .= substr($word, $i, 1)."\s*";
-			}
-
-			// We only want to do this when it is followed by a non-word character
-			// That way valid stuff like "dealer to" does not become "dealerto"
-			$str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str);
-		}
-
-		/*
-		* Remove disallowed Javascript in links or img tags
-		* We used to do some version comparisons and use of stripos for PHP5, but it is dog slow compared
-		* to these simplified non-capturing preg_match(), especially if the pattern exists in the string
-		*/
-		do
-		{
-			$original = $str;
-
-			if (preg_match("/<a/i", $str))
-			{
-				$str = preg_replace_callback("#<a\s+([^>]*?)(>|$)#si", array($this, '_js_link_removal'), $str);
-			}
-
-			if (preg_match("/<img/i", $str))
-			{
-				$str = preg_replace_callback("#<img\s+([^>]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str);
-			}
-
-			if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str))
-			{
-				$str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str);
-			}
-		}
-		while($original != $str);
-
-		unset($original);
-
-		/*
-		* Remove JavaScript Event Handlers
-		*
-		* Note: This code is a little blunt.  It removes
-		* the event handler and anything up to the closing >,
-		* but it's unlikely to be a problem.
-		*
-		*/
-		$event_handlers = array('[^a-z_\-]on\w*','xmlns');
-
-		if ($is_image === TRUE)
-		{
-			/*
-			* Adobe Photoshop puts XML metadata into JFIF images, including namespacing, 
-			* so we have to allow this for images. -Paul
-			*/
-			unset($event_handlers[array_search('xmlns', $event_handlers)]);
-		}
-
-		$str = preg_replace("#<([^><]+?)(".implode('|', $event_handlers).")(\s*=\s*[^><]*)([><]*)#i", "<\\1\\4", $str);
-
-		/*
-		* Sanitize naughty HTML elements
-		*
-		* If a tag containing any of the words in the list
-		* below is found, the tag gets converted to entities.
-		*
-		* So this: <blink>
-		* Becomes: &lt;blink&gt;
-		*
-		*/
-		$naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss';
-		$str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
-
-		/*
-		* Sanitize naughty scripting elements
-		*
-		* Similar to above, only instead of looking for
-		* tags it looks for PHP and JavaScript commands
-		* that are disallowed.  Rather than removing the
-		* code, it simply converts the parenthesis to entities
-		* rendering the code un-executable.
-		*
-		* For example:	eval('some code')
-		* Becomes:		eval&#40;'some code'&#41;
-		*
-		*/
-		$str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2&#40;\\3&#41;", $str);
-
-		/*
-		* Final clean up
-		*
-		* This adds a bit of extra precaution in case
-		* something got through the above filters
-		*
-		*/
-		foreach ($this->never_allowed_str as $key => $val)
-		{
-			$str = str_replace($key, $val, $str);   
-		}
-
-		foreach ($this->never_allowed_regex as $key => $val)
-		{
-			$str = preg_replace("#".$key."#i", $val, $str);
-		}
-
-		/*
-		*  Images are Handled in a Special Way
-		*  - Essentially, we want to know that after all of the character conversion is done whether
-		*  any unwanted, likely XSS, code was found.  If not, we return TRUE, as the image is clean.
-		*  However, if the string post-conversion does not matched the string post-removal of XSS,
-		*  then it fails, as there was unwanted XSS code found and removed/changed during processing.
-		*/
-
-		if ($is_image === TRUE)
-		{
-			if ($str == $converted_string)
-			{
-				return TRUE;
-			}
-			else
-			{
-				return FALSE;
-			}
-		}
-
-		log_message('debug', "XSS Filtering completed");
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Random Hash for protecting URLs
-	*
-	* @access	public
-	* @return	string
-	*/
-	function xss_hash()
-	{
-		if ($this->xss_hash == '')
-		{
-			if (phpversion() >= 4.2)
-				mt_srand();
-			else
-				mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);
-
-			$this->xss_hash = md5(time() + mt_rand(0, 1999999999));
-		}
-
-		return $this->xss_hash;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Remove Invisible Characters
-	*
-	* This prevents sandwiching null characters
-	* between ascii characters, like Java\0script.
-	*
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function _remove_invisible_characters($str)
-	{
-		static $non_displayables;
-
-		if ( ! isset($non_displayables))
-		{
-			// every control character except newline (dec 10), carriage return (dec 13), and horizontal tab (dec 09),
-			$non_displayables = array(
-										'/%0[0-8bcef]/',			// url encoded 00-08, 11, 12, 14, 15
-										'/%1[0-9a-f]/',				// url encoded 16-31
-										'/[\x00-\x08]/',			// 00-08
-										'/\x0b/', '/\x0c/',			// 11, 12
-										'/[\x0e-\x1f]/'				// 14-31
-									);
-		}
-
-		do
-		{
-			$cleaned = $str;
-			$str = preg_replace($non_displayables, '', $str);
-		}
-		while ($cleaned != $str);
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Compact Exploded Words
-	*
-	* Callback function for xss_clean() to remove whitespace from
-	* things like j a v a s c r i p t
-	*
-	* @access	public
-	* @param	type
-	* @return	type
-	*/
-	function _compact_exploded_words($matches)
-	{
-		return preg_replace('/\s+/s', '', $matches[1]).$matches[2];
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Sanitize Naughty HTML
-	*
-	* Callback function for xss_clean() to remove naughty HTML elements
-	*
-	* @access	private
-	* @param	array
-	* @return	string
-	*/
-	function _sanitize_naughty_html($matches)
-	{
-		// encode opening brace
-		$str = '&lt;'.$matches[1].$matches[2].$matches[3];
-
-		// encode captured opening or closing brace to prevent recursive vectors
-		$str .= str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* JS Link Removal
-	*
-	* Callback function for xss_clean() to sanitize links
-	* This limits the PCRE backtracks, making it more performance friendly
-	* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
-	* PHP 5.2+ on link-heavy strings
-	*
-	* @access	private
-	* @param	array
-	* @return	string
-	*/
-	function _js_link_removal($match)
-	{
-		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
-		return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
-	}
-
-	/**
-	* JS Image Removal
-	*
-	* Callback function for xss_clean() to sanitize image tags
-	* This limits the PCRE backtracks, making it more performance friendly
-	* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in
-	* PHP 5.2+ on image tag heavy strings
-	*
-	* @access	private
-	* @param	array
-	* @return	string
-	*/
-	function _js_img_removal($match)
-	{
-		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
-		return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Attribute Conversion
-	*
-	* Used as a callback for XSS Clean
-	*
-	* @access	public
-	* @param	array
-	* @return	string
-	*/
-	function _convert_attribute($match)
-	{
-		return str_replace(array('>', '<'), array('&gt;', '&lt;'), $match[0]);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* HTML Entity Decode Callback
-	*
-	* Used as a callback for XSS Clean
-	*
-	* @access	public
-	* @param	array
-	* @return	string
-	*/
-	function _html_entity_decode_callback($match)
-	{
-		$CFG =& load_class('Config');
-		$charset = $CFG->item('charset');
-
-		return $this->_html_entity_decode($match[0], strtoupper($charset));
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* HTML Entities Decode
-	*
-	* This function is a replacement for html_entity_decode()
-	*
-	* In some versions of PHP the native function does not work
-	* when UTF-8 is the specified character set, so this gives us
-	* a work-around.  More info here:
-	* http://bugs.php.net/bug.php?id=25670
-	*
-	* @access	private
-	* @param	string
-	* @param	string
-	* @return	string
-	*/
-	/* -------------------------------------------------
-	/*  Replacement for html_entity_decode()
-	/* -------------------------------------------------*/
-
-	/*
-	NOTE: html_entity_decode() has a bug in some PHP versions when UTF-8 is the
-	character set, and the PHP developers said they were not back porting the
-	fix to versions other than PHP 5.x.
-	*/
-	function _html_entity_decode($str, $charset='UTF-8')
-	{
-		if (stristr($str, '&') === FALSE) return $str;
-
-		// The reason we are not using html_entity_decode() by itself is because
-		// while it is not technically correct to leave out the semicolon
-		// at the end of an entity most browsers will still interpret the entity
-		// correctly.  html_entity_decode() does not convert entities without
-		// semicolons, so we are left with our own little solution here. Bummer.
-
-		if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR version_compare(phpversion(), '5.0.0', '>=')))
-		{
-			$str = html_entity_decode($str, ENT_COMPAT, $charset);
-			$str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);
-			return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);
-		}
-
-		// Numeric Entities
-		$str = preg_replace('~&#x(0*[0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str);
-		$str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str);
-
-		// Literal Entities - Slightly slow so we do another check
-		if (stristr($str, '&') === FALSE)
-		{
-			$str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES)));
-		}
-
-		return $str;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	* Filter Attributes
-	*
-	* Filters tag attributes for consistency and safety
-	*
-	* @access	public
-	* @param	string
-	* @return	string
-	*/
-	function _filter_attributes($str)
-	{
-		$out = '';
-
-		if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches))
-		{
-			foreach ($matches[0] as $match)
-			{
-				$out .= "{$match}";
-			}
-		}
-
-		return $out;
-	}
-
-	// --------------------------------------------------------------------
-
-}
-// END Input class
-
-/* End of file Input.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

+ */

+

+// ------------------------------------------------------------------------

+

+/**

+ * Input Class

+ *

+ * Pre-processes global input data for security

+ *

+ * @package		CodeIgniter

+ * @subpackage	Libraries

+ * @category	Input

+ * @author		ExpressionEngine Dev Team

+ * @link		http://codeigniter.com/user_guide/libraries/input.html

+ */

+class CI_Input {

+	var $use_xss_clean		= FALSE;

+	var $xss_hash			= '';

+	var $ip_address			= FALSE;

+	var $user_agent			= FALSE;

+	var $allow_get_array	= FALSE;

+

+	/* never allowed, string replacement */

+	var $never_allowed_str = array(

+									'document.cookie'	=> '[removed]',

+									'document.write'	=> '[removed]',

+									'.parentNode'		=> '[removed]',

+									'.innerHTML'		=> '[removed]',

+									'window.location'	=> '[removed]',

+									'-moz-binding'		=> '[removed]',

+									'<!--'				=> '&lt;!--',

+									'-->'				=> '--&gt;',

+									'<![CDATA['			=> '&lt;![CDATA['

+									);

+	/* never allowed, regex replacement */

+	var $never_allowed_regex = array(

+										"javascript\s*:"	=> '[removed]',

+										"expression\s*\("	=> '[removed]', // CSS and IE

+										"Redirect\s+302"	=> '[removed]'

+									);

+

+	/**

+	* Constructor

+	*

+	* Sets whether to globally enable the XSS processing

+	* and whether to allow the $_GET array

+	*

+	* @access	public

+	*/

+	function CI_Input()

+	{

+		log_message('debug', "Input Class Initialized");

+

+		$CFG =& load_class('Config');

+		$this->use_xss_clean	= ($CFG->item('global_xss_filtering') === TRUE) ? TRUE : FALSE;

+		$this->allow_get_array	= ($CFG->item('enable_query_strings') === TRUE) ? TRUE : FALSE;

+		$this->_sanitize_globals();

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Sanitize Globals

+	*

+	* This function does the following:

+	*

+	* Unsets $_GET data (if query strings are not enabled)

+	*

+	* Unsets all globals if register_globals is enabled

+	*

+	* Standardizes newline characters to \n

+	*

+	* @access	private

+	* @return	void

+	*/

+	function _sanitize_globals()

+	{

+		// Would kind of be "wrong" to unset any of these GLOBALS

+		$protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST', '_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',

+							'system_folder', 'application_folder', 'BM', 'EXT', 'CFG', 'URI', 'RTR', 'OUT', 'IN');

+

+		// Unset globals for security. 

+		// This is effectively the same as register_globals = off

+		foreach (array($_GET, $_POST, $_COOKIE, $_SERVER, $_FILES, $_ENV, (isset($_SESSION) && is_array($_SESSION)) ? $_SESSION : array()) as $global)

+		{

+			if ( ! is_array($global))

+			{

+				if ( ! in_array($global, $protected))

+				{

+					unset($GLOBALS[$global]);

+				}

+			}

+			else

+			{

+				foreach ($global as $key => $val)

+				{

+					if ( ! in_array($key, $protected))

+					{

+						unset($GLOBALS[$key]);

+					}

+

+					if (is_array($val))

+					{

+						foreach($val as $k => $v)

+						{

+							if ( ! in_array($k, $protected))

+							{

+								unset($GLOBALS[$k]);

+							}

+						}

+					}

+				}

+			}

+		}

+

+		// Is $_GET data allowed? If not we'll set the $_GET to an empty array

+		if ($this->allow_get_array == FALSE)

+		{

+			$_GET = array();

+		}

+		else

+		{

+			$_GET = $this->_clean_input_data($_GET);

+		}

+

+		// Clean $_POST Data

+		$_POST = $this->_clean_input_data($_POST);

+

+		// Clean $_COOKIE Data

+		// Also get rid of specially treated cookies that might be set by a server

+		// or silly application, that are of no use to a CI application anyway

+		// but that when present will trip our 'Disallowed Key Characters' alarm

+		// http://www.ietf.org/rfc/rfc2109.txt

+		// note that the key names below are single quoted strings, and are not PHP variables

+		unset($_COOKIE['$Version']);

+		unset($_COOKIE['$Path']);

+		unset($_COOKIE['$Domain']);

+		$_COOKIE = $this->_clean_input_data($_COOKIE);

+

+		log_message('debug', "Global POST and COOKIE data sanitized");

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Clean Input Data

+	*

+	* This is a helper function. It escapes data and

+	* standardizes newline characters to \n

+	*

+	* @access	private

+	* @param	string

+	* @return	string

+	*/

+	function _clean_input_data($str)

+	{

+		if (is_array($str))

+		{

+			$new_array = array();

+			foreach ($str as $key => $val)

+			{

+				$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);

+			}

+			return $new_array;

+		}

+

+		// We strip slashes if magic quotes is on to keep things consistent

+		if (get_magic_quotes_gpc())

+		{

+			$str = stripslashes($str);

+		}

+

+		// Should we filter the input data?

+		if ($this->use_xss_clean === TRUE)

+		{

+			$str = $this->xss_clean($str);

+		}

+

+		// Standardize newlines

+		if (strpos($str, "\r") !== FALSE)

+		{

+			$str = str_replace(array("\r\n", "\r"), "\n", $str);

+		}

+

+		return $str;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Clean Keys

+	*

+	* This is a helper function. To prevent malicious users

+	* from trying to exploit keys we make sure that keys are

+	* only named with alpha-numeric text and a few other items.

+	*

+	* @access	private

+	* @param	string

+	* @return	string

+	*/

+	function _clean_input_keys($str)

+	{

+		if ( ! preg_match("/^[a-z0-9:_\/-]+$/i", $str))

+		{

+			exit('Disallowed Key Characters.');

+		}

+

+		return $str;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch from array

+	*

+	* This is a helper function to retrieve values from global arrays

+	*

+	* @access	private

+	* @param	array

+	* @param	string

+	* @param	bool

+	* @return	string

+	*/

+	function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE)

+	{

+		if ( ! isset($array[$index]))

+		{

+			return FALSE;

+		}

+

+		if ($xss_clean === TRUE)

+		{

+			return $this->xss_clean($array[$index]);

+		}

+

+		return $array[$index];

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch an item from the GET array

+	*

+	* @access	public

+	* @param	string

+	* @param	bool

+	* @return	string

+	*/

+	function get($index = '', $xss_clean = FALSE)

+	{

+		return $this->_fetch_from_array($_GET, $index, $xss_clean);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch an item from the POST array

+	*

+	* @access	public

+	* @param	string

+	* @param	bool

+	* @return	string

+	*/

+	function post($index = '', $xss_clean = FALSE)

+	{

+		return $this->_fetch_from_array($_POST, $index, $xss_clean);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch an item from either the GET array or the POST

+	*

+	* @access	public

+	* @param	string	The index key

+	* @param	bool	XSS cleaning

+	* @return	string

+	*/

+	function get_post($index = '', $xss_clean = FALSE)

+	{

+		if ( ! isset($_POST[$index]) )

+		{

+			return $this->get($index, $xss_clean);

+		}

+		else

+		{

+			return $this->post($index, $xss_clean);

+		}

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch an item from the COOKIE array

+	*

+	* @access	public

+	* @param	string

+	* @param	bool

+	* @return	string

+	*/

+	function cookie($index = '', $xss_clean = FALSE)

+	{

+		return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch an item from the SERVER array

+	*

+	* @access	public

+	* @param	string

+	* @param	bool

+	* @return	string

+	*/

+	function server($index = '', $xss_clean = FALSE)

+	{

+		return $this->_fetch_from_array($_SERVER, $index, $xss_clean);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Fetch the IP Address

+	*

+	* @access	public

+	* @return	string

+	*/

+	function ip_address()

+	{

+		if ($this->ip_address !== FALSE)

+		{

+			return $this->ip_address;

+		}

+

+		if ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))

+		{

+			$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];

+		}

+		elseif ($this->server('REMOTE_ADDR'))

+		{

+			$this->ip_address = $_SERVER['REMOTE_ADDR'];

+		}

+		elseif ($this->server('HTTP_CLIENT_IP'))

+		{

+			$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];

+		}

+		elseif ($this->server('HTTP_X_FORWARDED_FOR'))

+		{

+			$this->ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];

+		}

+

+		if ($this->ip_address === FALSE)

+		{

+			$this->ip_address = '0.0.0.0';

+			return $this->ip_address;

+		}

+

+		if (strstr($this->ip_address, ','))

+		{

+			$x = explode(',', $this->ip_address);

+			$this->ip_address = end($x);

+		}

+

+		if ( ! $this->valid_ip($this->ip_address))

+		{

+			$this->ip_address = '0.0.0.0';

+		}

+

+		return $this->ip_address;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Validate IP Address

+	*

+	* Updated version suggested by Geert De Deckere

+	* 

+	* @access	public

+	* @param	string

+	* @return	string

+	*/

+	function valid_ip($ip)

+	{

+		$ip_segments = explode('.', $ip);

+

+		// Always 4 segments needed

+		if (count($ip_segments) != 4)

+		{

+			return FALSE;

+		}

+		// IP can not start with 0

+		if ($ip_segments[0][0] == '0')

+		{

+			return FALSE;

+		}

+		// Check each segment

+		foreach ($ip_segments as $segment)

+		{

+			// IP segments must be digits and can not be 

+			// longer than 3 digits or greater then 255

+			if ($segment == '' OR preg_match("/[^0-9]/", $segment) OR $segment > 255 OR strlen($segment) > 3)

+			{

+				return FALSE;

+			}

+		}

+

+		return TRUE;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* User Agent

+	*

+	* @access	public

+	* @return	string

+	*/

+	function user_agent()

+	{

+		if ($this->user_agent !== FALSE)

+		{

+			return $this->user_agent;

+		}

+

+		$this->user_agent = ( ! isset($_SERVER['HTTP_USER_AGENT'])) ? FALSE : $_SERVER['HTTP_USER_AGENT'];

+

+		return $this->user_agent;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Filename Security

+	*

+	* @access	public

+	* @param	string

+	* @return	string

+	*/

+	function filename_security($str)

+	{

+		$bad = array(

+						"../",

+						"./",

+						"<!--",

+						"-->",

+						"<",

+						">",

+						"'",

+						'"',

+						'&',

+						'$',

+						'#',

+						'{',

+						'}',

+						'[',

+						']',

+						'=',

+						';',

+						'?',

+						"%20",

+						"%22",

+						"%3c",		// <

+						"%253c", 	// <

+						"%3e", 		// >

+						"%0e", 		// >

+						"%28", 		// (  

+						"%29", 		// ) 

+						"%2528", 	// (

+						"%26", 		// &

+						"%24", 		// $

+						"%3f", 		// ?

+						"%3b", 		// ;

+						"%3d"		// =

+					);

+

+		return stripslashes(str_replace($bad, '', $str));

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* XSS Clean

+	*

+	* Sanitizes data so that Cross Site Scripting Hacks can be

+	* prevented.  This function does a fair amount of work but

+	* it is extremely thorough, designed to prevent even the

+	* most obscure XSS attempts.  Nothing is ever 100% foolproof,

+	* of course, but I haven't been able to get anything passed

+	* the filter.

+	*

+	* Note: This function should only be used to deal with data

+	* upon submission.  It's not something that should

+	* be used for general runtime processing.

+	*

+	* This function was based in part on some code and ideas I

+	* got from Bitflux: http://blog.bitflux.ch/wiki/XSS_Prevention

+	*

+	* To help develop this script I used this great list of

+	* vulnerabilities along with a few other hacks I've

+	* harvested from examining vulnerabilities in other programs:

+	* http://ha.ckers.org/xss.html

+	*

+	* @access	public

+	* @param	string

+	* @return	string

+	*/

+	function xss_clean($str, $is_image = FALSE)

+	{

+		/*

+		* Is the string an array?

+		*

+		*/

+		if (is_array($str))

+		{

+			while (list($key) = each($str))

+			{

+				$str[$key] = $this->xss_clean($str[$key]);

+			}

+

+			return $str;

+		}

+

+		/*

+		* Remove Invisible Characters

+		*/

+		$str = $this->_remove_invisible_characters($str);

+

+		/*

+		* Protect GET variables in URLs

+		*/

+

+		// 901119URL5918AMP18930PROTECT8198

+

+		$str = preg_replace('|\&([a-z\_0-9]+)\=([a-z\_0-9]+)|i', $this->xss_hash()."\\1=\\2", $str);

+

+		/*

+		* Validate standard character entities

+		*

+		* Add a semicolon if missing.  We do this to enable

+		* the conversion of entities to ASCII later.

+		*

+		*/

+		$str = preg_replace('#(&\#?[0-9a-z]{2,})[\x00-\x20]*;?#i', "\\1;", $str);

+

+		/*

+		* Validate UTF16 two byte encoding (x00) 

+		*

+		* Just as above, adds a semicolon if missing.

+		*

+		*/

+		$str = preg_replace('#(&\#x?)([0-9A-F]+);?#i',"\\1\\2;",$str);

+

+		/*

+		* Un-Protect GET variables in URLs

+		*/

+		$str = str_replace($this->xss_hash(), '&', $str);

+

+		/*

+		* URL Decode

+		*

+		* Just in case stuff like this is submitted:

+		*

+		* <a href="http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D">Google</a>

+		*

+		* Note: Use rawurldecode() so it does not remove plus signs

+		*

+		*/

+		$str = rawurldecode($str);

+

+		/*

+		* Convert character entities to ASCII 

+		*

+		* This permits our tests below to work reliably.

+		* We only convert entities that are within tags since

+		* these are the ones that will pose security problems.

+		*

+		*/

+

+		$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);

+

+		$str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_html_entity_decode_callback'), $str);

+

+		/*

+		* Remove Invisible Characters Again!

+		*/

+		$str = $this->_remove_invisible_characters($str);

+

+		/*

+		* Convert all tabs to spaces

+		*

+		* This prevents strings like this: ja	vascript

+		* NOTE: we deal with spaces between characters later.

+		* NOTE: preg_replace was found to be amazingly slow here on large blocks of data,

+		* so we use str_replace.

+		*

+		*/

+

+ 		if (strpos($str, "\t") !== FALSE)

+		{

+			$str = str_replace("\t", ' ', $str);

+		}

+

+		/*

+		* Capture converted string for later comparison

+		*/

+		$converted_string = $str;

+

+		/*

+		* Not Allowed Under Any Conditions

+		*/

+

+		foreach ($this->never_allowed_str as $key => $val)

+		{

+			$str = str_replace($key, $val, $str);   

+		}

+

+		foreach ($this->never_allowed_regex as $key => $val)

+		{

+			$str = preg_replace("#".$key."#i", $val, $str);   

+		}

+

+		/*

+		* Makes PHP tags safe

+		*

+		*  Note: XML tags are inadvertently replaced too:

+		*

+		*	<?xml

+		*

+		* But it doesn't seem to pose a problem.

+		*

+		*/

+		if ($is_image === TRUE)

+		{

+			// Images have a tendency to have the PHP short opening and closing tags every so often

+			// so we skip those and only do the long opening tags.

+			$str = str_replace(array('<?php', '<?PHP'),  array('&lt;?php', '&lt;?PHP'), $str);

+		}

+		else

+		{

+			$str = str_replace(array('<?php', '<?PHP', '<?', '?'.'>'),  array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);

+		}

+

+		/*

+		* Compact any exploded words

+		*

+		* This corrects words like:  j a v a s c r i p t

+		* These words are compacted back to their correct state.

+		*

+		*/

+		$words = array('javascript', 'expression', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window');

+		foreach ($words as $word)

+		{

+			$temp = '';

+

+			for ($i = 0, $wordlen = strlen($word); $i < $wordlen; $i++)

+			{

+				$temp .= substr($word, $i, 1)."\s*";

+			}

+

+			// We only want to do this when it is followed by a non-word character

+			// That way valid stuff like "dealer to" does not become "dealerto"

+			$str = preg_replace_callback('#('.substr($temp, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str);

+		}

+

+		/*

+		* Remove disallowed Javascript in links or img tags

+		* We used to do some version comparisons and use of stripos for PHP5, but it is dog slow compared

+		* to these simplified non-capturing preg_match(), especially if the pattern exists in the string

+		*/

+		do

+		{

+			$original = $str;

+

+			if (preg_match("/<a/i", $str))

+			{

+				$str = preg_replace_callback("#<a\s+([^>]*?)(>|$)#si", array($this, '_js_link_removal'), $str);

+			}

+

+			if (preg_match("/<img/i", $str))

+			{

+				$str = preg_replace_callback("#<img\s+([^>]*?)(\s?/?>|$)#si", array($this, '_js_img_removal'), $str);

+			}

+

+			if (preg_match("/script/i", $str) OR preg_match("/xss/i", $str))

+			{

+				$str = preg_replace("#<(/*)(script|xss)(.*?)\>#si", '[removed]', $str);

+			}

+		}

+		while($original != $str);

+

+		unset($original);

+

+		/*

+		* Remove JavaScript Event Handlers

+		*

+		* Note: This code is a little blunt.  It removes

+		* the event handler and anything up to the closing >,

+		* but it's unlikely to be a problem.

+		*

+		*/

+		$event_handlers = array('[^a-z_\-]on\w*','xmlns');

+

+		if ($is_image === TRUE)

+		{

+			/*

+			* Adobe Photoshop puts XML metadata into JFIF images, including namespacing, 

+			* so we have to allow this for images. -Paul

+			*/

+			unset($event_handlers[array_search('xmlns', $event_handlers)]);

+		}

+

+		$str = preg_replace("#<([^><]+?)(".implode('|', $event_handlers).")(\s*=\s*[^><]*)([><]*)#i", "<\\1\\4", $str);

+

+		/*

+		* Sanitize naughty HTML elements

+		*

+		* If a tag containing any of the words in the list

+		* below is found, the tag gets converted to entities.

+		*

+		* So this: <blink>

+		* Becomes: &lt;blink&gt;

+		*

+		*/

+		$naughty = 'alert|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|isindex|layer|link|meta|object|plaintext|style|script|textarea|title|video|xml|xss';

+		$str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);

+

+		/*

+		* Sanitize naughty scripting elements

+		*

+		* Similar to above, only instead of looking for

+		* tags it looks for PHP and JavaScript commands

+		* that are disallowed.  Rather than removing the

+		* code, it simply converts the parenthesis to entities

+		* rendering the code un-executable.

+		*

+		* For example:	eval('some code')

+		* Becomes:		eval&#40;'some code'&#41;

+		*

+		*/

+		$str = preg_replace('#(alert|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', "\\1\\2&#40;\\3&#41;", $str);

+

+		/*

+		* Final clean up

+		*

+		* This adds a bit of extra precaution in case

+		* something got through the above filters

+		*

+		*/

+		foreach ($this->never_allowed_str as $key => $val)

+		{

+			$str = str_replace($key, $val, $str);   

+		}

+

+		foreach ($this->never_allowed_regex as $key => $val)

+		{

+			$str = preg_replace("#".$key."#i", $val, $str);

+		}

+

+		/*

+		*  Images are Handled in a Special Way

+		*  - Essentially, we want to know that after all of the character conversion is done whether

+		*  any unwanted, likely XSS, code was found.  If not, we return TRUE, as the image is clean.

+		*  However, if the string post-conversion does not matched the string post-removal of XSS,

+		*  then it fails, as there was unwanted XSS code found and removed/changed during processing.

+		*/

+

+		if ($is_image === TRUE)

+		{

+			if ($str == $converted_string)

+			{

+				return TRUE;

+			}

+			else

+			{

+				return FALSE;

+			}

+		}

+

+		log_message('debug', "XSS Filtering completed");

+		return $str;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Random Hash for protecting URLs

+	*

+	* @access	public

+	* @return	string

+	*/

+	function xss_hash()

+	{

+		if ($this->xss_hash == '')

+		{

+			if (phpversion() >= 4.2)

+				mt_srand();

+			else

+				mt_srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff);

+

+			$this->xss_hash = md5(time() + mt_rand(0, 1999999999));

+		}

+

+		return $this->xss_hash;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Remove Invisible Characters

+	*

+	* This prevents sandwiching null characters

+	* between ascii characters, like Java\0script.

+	*

+	* @access	public

+	* @param	string

+	* @return	string

+	*/

+	function _remove_invisible_characters($str)

+	{

+		static $non_displayables;

+

+		if ( ! isset($non_displayables))

+		{

+			// every control character except newline (dec 10), carriage return (dec 13), and horizontal tab (dec 09),

+			$non_displayables = array(

+										'/%0[0-8bcef]/',			// url encoded 00-08, 11, 12, 14, 15

+										'/%1[0-9a-f]/',				// url encoded 16-31

+										'/[\x00-\x08]/',			// 00-08

+										'/\x0b/', '/\x0c/',			// 11, 12

+										'/[\x0e-\x1f]/'				// 14-31

+									);

+		}

+

+		do

+		{

+			$cleaned = $str;

+			$str = preg_replace($non_displayables, '', $str);

+		}

+		while ($cleaned != $str);

+

+		return $str;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Compact Exploded Words

+	*

+	* Callback function for xss_clean() to remove whitespace from

+	* things like j a v a s c r i p t

+	*

+	* @access	public

+	* @param	type

+	* @return	type

+	*/

+	function _compact_exploded_words($matches)

+	{

+		return preg_replace('/\s+/s', '', $matches[1]).$matches[2];

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Sanitize Naughty HTML

+	*

+	* Callback function for xss_clean() to remove naughty HTML elements

+	*

+	* @access	private

+	* @param	array

+	* @return	string

+	*/

+	function _sanitize_naughty_html($matches)

+	{

+		// encode opening brace

+		$str = '&lt;'.$matches[1].$matches[2].$matches[3];

+

+		// encode captured opening or closing brace to prevent recursive vectors

+		$str .= str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);

+

+		return $str;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* JS Link Removal

+	*

+	* Callback function for xss_clean() to sanitize links

+	* This limits the PCRE backtracks, making it more performance friendly

+	* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in

+	* PHP 5.2+ on link-heavy strings

+	*

+	* @access	private

+	* @param	array

+	* @return	string

+	*/

+	function _js_link_removal($match)

+	{

+		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));

+		return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);

+	}

+

+	/**

+	* JS Image Removal

+	*

+	* Callback function for xss_clean() to sanitize image tags

+	* This limits the PCRE backtracks, making it more performance friendly

+	* and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in

+	* PHP 5.2+ on image tag heavy strings

+	*

+	* @access	private

+	* @param	array

+	* @return	string

+	*/

+	function _js_img_removal($match)

+	{

+		$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));

+		return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Attribute Conversion

+	*

+	* Used as a callback for XSS Clean

+	*

+	* @access	public

+	* @param	array

+	* @return	string

+	*/

+	function _convert_attribute($match)

+	{

+		return str_replace(array('>', '<'), array('&gt;', '&lt;'), $match[0]);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* HTML Entity Decode Callback

+	*

+	* Used as a callback for XSS Clean

+	*

+	* @access	public

+	* @param	array

+	* @return	string

+	*/

+	function _html_entity_decode_callback($match)

+	{

+		$CFG =& load_class('Config');

+		$charset = $CFG->item('charset');

+

+		return $this->_html_entity_decode($match[0], strtoupper($charset));

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* HTML Entities Decode

+	*

+	* This function is a replacement for html_entity_decode()

+	*

+	* In some versions of PHP the native function does not work

+	* when UTF-8 is the specified character set, so this gives us

+	* a work-around.  More info here:

+	* http://bugs.php.net/bug.php?id=25670

+	*

+	* @access	private

+	* @param	string

+	* @param	string

+	* @return	string

+	*/

+	/* -------------------------------------------------

+	/*  Replacement for html_entity_decode()

+	/* -------------------------------------------------*/

+

+	/*

+	NOTE: html_entity_decode() has a bug in some PHP versions when UTF-8 is the

+	character set, and the PHP developers said they were not back porting the

+	fix to versions other than PHP 5.x.

+	*/

+	function _html_entity_decode($str, $charset='UTF-8')

+	{

+		if (stristr($str, '&') === FALSE) return $str;

+

+		// The reason we are not using html_entity_decode() by itself is because

+		// while it is not technically correct to leave out the semicolon

+		// at the end of an entity most browsers will still interpret the entity

+		// correctly.  html_entity_decode() does not convert entities without

+		// semicolons, so we are left with our own little solution here. Bummer.

+

+		if (function_exists('html_entity_decode') && (strtolower($charset) != 'utf-8' OR version_compare(phpversion(), '5.0.0', '>=')))

+		{

+			$str = html_entity_decode($str, ENT_COMPAT, $charset);

+			$str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str);

+			return preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str);

+		}

+

+		// Numeric Entities

+		$str = preg_replace('~&#x(0*[0-9a-f]{2,5});{0,1}~ei', 'chr(hexdec("\\1"))', $str);

+		$str = preg_replace('~&#([0-9]{2,4});{0,1}~e', 'chr(\\1)', $str);

+

+		// Literal Entities - Slightly slow so we do another check

+		if (stristr($str, '&') === FALSE)

+		{

+			$str = strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES)));

+		}

+

+		return $str;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	* Filter Attributes

+	*

+	* Filters tag attributes for consistency and safety

+	*

+	* @access	public

+	* @param	string

+	* @return	string

+	*/

+	function _filter_attributes($str)

+	{

+		$out = '';

+

+		if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches))

+		{

+			foreach ($matches[0] as $match)

+			{

+				$out .= "{$match}";

+			}

+		}

+

+		return $out;

+	}

+

+	// --------------------------------------------------------------------

+

+}

+// END Input class

+

+/* End of file Input.php */

 /* Location: ./system/libraries/Input.php */
\ No newline at end of file
diff --git a/system/libraries/Language.php b/system/libraries/Language.php
index 78f4143..bc237e7 100644
--- a/system/libraries/Language.php
+++ b/system/libraries/Language.php
@@ -1,123 +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	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 */
+<?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 660ce8f..25bf21f 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	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 */
+<?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/system/libraries/Typography.php b/system/libraries/Typography.php
index 6a0f2ec..3ff0d2f 100644
--- a/system/libraries/Typography.php
+++ b/system/libraries/Typography.php
@@ -1,386 +1,385 @@
-<?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
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * Typography Class
- *
- *
- * @access		private
- * @category	Helpers
- * @author		ExpressionEngine Dev Team
- * @link		http://codeigniter.com/user_guide/helpers/
- */
-class CI_Typography {
-
-	// Block level elements that should not be wrapped inside <p> tags
-	var $block_elements = 'address|blockquote|div|dl|fieldset|form|h\d|hr|noscript|object|ol|p|pre|script|table|ul';
-	
-	// Elements that should not have <p> and <br /> tags within them.
-	var $skip_elements	= 'p|pre|ol|ul|dl|object|table';
-	
-	// Tags we want the parser to completely ignore when splitting the string.
-	var $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var';
-
-	// whether or not to protect quotes within { curly braces }
-	var $protect_braced_quotes = FALSE;
-	
-	/**
-	 * Nothing to do here...
-	 *
-	 */
-	function CI_Typography()
-	{
-	}
-
-	/**
-	 * Auto Typography
-	 *
-	 * This function converts text, making it typographically correct:
-	 * 	- Converts double spaces into paragraphs.
-	 * 	- Converts single line breaks into <br /> tags
-	 * 	- Converts single and double quotes into correctly facing curly quote entities.
-	 * 	- Converts three dots into ellipsis.
-	 * 	- Converts double dashes into em-dashes.
-	 *  - Converts two spaces into entities
-	 *
-	 * @access	public
-	 * @param	string
-	 * @param	bool	whether to reduce more then two consecutive newlines to two
-	 * @return	string
-	 */
-	function auto_typography($str, $reduce_linebreaks = FALSE)
-	{
-		if ($str == '')
-		{
-			return '';
-		}
-
-		// Standardize Newlines to make matching easier
-		if (strpos($str, "\r") !== FALSE)
-		{
-			$str = str_replace(array("\r\n", "\r"), "\n", $str);			
-		}
-			
-		// Reduce line breaks.  If there are more than two consecutive linebreaks
-		// we'll compress them down to a maximum of two since there's no benefit to more.
-		if ($reduce_linebreaks === TRUE)
-		{
-			$str = preg_replace("/\n\n+/", "\n\n", $str);
-		} 
-
-		// Convert quotes within tags to temporary markers. We don't want quotes converted 
-		// within tags so we'll temporarily convert them to {@DQ} and {@SQ}
-		// and we don't want double dashes converted to emdash entities, so they are marked with {@DD}
-		// likewise double spaces are converted to {@NBS} to prevent entity conversion
-		if (preg_match_all("#\<.+?>#si", $str, $matches))
-		{
-			for ($i = 0, $total = count($matches[0]); $i < $total; $i++)
-			{
-				$str = str_replace($matches[0][$i],
-									str_replace(array("'",'"','--','  '), array('{@SQ}', '{@DQ}', '{@DD}', '{@NBS}'), $matches[0][$i]),
-									$str);
-			}
-		}
-		
-		if ($this->protect_braced_quotes === TRUE)
-		{
-			if (preg_match_all("#\{.+?}#si", $str, $matches))
-			{
-				for ($i = 0, $total = count($matches[0]); $i < $total; $i++)
-				{
-					$str = str_replace($matches[0][$i],
-										str_replace(array("'",'"'), array('{@SQ}', '{@DQ}'), $matches[0][$i]),
-										$str);
-				}
-			}			
-		}
-		
-		// Convert "ignore" tags to temporary marker.  The parser splits out the string at every tag 
-		// it encounters.  Certain inline tags, like image tags, links, span tags, etc. will be 
-		// adversely affected if they are split out so we'll convert the opening bracket < temporarily to: {@TAG}
-		$str = preg_replace("#<(/*)(".$this->inline_elements.")([ >])#i", "{@TAG}\\1\\2\\3", $str);
-
-		// Split the string at every tag.  This expression creates an array with this prototype:
-		// 
-		// 	[array]
-		// 	{
-		// 		[0] = <opening tag>
-		// 		[1] = Content...
-		// 		[2] = <closing tag>
-		// 		Etc...
-		// 	}	
-		$chunks = preg_split('/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
-		
-		// Build our finalized string.  We cycle through the array, skipping tags, and processing the contained text	
-		$str = '';
-		$process = TRUE;
-		$paragraph = FALSE;
-		foreach ($chunks as $chunk)
-		{
-			// Are we dealing with a tag? If so, we'll skip the processing for this cycle.
-			// Well also set the "process" flag which allows us to skip <pre> tags and a few other things.
-			if (preg_match("#<(/*)(".$this->block_elements.").*?\>#", $chunk, $match))
-			{
-				if (preg_match("#".$this->skip_elements."#", $match[2]))
-				{
-					$process =  ($match[1] == '/') ? TRUE : FALSE;
-				}
-				
-				$str .= $chunk;
-				continue;
-			}
-			elseif (preg_match('/<(\/?)([a-z]*).*?>/s', $chunk, $tagmatch))
-			{
-				if ($tagmatch[1] == '/' && $tagmatch[2] == $this->last_tag)
-				{
-					$process = FALSE;
-				}
-				else
-				{
-					$process = TRUE;
-					$this->last_tag = $tagmatch[2];					
-				}
-			}
-
-			if ($process == FALSE)
-			{
-				$str .= $chunk;
-				continue;
-			}
-			
-			//  Convert Newlines into <p> and <br /> tags
-			$str .= $this->format_characters($this->_format_newlines($chunk));			
-		}
-
-		// is the whole of the content inside a block level element?
-		if ( ! preg_match("/^<(?:".$this->block_elements.")/i", $str, $match))
-		{
-			$str = "<p>{$str}</p>";
-		}
-
-
-		// some special linebreak cleanup
-		$str = preg_replace_callback('#<(?!/|'.$this->block_elements.')([^>]*)><p>(.*?)</p><(\w*)#si', array($this, '_linebreak_cleanup'), $str);
-		
-		// and cleanup empty paragraph tags sitting between two closing tags
-		$str = preg_replace('#(</\w+>)<p>(\s*)</p>(</\w+>)#si', '$1$2$3', $str);
-		
-		// Final clean up
-		$table = array(
-		
-						// If the user submitted their own paragraph tags within the text
-						// we will retain them instead of using our tags.
-						'/(<p[^>*?]>)<p>/'	=> '$1', // <?php BBEdit syntax coloring bug fix
-						
-						// Reduce multiple instances of opening/closing paragraph tags to a single one
-						'#(</p>)+#'			=> '</p>',
-						'/(<p><p>)+/'		=> '<p>',
-						'/(<p>\W+<p>)+/'	=> '<p>',
-						
-						// Clean up stray paragraph tags that appear before block level elements
-						'#<p></p><('.$this->block_elements.')#'	=> '<$1',
-						
-						// Clean up open paragraph tags that appear before block level elements
-						'#<p>(\W)<('.$this->block_elements.')#'	=> '<p></p>$1<$2',
-
-						// Clean up stray non-breaking spaces preceeding block elements
-						'#[&nbsp; ]+<('.$this->block_elements.')#'	=> '  <$1',
-			
-						// Replace the temporary markers we added earlier
-						'/\{@TAG\}/'		=> '<',
-						'/\{@DQ\}/'			=> '"',
-						'/\{@SQ\}/'			=> "'",
-						'/\{@DD\}/'			=> '--',
-						'/\{@NBS\}/'		=> '  '
-
-						);
-
-		// Do we need to reduce empty lines?
-		if ($reduce_linebreaks === TRUE)
-		{
-			$table['#<p>\n*</p>#'] = '';
-		}
-		else
-		{
-			// If we have empty paragraph tags we add a non-breaking space
-			// otherwise most browsers won't treat them as true paragraphs
-			$table['#<p></p>#'] = '<p>&nbsp;</p>';
-		}
-	
-		return preg_replace(array_keys($table), $table, $str);
-
-	}
-	
-	// --------------------------------------------------------------------
-	
-	/**
-	 * Linebreak Cleanup
-	 *
-	 * Removes paragraph and line break tags inserted inbetween
-	 * inline content and a new opening block level element
-	 *
-	 * @access	private
-	 * @param	array
-	 * @return	string
-	 */
-	function _linebreak_cleanup($match)
-	{
-		if (in_array($match[3], explode('|', $this->block_elements)))
-		{
-			return "<{$match[1]}>".str_replace('<br />', '', $match[2])."<{$match[3]}";
-		}
-		else
-		{
-			return $match[0];
-		}
-	}
-
-	// --------------------------------------------------------------------
-	
-	/**
-	 * Format Characters
-	 *
-	 * This function mainly converts double and single quotes
-	 * to curly entities, but it also converts em-dashes,
-	 * double spaces, and ampersands
-	 *
-	 * @access	public
-	 * @param	string
-	 * @return	string
-	 */
-	function format_characters($str)
-	{
-		static $table;
-		
-		if ( ! isset($table))
-		{
-	        $table = array(					
-							// nested smart quotes, opening and closing
-							// note that rules for grammar (English) allow only for two levels deep
-							// and that single quotes are _supposed_ to always be on the outside
-							// but we'll accommodate both
-							'/(^|\W|\s)\'"/'				=> '$1&#8216;&#8220;',
-							'/\'"(\s|\W|$)/'				=> '&#8217;&#8221;$1',
-							'/(^|\W|\s)"\'/'				=> '$1&#8220;&#8216;',
-							'/"\'(\s|\W|$)/'				=> '&#8221;&#8217;$1',
-
-							// single quote smart quotes
-							'/\'(\s|\W|$)/'					=> '&#8217;$1',
-							'/(^|\W|\s)\'/'					=> '$1&#8216;',
-
-							// double quote smart quotes
-							'/"(\s|\W|$)/'					=> '&#8221;$1',
-							'/(^|\W|\s)"/'					=> '$1&#8220;',
-
-							// apostrophes
-							"/(\w)'(\w)/"       	    	=> '$1&#8217;$2',
-
-							// Em dash and ellipses dots
-							'/\s?\-\-\s?/'					=> '&#8212;',
-							'/(\w)\.{3}/'					=> '$1&#8230;',
-
-							// double space after sentences
-							'/(\W)  /'						=> '$1&nbsp; ',
-
-							// ampersands, if not a character entity
-							'/&(?!#?[a-zA-Z0-9]{2,};)/'		=> '&amp;'
-	        			);			
-		}	
-
-		return preg_replace(array_keys($table), $table, $str);
-	}
-	
-	// --------------------------------------------------------------------
-
-	/**
-	 * Format Newlines
-	 *
-	 * Converts newline characters into either <p> tags or <br />
-	 *
-	 * @access	public
-	 * @param	string
-	 * @return	string
-	 */	
-	function _format_newlines($str)
-	{
-		if ($str == '')
-		{
-			return $str;
-		}
-
-		if (strpos($str, "\n") === FALSE)
-		{
-			return $str;
-		}
-		
-		// Convert two consecutive newlines to paragraphs
-		$str = str_replace("\n\n", "</p>\n\n<p>", $str);
-		
-		// Convert single spaces to <br /> tags
-		$str = preg_replace("/([^\n])(\n)([^\n])/", "\\1<br />\\2\\3", $str);
-		
-		// Wrap the whole enchilada in enclosing paragraphs
-		if ($str != "\n")
-		{
-			$str =  '<p>'.$str.'</p>';
-		}
-
-		// Remove empty paragraphs if they are on the first line, as this
-		// is a potential unintended consequence of the previous code
-		$str = preg_replace("/<p><\/p>(.*)/", "\\1", $str, 1);
-		
-		return $str;
-	}
-	
-	// ------------------------------------------------------------------------
-	
-	/**
-	 * Convert newlines to HTML line breaks except within PRE tags
-	 *
-	 * @access	public
-	 * @param	string
-	 * @return	string
-	 */		
-	function nl2br_except_pre($str)
-	{
-		$ex = explode("pre>",$str);
-		$ct = count($ex);
-	
-		$newstr = "";
-		for ($i = 0; $i < $ct; $i++)
-		{
-			if (($i % 2) == 0)
-			{
-				$newstr .= nl2br($ex[$i]);
-			}
-			else
-			{
-				$newstr .= $ex[$i];
-			}
-		
-			if ($ct - 1 != $i)
-				$newstr .= "pre>";
-		}
-	
-		return $newstr;
-	}
-	
-}
-// END Typography Class
-
-/* End of file Typography.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

+ */

+

+// ------------------------------------------------------------------------

+

+/**

+ * Typography Class

+ *

+ *

+ * @access		private

+ * @category	Helpers

+ * @author		ExpressionEngine Dev Team

+ * @link		http://codeigniter.com/user_guide/helpers/

+ */

+class CI_Typography {

+

+	// Block level elements that should not be wrapped inside <p> tags

+	var $block_elements = 'address|blockquote|div|dl|fieldset|form|h\d|hr|noscript|object|ol|p|pre|script|table|ul';

+	

+	// Elements that should not have <p> and <br /> tags within them.

+	var $skip_elements	= 'p|pre|ol|ul|dl|object|table';

+	

+	// Tags we want the parser to completely ignore when splitting the string.

+	var $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var';

+

+	// whether or not to protect quotes within { curly braces }

+	var $protect_braced_quotes = FALSE;

+	

+	/**

+	 * Nothing to do here...

+	 *

+	 */

+	function CI_Typography()

+	{

+	}

+

+	/**

+	 * Auto Typography

+	 *

+	 * This function converts text, making it typographically correct:

+	 * 	- Converts double spaces into paragraphs.

+	 * 	- Converts single line breaks into <br /> tags

+	 * 	- Converts single and double quotes into correctly facing curly quote entities.

+	 * 	- Converts three dots into ellipsis.

+	 * 	- Converts double dashes into em-dashes.

+	 *  - Converts two spaces into entities

+	 *

+	 * @access	public

+	 * @param	string

+	 * @param	bool	whether to reduce more then two consecutive newlines to two

+	 * @return	string

+	 */

+	function auto_typography($str, $reduce_linebreaks = FALSE)

+	{

+		if ($str == '')

+		{

+			return '';

+		}

+

+		// Standardize Newlines to make matching easier

+		if (strpos($str, "\r") !== FALSE)

+		{

+			$str = str_replace(array("\r\n", "\r"), "\n", $str);			

+		}

+			

+		// Reduce line breaks.  If there are more than two consecutive linebreaks

+		// we'll compress them down to a maximum of two since there's no benefit to more.

+		if ($reduce_linebreaks === TRUE)

+		{

+			$str = preg_replace("/\n\n+/", "\n\n", $str);

+		} 

+

+		// Convert quotes within tags to temporary markers. We don't want quotes converted 

+		// within tags so we'll temporarily convert them to {@DQ} and {@SQ}

+		// and we don't want double dashes converted to emdash entities, so they are marked with {@DD}

+		// likewise double spaces are converted to {@NBS} to prevent entity conversion

+		if (preg_match_all("#\<.+?>#si", $str, $matches))

+		{

+			for ($i = 0, $total = count($matches[0]); $i < $total; $i++)

+			{

+				$str = str_replace($matches[0][$i],

+									str_replace(array("'",'"','--','  '), array('{@SQ}', '{@DQ}', '{@DD}', '{@NBS}'), $matches[0][$i]),

+									$str);

+			}

+		}

+		

+		if ($this->protect_braced_quotes === TRUE)

+		{

+			if (preg_match_all("#\{.+?}#si", $str, $matches))

+			{

+				for ($i = 0, $total = count($matches[0]); $i < $total; $i++)

+				{

+					$str = str_replace($matches[0][$i],

+										str_replace(array("'",'"'), array('{@SQ}', '{@DQ}'), $matches[0][$i]),

+										$str);

+				}

+			}			

+		}

+		

+		// Convert "ignore" tags to temporary marker.  The parser splits out the string at every tag 

+		// it encounters.  Certain inline tags, like image tags, links, span tags, etc. will be 

+		// adversely affected if they are split out so we'll convert the opening bracket < temporarily to: {@TAG}

+		$str = preg_replace("#<(/*)(".$this->inline_elements.")([ >])#i", "{@TAG}\\1\\2\\3", $str);

+

+		// Split the string at every tag.  This expression creates an array with this prototype:

+		// 

+		// 	[array]

+		// 	{

+		// 		[0] = <opening tag>

+		// 		[1] = Content...

+		// 		[2] = <closing tag>

+		// 		Etc...

+		// 	}	

+		$chunks = preg_split('/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

+		

+		// Build our finalized string.  We cycle through the array, skipping tags, and processing the contained text	

+		$str = '';

+		$process = TRUE;

+		$paragraph = FALSE;

+		foreach ($chunks as $chunk)

+		{

+			// Are we dealing with a tag? If so, we'll skip the processing for this cycle.

+			// Well also set the "process" flag which allows us to skip <pre> tags and a few other things.

+			if (preg_match("#<(/*)(".$this->block_elements.").*?>#", $chunk, $match))

+			{

+				if (preg_match("#".$this->skip_elements."#", $match[2]))

+				{

+					$process =  ($match[1] == '/') ? TRUE : FALSE;

+				}

+				

+				$str .= $chunk;

+				continue;

+			}

+			elseif (preg_match('/<(\/?)([a-z]*).*?>/s', $chunk, $tagmatch))

+			{

+				if ($tagmatch[1] == '/' && $tagmatch[2] == $this->last_tag)

+				{

+					$process = FALSE;

+				}

+				else

+				{

+					$process = TRUE;

+					$this->last_tag = $tagmatch[2];					

+				}

+			}

+

+			if ($process == FALSE)

+			{

+				$str .= $chunk;

+				continue;

+			}

+			

+			//  Convert Newlines into <p> and <br /> tags

+			$str .= $this->format_characters($this->_format_newlines($chunk));			

+		}

+

+		// is the whole of the content inside a block level element?

+		if ( ! preg_match("/^<(?:".$this->block_elements.")/i", $str, $match))

+		{

+			$str = "<p>{$str}</p>";

+		}

+

+

+		// some special linebreak cleanup

+		$str = preg_replace_callback('#<(?!/|'.$this->block_elements.')([^>]*)><p>(.*?)</p><(\w*)#si', array($this, '_linebreak_cleanup'), $str);

+		

+		// and cleanup empty paragraph tags sitting between two closing tags

+		$str = preg_replace('#(</\w+>)<p>(\s*)</p>(</\w+>)#si', '$1$2$3', $str);

+		

+		// Final clean up

+		$table = array(

+		

+						// If the user submitted their own paragraph tags within the text

+						// we will retain them instead of using our tags.

+						'/(<p[^>*?]>)<p>/'	=> '$1', // <?php BBEdit syntax coloring bug fix

+						

+						// Reduce multiple instances of opening/closing paragraph tags to a single one

+						'#(</p>)+#'			=> '</p>',

+						'/(<p>\W*<p>)+/'	=> '<p>',

+						

+						// Clean up stray paragraph tags that appear before block level elements

+						'#<p></p><('.$this->block_elements.')#'	=> '<$1',

+						

+						// Clean up open paragraph tags that appear before block level elements

+						'#<p>(\W)<('.$this->block_elements.')#'	=> '<p></p>$1<$2',

+

+						// Clean up stray non-breaking spaces preceeding block elements

+						'#[&nbsp; ]+<('.$this->block_elements.')#'	=> '  <$1',

+			

+						// Replace the temporary markers we added earlier

+						'/\{@TAG\}/'		=> '<',

+						'/\{@DQ\}/'			=> '"',

+						'/\{@SQ\}/'			=> "'",

+						'/\{@DD\}/'			=> '--',

+						'/\{@NBS\}/'		=> '  '

+

+						);

+

+		// Do we need to reduce empty lines?

+		if ($reduce_linebreaks === TRUE)

+		{

+			$table['#<p>\n*</p>#'] = '';

+		}

+		else

+		{

+			// If we have empty paragraph tags we add a non-breaking space

+			// otherwise most browsers won't treat them as true paragraphs

+			$table['#<p></p>#'] = '<p>&nbsp;</p>';

+		}

+	

+		return preg_replace(array_keys($table), $table, $str);

+

+	}

+	

+	// --------------------------------------------------------------------

+	

+	/**

+	 * Linebreak Cleanup

+	 *

+	 * Removes paragraph and line break tags inserted inbetween

+	 * inline content and a new opening block level element

+	 *

+	 * @access	private

+	 * @param	array

+	 * @return	string

+	 */

+	function _linebreak_cleanup($match)

+	{

+		if (in_array($match[3], explode('|', $this->block_elements)))

+		{

+			return "<{$match[1]}>".str_replace('<br />', '', $match[2])."<{$match[3]}";

+		}

+		else

+		{

+			return $match[0];

+		}

+	}

+

+	// --------------------------------------------------------------------

+	

+	/**

+	 * Format Characters

+	 *

+	 * This function mainly converts double and single quotes

+	 * to curly entities, but it also converts em-dashes,

+	 * double spaces, and ampersands

+	 *

+	 * @access	public

+	 * @param	string

+	 * @return	string

+	 */

+	function format_characters($str)

+	{

+		static $table;

+		

+		if ( ! isset($table))

+		{

+	        $table = array(					

+							// nested smart quotes, opening and closing

+							// note that rules for grammar (English) allow only for two levels deep

+							// and that single quotes are _supposed_ to always be on the outside

+							// but we'll accommodate both

+							'/(^|\W|\s)\'"/'				=> '$1&#8216;&#8220;',

+							'/\'"(\s|\W|$)/'				=> '&#8217;&#8221;$1',

+							'/(^|\W|\s)"\'/'				=> '$1&#8220;&#8216;',

+							'/"\'(\s|\W|$)/'				=> '&#8221;&#8217;$1',

+

+							// single quote smart quotes

+							'/\'(\s|\W|$)/'					=> '&#8217;$1',

+							'/(^|\W|\s)\'/'					=> '$1&#8216;',

+

+							// double quote smart quotes

+							'/"(\s|\W|$)/'					=> '&#8221;$1',

+							'/(^|\W|\s)"/'					=> '$1&#8220;',

+

+							// apostrophes

+							"/(\w)'(\w)/"       	    	=> '$1&#8217;$2',

+

+							// Em dash and ellipses dots

+							'/\s?\-\-\s?/'					=> '&#8212;',

+							'/(\w)\.{3}/'					=> '$1&#8230;',

+

+							// double space after sentences

+							'/(\W)  /'						=> '$1&nbsp; ',

+

+							// ampersands, if not a character entity

+							'/&(?!#?[a-zA-Z0-9]{2,};)/'		=> '&amp;'

+	        			);			

+		}	

+

+		return preg_replace(array_keys($table), $table, $str);

+	}

+	

+	// --------------------------------------------------------------------

+

+	/**

+	 * Format Newlines

+	 *

+	 * Converts newline characters into either <p> tags or <br />

+	 *

+	 * @access	public

+	 * @param	string

+	 * @return	string

+	 */	

+	function _format_newlines($str)

+	{

+		if ($str == '')

+		{

+			return $str;

+		}

+

+		if (strpos($str, "\n") === FALSE)

+		{

+			return $str;

+		}

+		

+		// Convert two consecutive newlines to paragraphs

+		$str = str_replace("\n\n", "</p>\n\n<p>", $str);

+		

+		// Convert single spaces to <br /> tags

+		$str = preg_replace("/([^\n])(\n)([^\n])/", "\\1<br />\\2\\3", $str);

+		

+		// Wrap the whole enchilada in enclosing paragraphs

+		if ($str != "\n")

+		{

+			$str =  '<p>'.$str.'</p>';

+		}

+

+		// Remove empty paragraphs if they are on the first line, as this

+		// is a potential unintended consequence of the previous code

+		$str = preg_replace("/<p><\/p>(.*)/", "\\1", $str, 1);

+		

+		return $str;

+	}

+	

+	// ------------------------------------------------------------------------

+	

+	/**

+	 * Convert newlines to HTML line breaks except within PRE tags

+	 *

+	 * @access	public

+	 * @param	string

+	 * @return	string

+	 */		

+	function nl2br_except_pre($str)

+	{

+		$ex = explode("pre>",$str);

+		$ct = count($ex);

+	

+		$newstr = "";

+		for ($i = 0; $i < $ct; $i++)

+		{

+			if (($i % 2) == 0)

+			{

+				$newstr .= nl2br($ex[$i]);

+			}

+			else

+			{

+				$newstr .= $ex[$i];

+			}

+		

+			if ($ct - 1 != $i)

+				$newstr .= "pre>";

+		}

+	

+		return $newstr;

+	}

+	

+}

+// END Typography Class

+

+/* End of file Typography.php */

 /* Location: ./system/libraries/Typography.php */
\ No newline at end of file
diff --git a/system/libraries/URI.php b/system/libraries/URI.php
index aa2d71e..b27dfa3 100644
--- a/system/libraries/URI.php
+++ b/system/libraries/URI.php
@@ -1,585 +1,585 @@
-<?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
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * URI Class
- *
- * Parses URIs and determines routing
- *
- * @package		CodeIgniter
- * @subpackage	Libraries
- * @category	URI
- * @author		ExpressionEngine Dev Team
- * @link		http://codeigniter.com/user_guide/libraries/uri.html
- */
-class CI_URI {
-
-	var	$keyval	= array();
-	var $uri_string;
-	var $segments		= array();
-	var $rsegments		= array();
-
-	/**
-	 * Constructor
-	 *
-	 * Simply globalizes the $RTR object.  The front
-	 * loads the Router class early on so it's not available
-	 * normally as other classes are.
-	 *
-	 * @access	public
-	 */
-	function CI_URI()
-	{
-		$this->config =& load_class('Config');
-		log_message('debug', "URI Class Initialized");
-	}
-
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Get the URI String
-	 *
-	 * @access	private
-	 * @return	string
-	 */
-	function _fetch_uri_string()
-	{
-		if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
-		{
-			// If the URL has a question mark then it's simplest to just
-			// build the URI string from the zero index of the $_GET array.
-			// This avoids having to deal with $_SERVER variables, which
-			// can be unreliable in some environments
-			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
-			{
-				$this->uri_string = key($_GET);
-				return;
-			}
-
-			// Is there a PATH_INFO variable?
-			// Note: some servers seem to have trouble with getenv() so we'll test it two ways
-			$path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
-			if (trim($path, '/') != '' && $path != "/".SELF)
-			{
-				$this->uri_string = $path;
-				return;
-			}
-
-			// No PATH_INFO?... What about QUERY_STRING?
-			$path =  (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
-			if (trim($path, '/') != '')
-			{
-				$this->uri_string = $path;
-				return;
-			}
-
-			// No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?
-			$path = (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO');
-			if (trim($path, '/') != '' && $path != "/".SELF)
-			{
-				// remove path and script information so we have good URI data
-				$this->uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $path);
-				return;
-			}
-
-			// We've exhausted all our options...
-			$this->uri_string = '';
-		}
-		else
-		{
-			$uri = strtoupper($this->config->item('uri_protocol'));
-
-			if ($uri == 'REQUEST_URI')
-			{
-				$this->uri_string = $this->_parse_request_uri();
-				return;
-			}
-
-			$this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
-		}
-
-		// If the URI contains only a slash we'll kill it
-		if ($this->uri_string == '/')
-		{
-			$this->uri_string = '';
-		}
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Parse the REQUEST_URI
-	 *
-	 * Due to the way REQUEST_URI works it usually contains path info
-	 * that makes it unusable as URI data.  We'll trim off the unnecessary
-	 * data, hopefully arriving at a valid URI that we can use.
-	 *
-	 * @access	private
-	 * @return	string
-	 */
-	function _parse_request_uri()
-	{
-		if ( ! isset($_SERVER['REQUEST_URI']) OR $_SERVER['REQUEST_URI'] == '')
-		{
-			return '';
-		}
-
-		$request_uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));
-
-		if ($request_uri == '' OR $request_uri == SELF)
-		{
-			return '';
-		}
-
-		$fc_path = FCPATH;
-		if (strpos($request_uri, '?') !== FALSE)
-		{
-			$fc_path .= '?';
-		}
-
-		$parsed_uri = explode("/", $request_uri);
-
-		$i = 0;
-		foreach(explode("/", $fc_path) as $segment)
-		{
-			if (isset($parsed_uri[$i]) && $segment == $parsed_uri[$i])
-			{
-				$i++;
-			}
-		}
-
-		$parsed_uri = implode("/", array_slice($parsed_uri, $i));
-
-		if ($parsed_uri != '')
-		{
-			$parsed_uri = '/'.$parsed_uri;
-		}
-
-		return $parsed_uri;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Filter segments for malicious characters
-	 *
-	 * @access	private
-	 * @param	string
-	 * @return	string
-	 */
-	function _filter_uri($str)
-	{
-		if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
-		{
-			if ( ! preg_match("|^[".preg_quote($this->config->item('permitted_uri_chars'))."]+$|i", $str))
-			{
-				header('HTTP/1.1 400 Bad Request');
-				exit('The URI you submitted has disallowed characters.');
-			}
-		}
-
-		// Convert programatic characters to entities
-		$bad	= array('$', 		'(', 		')',	 	'%28', 		'%29');
-		$good	= array('&#36;',	'&#40;',	'&#41;',	'&#40;',	'&#41;');
-
-		return str_replace($bad, $good, $str);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Remove the suffix from the URL if needed
-	 *
-	 * @access	private
-	 * @return	void
-	 */
-	function _remove_url_suffix()
-	{
-		if  ($this->config->item('url_suffix') != "")
-		{
-			$this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
-		}
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Explode the URI Segments. The individual segments will
-	 * be stored in the $this->segments array.
-	 *
-	 * @access	private
-	 * @return	void
-	 */
-	function _explode_segments()
-	{
-		foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
-		{
-			// Filter segments for security
-			$val = trim($this->_filter_uri($val));
-
-			if ($val != '')
-			{
-				$this->segments[] = $val;
-			}
-		}
-	}
-
-	// --------------------------------------------------------------------
-	/**
-	 * Re-index Segments
-	 *
-	 * This function re-indexes the $this->segment array so that it
-	 * starts at 1 rather than 0.  Doing so makes it simpler to
-	 * use functions like $this->uri->segment(n) since there is
-	 * a 1:1 relationship between the segment array and the actual segments.
-	 *
-	 * @access	private
-	 * @return	void
-	 */
-	function _reindex_segments()
-	{
-		array_unshift($this->segments, NULL);
-		array_unshift($this->rsegments, NULL);
-		unset($this->segments[0]);
-		unset($this->rsegments[0]);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch a URI Segment
-	 *
-	 * This function returns the URI segment based on the number provided.
-	 *
-	 * @access	public
-	 * @param	integer
-	 * @param	bool
-	 * @return	string
-	 */
-	function segment($n, $no_result = FALSE)
-	{
-		return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch a URI "routed" Segment
-	 *
-	 * This function returns the re-routed URI segment (assuming routing rules are used)
-	 * based on the number provided.  If there is no routing this function returns the
-	 * same result as $this->segment()
-	 *
-	 * @access	public
-	 * @param	integer
-	 * @param	bool
-	 * @return	string
-	 */
-	function rsegment($n, $no_result = FALSE)
-	{
-		return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Generate a key value pair from the URI string
-	 *
-	 * This function generates and associative array of URI data starting
-	 * at the supplied segment. For example, if this is your URI:
-	 *
-	 *	example.com/user/search/name/joe/location/UK/gender/male
-	 *
-	 * You can use this function to generate an array with this prototype:
-	 *
-	 * array (
-	 *			name => joe
-	 *			location => UK
-	 *			gender => male
-	 *		 )
-	 *
-	 * @access	public
-	 * @param	integer	the starting segment number
-	 * @param	array	an array of default values
-	 * @return	array
-	 */
-	function uri_to_assoc($n = 3, $default = array())
-	{
-	 	return $this->_uri_to_assoc($n, $default, 'segment');
-	}
-	/**
-	 * Identical to above only it uses the re-routed segment array
-	 *
-	 */
-	function ruri_to_assoc($n = 3, $default = array())
-	{
-	 	return $this->_uri_to_assoc($n, $default, 'rsegment');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Generate a key value pair from the URI string or Re-routed URI string
-	 *
-	 * @access	private
-	 * @param	integer	the starting segment number
-	 * @param	array	an array of default values
-	 * @param	string	which array we should use
-	 * @return	array
-	 */
-	function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
-	{
-		if ($which == 'segment')
-		{
-			$total_segments = 'total_segments';
-			$segment_array = 'segment_array';
-		}
-		else
-		{
-			$total_segments = 'total_rsegments';
-			$segment_array = 'rsegment_array';
-		}
-
-		if ( ! is_numeric($n))
-		{
-			return $default;
-		}
-
-		if (isset($this->keyval[$n]))
-		{
-			return $this->keyval[$n];
-		}
-
-		if ($this->$total_segments() < $n)
-		{
-			if (count($default) == 0)
-			{
-				return array();
-			}
-
-			$retval = array();
-			foreach ($default as $val)
-			{
-				$retval[$val] = FALSE;
-			}
-			return $retval;
-		}
-
-		$segments = array_slice($this->$segment_array(), ($n - 1));
-
-		$i = 0;
-		$lastval = '';
-		$retval  = array();
-		foreach ($segments as $seg)
-		{
-			if ($i % 2)
-			{
-				$retval[$lastval] = $seg;
-			}
-			else
-			{
-				$retval[$seg] = FALSE;
-				$lastval = $seg;
-			}
-
-			$i++;
-		}
-
-		if (count($default) > 0)
-		{
-			foreach ($default as $val)
-			{
-				if ( ! array_key_exists($val, $retval))
-				{
-					$retval[$val] = FALSE;
-				}
-			}
-		}
-
-		// Cache the array for reuse
-		$this->keyval[$n] = $retval;
-		return $retval;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Generate a URI string from an associative array
-	 *
-	 *
-	 * @access	public
-	 * @param	array	an associative array of key/values
-	 * @return	array
-	 */
-	function assoc_to_uri($array)
-	{
-		$temp = array();
-		foreach ((array)$array as $key => $val)
-		{
-			$temp[] = $key;
-			$temp[] = $val;
-		}
-
-		return implode('/', $temp);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch a URI Segment and add a trailing slash
-	 *
-	 * @access	public
-	 * @param	integer
-	 * @param	string
-	 * @return	string
-	 */
-	function slash_segment($n, $where = 'trailing')
-	{
-		return $this->_slash_segment($n, $where, 'segment');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch a URI Segment and add a trailing slash
-	 *
-	 * @access	public
-	 * @param	integer
-	 * @param	string
-	 * @return	string
-	 */
-	function slash_rsegment($n, $where = 'trailing')
-	{
-		return $this->_slash_segment($n, $where, 'rsegment');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch a URI Segment and add a trailing slash - helper function
-	 *
-	 * @access	private
-	 * @param	integer
-	 * @param	string
-	 * @param	string
-	 * @return	string
-	 */
-	function _slash_segment($n, $where = 'trailing', $which = 'segment')
-	{
-		if ($where == 'trailing')
-		{
-			$trailing	= '/';
-			$leading	= '';
-		}
-		elseif ($where == 'leading')
-		{
-			$leading	= '/';
-			$trailing	= '';
-		}
-		else
-		{
-			$leading	= '/';
-			$trailing	= '/';
-		}
-		return $leading.$this->$which($n).$trailing;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Segment Array
-	 *
-	 * @access	public
-	 * @return	array
-	 */
-	function segment_array()
-	{
-		return $this->segments;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Routed Segment Array
-	 *
-	 * @access	public
-	 * @return	array
-	 */
-	function rsegment_array()
-	{
-		return $this->rsegments;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Total number of segments
-	 *
-	 * @access	public
-	 * @return	integer
-	 */
-	function total_segments()
-	{
-		return count($this->segments);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Total number of routed segments
-	 *
-	 * @access	public
-	 * @return	integer
-	 */
-	function total_rsegments()
-	{
-		return count($this->rsegments);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch the entire URI string
-	 *
-	 * @access	public
-	 * @return	string
-	 */
-	function uri_string()
-	{
-		return $this->uri_string;
-	}
-
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Fetch the entire Re-routed URI string
-	 *
-	 * @access	public
-	 * @return	string
-	 */
-	function ruri_string()
-	{
-		return '/'.implode('/', $this->rsegment_array()).'/';
-	}
-
-}
-// END URI Class
-
-/* End of file URI.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

+ */

+

+// ------------------------------------------------------------------------

+

+/**

+ * URI Class

+ *

+ * Parses URIs and determines routing

+ *

+ * @package		CodeIgniter

+ * @subpackage	Libraries

+ * @category	URI

+ * @author		ExpressionEngine Dev Team

+ * @link		http://codeigniter.com/user_guide/libraries/uri.html

+ */

+class CI_URI {

+

+	var	$keyval	= array();

+	var $uri_string;

+	var $segments		= array();

+	var $rsegments		= array();

+

+	/**

+	 * Constructor

+	 *

+	 * Simply globalizes the $RTR object.  The front

+	 * loads the Router class early on so it's not available

+	 * normally as other classes are.

+	 *

+	 * @access	public

+	 */

+	function CI_URI()

+	{

+		$this->config =& load_class('Config');

+		log_message('debug', "URI Class Initialized");

+	}

+

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Get the URI String

+	 *

+	 * @access	private

+	 * @return	string

+	 */

+	function _fetch_uri_string()

+	{

+		if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')

+		{

+			// If the URL has a question mark then it's simplest to just

+			// build the URI string from the zero index of the $_GET array.

+			// This avoids having to deal with $_SERVER variables, which

+			// can be unreliable in some environments

+			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')

+			{

+				$this->uri_string = key($_GET);

+				return;

+			}

+

+			// Is there a PATH_INFO variable?

+			// Note: some servers seem to have trouble with getenv() so we'll test it two ways

+			$path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');

+			if (trim($path, '/') != '' && $path != "/".SELF)

+			{

+				$this->uri_string = $path;

+				return;

+			}

+

+			// No PATH_INFO?... What about QUERY_STRING?

+			$path =  (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');

+			if (trim($path, '/') != '')

+			{

+				$this->uri_string = $path;

+				return;

+			}

+

+			// No QUERY_STRING?... Maybe the ORIG_PATH_INFO variable exists?

+			$path = (isset($_SERVER['ORIG_PATH_INFO'])) ? $_SERVER['ORIG_PATH_INFO'] : @getenv('ORIG_PATH_INFO');

+			if (trim($path, '/') != '' && $path != "/".SELF)

+			{

+				// remove path and script information so we have good URI data

+				$this->uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $path);

+				return;

+			}

+

+			// We've exhausted all our options...

+			$this->uri_string = '';

+		}

+		else

+		{

+			$uri = strtoupper($this->config->item('uri_protocol'));

+

+			if ($uri == 'REQUEST_URI')

+			{

+				$this->uri_string = $this->_parse_request_uri();

+				return;

+			}

+

+			$this->uri_string = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);

+		}

+

+		// If the URI contains only a slash we'll kill it

+		if ($this->uri_string == '/')

+		{

+			$this->uri_string = '';

+		}

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Parse the REQUEST_URI

+	 *

+	 * Due to the way REQUEST_URI works it usually contains path info

+	 * that makes it unusable as URI data.  We'll trim off the unnecessary

+	 * data, hopefully arriving at a valid URI that we can use.

+	 *

+	 * @access	private

+	 * @return	string

+	 */

+	function _parse_request_uri()

+	{

+		if ( ! isset($_SERVER['REQUEST_URI']) OR $_SERVER['REQUEST_URI'] == '')

+		{

+			return '';

+		}

+

+		$request_uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));

+

+		if ($request_uri == '' OR $request_uri == SELF)

+		{

+			return '';

+		}

+

+		$fc_path = FCPATH;

+		if (strpos($request_uri, '?') !== FALSE)

+		{

+			$fc_path .= '?';

+		}

+

+		$parsed_uri = explode("/", $request_uri);

+

+		$i = 0;

+		foreach(explode("/", $fc_path) as $segment)

+		{

+			if (isset($parsed_uri[$i]) && $segment == $parsed_uri[$i])

+			{

+				$i++;

+			}

+		}

+

+		$parsed_uri = implode("/", array_slice($parsed_uri, $i));

+

+		if ($parsed_uri != '')

+		{

+			$parsed_uri = '/'.$parsed_uri;

+		}

+

+		return $parsed_uri;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Filter segments for malicious characters

+	 *

+	 * @access	private

+	 * @param	string

+	 * @return	string

+	 */

+	function _filter_uri($str)

+	{

+		if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)

+		{

+			if ( ! preg_match("|^[".preg_quote($this->config->item('permitted_uri_chars'))."]+$|i", $str))

+			{

+				header('HTTP/1.1 400 Bad Request');

+				exit('The URI you submitted has disallowed characters.');

+			}

+		}

+

+		// Convert programatic characters to entities

+		$bad	= array('$', 		'(', 		')',	 	'%28', 		'%29');

+		$good	= array('&#36;',	'&#40;',	'&#41;',	'&#40;',	'&#41;');

+

+		return str_replace($bad, $good, $str);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Remove the suffix from the URL if needed

+	 *

+	 * @access	private

+	 * @return	void

+	 */

+	function _remove_url_suffix()

+	{

+		if  ($this->config->item('url_suffix') != "")

+		{

+			$this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);

+		}

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Explode the URI Segments. The individual segments will

+	 * be stored in the $this->segments array.

+	 *

+	 * @access	private

+	 * @return	void

+	 */

+	function _explode_segments()

+	{

+		foreach(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)

+		{

+			// Filter segments for security

+			$val = trim($this->_filter_uri($val));

+

+			if ($val != '')

+			{

+				$this->segments[] = $val;

+			}

+		}

+	}

+

+	// --------------------------------------------------------------------

+	/**

+	 * Re-index Segments

+	 *

+	 * This function re-indexes the $this->segment array so that it

+	 * starts at 1 rather than 0.  Doing so makes it simpler to

+	 * use functions like $this->uri->segment(n) since there is

+	 * a 1:1 relationship between the segment array and the actual segments.

+	 *

+	 * @access	private

+	 * @return	void

+	 */

+	function _reindex_segments()

+	{

+		array_unshift($this->segments, NULL);

+		array_unshift($this->rsegments, NULL);

+		unset($this->segments[0]);

+		unset($this->rsegments[0]);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch a URI Segment

+	 *

+	 * This function returns the URI segment based on the number provided.

+	 *

+	 * @access	public

+	 * @param	integer

+	 * @param	bool

+	 * @return	string

+	 */

+	function segment($n, $no_result = FALSE)

+	{

+		return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch a URI "routed" Segment

+	 *

+	 * This function returns the re-routed URI segment (assuming routing rules are used)

+	 * based on the number provided.  If there is no routing this function returns the

+	 * same result as $this->segment()

+	 *

+	 * @access	public

+	 * @param	integer

+	 * @param	bool

+	 * @return	string

+	 */

+	function rsegment($n, $no_result = FALSE)

+	{

+		return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Generate a key value pair from the URI string

+	 *

+	 * This function generates and associative array of URI data starting

+	 * at the supplied segment. For example, if this is your URI:

+	 *

+	 *	example.com/user/search/name/joe/location/UK/gender/male

+	 *

+	 * You can use this function to generate an array with this prototype:

+	 *

+	 * array (

+	 *			name => joe

+	 *			location => UK

+	 *			gender => male

+	 *		 )

+	 *

+	 * @access	public

+	 * @param	integer	the starting segment number

+	 * @param	array	an array of default values

+	 * @return	array

+	 */

+	function uri_to_assoc($n = 3, $default = array())

+	{

+	 	return $this->_uri_to_assoc($n, $default, 'segment');

+	}

+	/**

+	 * Identical to above only it uses the re-routed segment array

+	 *

+	 */

+	function ruri_to_assoc($n = 3, $default = array())

+	{

+	 	return $this->_uri_to_assoc($n, $default, 'rsegment');

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Generate a key value pair from the URI string or Re-routed URI string

+	 *

+	 * @access	private

+	 * @param	integer	the starting segment number

+	 * @param	array	an array of default values

+	 * @param	string	which array we should use

+	 * @return	array

+	 */

+	function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')

+	{

+		if ($which == 'segment')

+		{

+			$total_segments = 'total_segments';

+			$segment_array = 'segment_array';

+		}

+		else

+		{

+			$total_segments = 'total_rsegments';

+			$segment_array = 'rsegment_array';

+		}

+

+		if ( ! is_numeric($n))

+		{

+			return $default;

+		}

+

+		if (isset($this->keyval[$n]))

+		{

+			return $this->keyval[$n];

+		}

+

+		if ($this->$total_segments() < $n)

+		{

+			if (count($default) == 0)

+			{

+				return array();

+			}

+

+			$retval = array();

+			foreach ($default as $val)

+			{

+				$retval[$val] = FALSE;

+			}

+			return $retval;

+		}

+

+		$segments = array_slice($this->$segment_array(), ($n - 1));

+

+		$i = 0;

+		$lastval = '';

+		$retval  = array();

+		foreach ($segments as $seg)

+		{

+			if ($i % 2)

+			{

+				$retval[$lastval] = $seg;

+			}

+			else

+			{

+				$retval[$seg] = FALSE;

+				$lastval = $seg;

+			}

+

+			$i++;

+		}

+

+		if (count($default) > 0)

+		{

+			foreach ($default as $val)

+			{

+				if ( ! array_key_exists($val, $retval))

+				{

+					$retval[$val] = FALSE;

+				}

+			}

+		}

+

+		// Cache the array for reuse

+		$this->keyval[$n] = $retval;

+		return $retval;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Generate a URI string from an associative array

+	 *

+	 *

+	 * @access	public

+	 * @param	array	an associative array of key/values

+	 * @return	array

+	 */

+	function assoc_to_uri($array)

+	{

+		$temp = array();

+		foreach ((array)$array as $key => $val)

+		{

+			$temp[] = $key;

+			$temp[] = $val;

+		}

+

+		return implode('/', $temp);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch a URI Segment and add a trailing slash

+	 *

+	 * @access	public

+	 * @param	integer

+	 * @param	string

+	 * @return	string

+	 */

+	function slash_segment($n, $where = 'trailing')

+	{

+		return $this->_slash_segment($n, $where, 'segment');

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch a URI Segment and add a trailing slash

+	 *

+	 * @access	public

+	 * @param	integer

+	 * @param	string

+	 * @return	string

+	 */

+	function slash_rsegment($n, $where = 'trailing')

+	{

+		return $this->_slash_segment($n, $where, 'rsegment');

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch a URI Segment and add a trailing slash - helper function

+	 *

+	 * @access	private

+	 * @param	integer

+	 * @param	string

+	 * @param	string

+	 * @return	string

+	 */

+	function _slash_segment($n, $where = 'trailing', $which = 'segment')

+	{

+		if ($where == 'trailing')

+		{

+			$trailing	= '/';

+			$leading	= '';

+		}

+		elseif ($where == 'leading')

+		{

+			$leading	= '/';

+			$trailing	= '';

+		}

+		else

+		{

+			$leading	= '/';

+			$trailing	= '/';

+		}

+		return $leading.$this->$which($n).$trailing;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Segment Array

+	 *

+	 * @access	public

+	 * @return	array

+	 */

+	function segment_array()

+	{

+		return $this->segments;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Routed Segment Array

+	 *

+	 * @access	public

+	 * @return	array

+	 */

+	function rsegment_array()

+	{

+		return $this->rsegments;

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Total number of segments

+	 *

+	 * @access	public

+	 * @return	integer

+	 */

+	function total_segments()

+	{

+		return count($this->segments);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Total number of routed segments

+	 *

+	 * @access	public

+	 * @return	integer

+	 */

+	function total_rsegments()

+	{

+		return count($this->rsegments);

+	}

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch the entire URI string

+	 *

+	 * @access	public

+	 * @return	string

+	 */

+	function uri_string()

+	{

+		return $this->uri_string;

+	}

+

+

+	// --------------------------------------------------------------------

+

+	/**

+	 * Fetch the entire Re-routed URI string

+	 *

+	 * @access	public

+	 * @return	string

+	 */

+	function ruri_string()

+	{

+		return '/'.implode('/', $this->rsegment_array()).'/';

+	}

+

+}

+// END URI Class

+

+/* End of file URI.php */

 /* Location: ./system/libraries/URI.php */
\ No newline at end of file
diff --git a/system/scaffolding/views/add.php b/system/scaffolding/views/add.php
index cbb12f6..cac255a 100644
--- a/system/scaffolding/views/add.php
+++ b/system/scaffolding/views/add.php
@@ -1,32 +1,32 @@
-<?php  $this->load->view('header');  ?>
-
-<p><?php echo anchor(array($base_uri, 'view'), '&lt; '.$scaff_view_all); ?></p>
-
-
-<?php echo form_open($action); ?>
-
-<table border="0" cellpadding="3" cellspacing="1">
-<?php foreach($fields as $field): ?>
-
-<?php if ($field->primary_key == 1) continue; ?>
-
-<tr>
-	<td><?php echo $field->name; echo ' '.$field->default; ?></td>
-	
-	<?php if ($field->type == 'blob'): ?>
-	<td><textarea class="textarea" name="<?php echo $field->name; ?>" cols="60" rows="10" ><?php echo form_prep($field->default); ?></textarea></td>
-	<?php else : ?>
-	<td><input class="input" name="<?php echo $field->name; ?>" value="<?php echo form_prep($field->default); ?>" size="60" /></td>
-	<?php endif; ?>
-	
-</tr>
-<?php endforeach; ?>
-</table>
-
-<input type="submit" class="submit" value="Insert" />
-
-</form>
-
-<?php $this->load->view('footer'); 
-/* End of file add.php */
-/* Location: ./system/scaffolding/views/add.php */
+<?php  $this->load->view('header');  ?>

+

+<p><?php echo anchor(array($base_uri, 'view'), '&lt; '.$scaff_view_all); ?></p>

+

+

+<?php echo form_open($action); ?>

+

+<table border="0" cellpadding="3" cellspacing="1">

+<?php foreach($fields as $field): ?>

+

+<?php if ($field->primary_key == 1) continue; ?>

+

+<tr>

+	<td><?php echo $field->name; echo ' '.$field->default; ?></td>

+	

+	<?php if ($field->type == 'blob'): ?>

+	<td><textarea class="textarea" name="<?php echo $field->name; ?>" cols="60" rows="10" ><?php echo form_prep($field->default); ?></textarea></td>

+	<?php else : ?>

+	<td><input class="input" name="<?php echo $field->name; ?>" value="<?php echo form_prep($field->default); ?>" size="60" /></td>

+	<?php endif; ?>

+	

+</tr>

+<?php endforeach; ?>

+</table>

+

+<input type="submit" class="submit" value="Insert" />

+

+</form>

+

+<?php $this->load->view('footer'); 

+/* End of file add.php */

+/* Location: ./system/scaffolding/views/add.php */

diff --git a/system/scaffolding/views/delete.php b/system/scaffolding/views/delete.php
index d195421..87b59be 100644
--- a/system/scaffolding/views/delete.php
+++ b/system/scaffolding/views/delete.php
@@ -1,9 +1,9 @@
-<?php  $this->load->view('header');  ?>
-
-<p><?php echo $message; ?></p>
-
-<p><?php echo $no; ?>&nbsp;&nbsp;|&nbsp;&nbsp;<?php echo $yes; ?>
-
-<?php $this->load->view('footer'); 
-/* End of file delete.php */
-/* Location: ./system/scaffolding/views/delete.php */
+<?php  $this->load->view('header');  ?>

+

+<p><?php echo $message; ?></p>

+

+<p><?php echo $no; ?>&nbsp;&nbsp;|&nbsp;&nbsp;<?php echo $yes; ?>

+

+<?php $this->load->view('footer'); 

+/* End of file delete.php */

+/* Location: ./system/scaffolding/views/delete.php */

diff --git a/system/scaffolding/views/edit.php b/system/scaffolding/views/edit.php
index fe553e5..c66259d 100644
--- a/system/scaffolding/views/edit.php
+++ b/system/scaffolding/views/edit.php
@@ -1,33 +1,33 @@
-<?php $this->load->view('header');  ?>
-
-
-<p><?php echo anchor(array($base_uri, 'view'), '&lt; '.$scaff_view_all);?></p>
-
-
-<?php echo form_open($action); ?>
-
-<table border="0" cellpadding="3" cellspacing="1">
-<?php foreach($fields as $field): ?>
-
-<?php if ($field->primary_key == 1) continue; ?>
-
-<tr>
-	<td><?php echo  $field->name; ?></td>
-	
-	<?php if ($field->type == 'blob'): ?>
-	<td><textarea class="textarea" name="<?php echo $field->name;?>" cols="60" rows="10" ><?php $f = $field->name; echo form_prep($query->$f); ?></textarea></td>
-	<?php else : ?>
-	<td><input class="input" value="<?php $f = $field->name; echo form_prep($query->$f); ?>" name="<?php echo $field->name; ?>" size="60" /></td>
-	<?php endif; ?>
-	
-</tr>
-<?php endforeach; ?>
-</table>
-
-<input type="submit" class="submit" value="Update" />
-
-</form>
-
-<?php $this->load->view('footer'); 
-/* End of file edit.php */
+<?php $this->load->view('header');  ?>

+

+

+<p><?php echo anchor(array($base_uri, 'view'), '&lt; '.$scaff_view_all);?></p>

+

+

+<?php echo form_open($action); ?>

+

+<table border="0" cellpadding="3" cellspacing="1">

+<?php foreach($fields as $field): ?>

+

+<?php if ($field->primary_key == 1) continue; ?>

+

+<tr>

+	<td><?php echo  $field->name; ?></td>

+	

+	<?php if ($field->type == 'blob'): ?>

+	<td><textarea class="textarea" name="<?php echo $field->name;?>" cols="60" rows="10" ><?php $f = $field->name; echo form_prep($query->$f); ?></textarea></td>

+	<?php else : ?>

+	<td><input class="input" value="<?php $f = $field->name; echo form_prep($query->$f); ?>" name="<?php echo $field->name; ?>" size="60" /></td>

+	<?php endif; ?>

+	

+</tr>

+<?php endforeach; ?>

+</table>

+

+<input type="submit" class="submit" value="Update" />

+

+</form>

+

+<?php $this->load->view('footer'); 

+/* End of file edit.php */

 /* Location: ./system/scaffolding/views/edit.php */
\ No newline at end of file
diff --git a/system/scaffolding/views/header.php b/system/scaffolding/views/header.php
index 50f234a..a1621ff 100644
--- a/system/scaffolding/views/header.php
+++ b/system/scaffolding/views/header.php
@@ -1,29 +1,29 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
-<head>
-
-<title><?php echo $title; ?></title>
-
-<style type='text/css'>
-<?php $this->file(BASEPATH.'scaffolding/views/stylesheet.css'); ?>
-</style>
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta http-equiv='expires' content='-1' />
-<meta http-equiv= 'pragma' content='no-cache' />
-
-</head>
-<body>
-
-<div id="header">
-<div id="header_left">
-<h3>Scaffolding:&nbsp; <?php echo $title; ?></h3>
-</div>
-<div id="header_right">
-<?php echo anchor(array($base_uri, 'view'), $scaff_view_records); ?> &nbsp;&nbsp;|&nbsp;&nbsp;
-<?php echo anchor(array($base_uri, 'add'),  $scaff_create_record); ?>
-</div>
-</div>
-
-<br clear="all">
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html>

+<head>

+

+<title><?php echo $title; ?></title>

+

+<style type='text/css'>

+<?php $this->file(BASEPATH.'scaffolding/views/stylesheet.css'); ?>

+</style>

+

+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

+<meta http-equiv='expires' content='-1' />

+<meta http-equiv= 'pragma' content='no-cache' />

+

+</head>

+<body>

+

+<div id="header">

+<div id="header_left">

+<h3>Scaffolding:&nbsp; <?php echo $title; ?></h3>

+</div>

+<div id="header_right">

+<?php echo anchor(array($base_uri, 'view'), $scaff_view_records); ?> &nbsp;&nbsp;|&nbsp;&nbsp;

+<?php echo anchor(array($base_uri, 'add'),  $scaff_create_record); ?>

+</div>

+</div>

+

+<br clear="all">

 <div id="outer">
\ No newline at end of file
diff --git a/system/scaffolding/views/no_data.php b/system/scaffolding/views/no_data.php
index bc81e74..963341b 100644
--- a/system/scaffolding/views/no_data.php
+++ b/system/scaffolding/views/no_data.php
@@ -1,8 +1,8 @@
-<?php  $this->load->view('header');  ?>
-
-<p><?php echo $scaff_no_data; ?></p>
-<p><?php echo anchor(array($base_uri, 'add'), $scaff_create_record); ?></p>
-
-<?php $this->load->view('footer'); 
-/* End of file no_data.php */
+<?php  $this->load->view('header');  ?>

+

+<p><?php echo $scaff_no_data; ?></p>

+<p><?php echo anchor(array($base_uri, 'add'), $scaff_create_record); ?></p>

+

+<?php $this->load->view('footer'); 

+/* End of file no_data.php */

 /* Location: ./system/scaffolding/views/no_data.php */
\ No newline at end of file
diff --git a/system/scaffolding/views/view.php b/system/scaffolding/views/view.php
index a81241d..69c1f45 100644
--- a/system/scaffolding/views/view.php
+++ b/system/scaffolding/views/view.php
@@ -1,27 +1,27 @@
-<?php  $this->load->view('header');  ?>
-
-<table border="0" cellpadding="0" cellspacing="1" style="width:100%">
- <tr>
-	<th>Edit</th>
-	<th>Delete</th>
-	<?php foreach($fields as $field): ?>
-	<th><?php echo $field; ?></th>
-	<?php endforeach; ?>
-</tr>
-
-<?php foreach($query->result() as $row): ?>
- <tr>
-	<td>&nbsp;<?php echo anchor(array($base_uri, 'edit', $row->$primary), $scaff_edit); ?>&nbsp;</td>
- 	<td><?php echo anchor(array($base_uri, 'delete', $row->$primary), $scaff_delete); ?></td>
- 	<?php foreach($fields as $field): ?>	
-	<td><?php echo form_prep($row->$field);?></td>
-	<?php endforeach; ?>
- </tr>
-<?php endforeach; ?>
-</table>
-
-<?php echo $paginate; ?>
-
-<?php $this->load->view('footer'); 
-/* End of file view.php */
+<?php  $this->load->view('header');  ?>

+

+<table border="0" cellpadding="0" cellspacing="1" style="width:100%">

+ <tr>

+	<th>Edit</th>

+	<th>Delete</th>

+	<?php foreach($fields as $field): ?>

+	<th><?php echo $field; ?></th>

+	<?php endforeach; ?>

+</tr>

+

+<?php foreach($query->result() as $row): ?>

+ <tr>

+	<td>&nbsp;<?php echo anchor(array($base_uri, 'edit', $row->$primary), $scaff_edit); ?>&nbsp;</td>

+ 	<td><?php echo anchor(array($base_uri, 'delete', $row->$primary), $scaff_delete); ?></td>

+ 	<?php foreach($fields as $field): ?>	

+	<td><?php echo form_prep($row->$field);?></td>

+	<?php endforeach; ?>

+ </tr>

+<?php endforeach; ?>

+</table>

+

+<?php echo $paginate; ?>

+

+<?php $this->load->view('footer'); 

+/* End of file view.php */

 /* Location: ./system/scaffolding/views/view.php */
\ No newline at end of file