Initial Import
diff --git a/system/helpers/array_helper.php b/system/helpers/array_helper.php
new file mode 100644
index 0000000..cccde1f
--- /dev/null
+++ b/system/helpers/array_helper.php
@@ -0,0 +1,47 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Array Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/array_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Random Element - Takes an array as input and returns a random element
+ *
+ * @access	public
+ * @param	array
+ * @return	mixed	depends on what the array contains
+ */	
+function random_element($array)
+{
+	if ( ! is_array($array))
+	{
+		return $array;
+	}
+	return $array[array_rand($array)];
+}
+
+
+?>
\ No newline at end of file
diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php
new file mode 100644
index 0000000..24e243d
--- /dev/null
+++ b/system/helpers/cookie_helper.php
@@ -0,0 +1,77 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Cookie Helpers
+ * 
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/cookie_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Set cookie
+ *
+ * Accepts six parameter, or you can submit an associative 
+ * array in the first parameter containing all the values.
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string	the value of the cookie
+ * @param	string	the number of seconds until expiration
+ * @param	string	the cookie domain.  Usually:  .yourdomain.com
+ * @param	string	the cookie path
+ * @param	string	the cookie prefix
+ * @return	void
+ */
+function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '')
+{ 
+	if (is_array($name))
+	{		
+		foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'name') as $item)
+		{
+			if (isset($name[$item]))
+			{
+				$$item = $name[$item];
+			}
+		}
+	}
+	
+	if ( ! is_numeric($expire))
+	{
+		$expire = time() - 86500;
+	}
+	else
+	{
+		if ($expire > 0)
+		{
+			$expire = time() + $expire;
+		}
+		else
+		{
+			$expire = 0;
+		}
+	}
+	
+	setcookie($prefix.$name, $value, $expire, $path, $domain, 0);
+}
+
+?>
\ No newline at end of file
diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php
new file mode 100644
index 0000000..2a3d508
--- /dev/null
+++ b/system/helpers/date_helper.php
@@ -0,0 +1,530 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Date Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/date_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Get "now" time
+ *
+ * Returns time() or its GMT equivalent based on the config file preference
+ *
+ * @access	public
+ * @return	integer
+ */	
+function now()
+{
+	$obj =& get_instance();
+	
+	if (strtolower($obj->config->item('time_reference')) == 'gmt') 
+	{
+		$now = time(); 
+		$system_time = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));   
+	
+		if (strlen($system_time) < 10)
+		{
+			$system_time = time();
+			log_message('error', 'The Date class could not set a proper GMT timestamp so the local time() value was used.');
+		}
+	
+		return $system_time;
+	}
+	else
+	{
+		return time();
+	}
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Convert MySQL Style Datecodes
+ *
+ * This function is identical to PHPs date() function,
+ * except that it allows date codes to be formatted using
+ * the MySQL style, where each code letter is preceded
+ * with a percent sign:  %Y %m %d etc...
+ *
+ * The benefit of doing dates this way is that you don't
+ * have to worry about escaping your text letters that
+ * match the date codes.
+ *
+ * @access	public
+ * @param	string
+ * @param	integer
+ * @return	integer
+ */	
+function mdate($datestr = '', $time = '')
+{
+	if ($datestr == '')
+		return '';
+	
+	if ($time == '')
+		$time = now();
+		
+	$datestr = str_replace('%\\', '', preg_replace("/([a-z]+?){1}/i", "\\\\\\1", $datestr));
+	return date($datestr, $time);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Convert MySQL Style Datecodes
+ *
+ * Returns a span of seconds in this format: 
+ *	10 days 14 hours 36 minutes 47 seconds
+ *
+ * @access	public
+ * @param	integer	a number of seconds
+ * @param	integer	Unix timestamp
+ * @return	integer
+ */	
+function timespan($seconds = 1, $time = '')
+{
+	$obj =& get_instance();
+	$obj->lang->load('date');
+
+	if ( ! is_numeric($seconds))
+	{
+		$seconds = 1;
+	}
+	
+	if ( ! is_numeric($time))
+	{
+		$time = time();
+	}
+	
+	if ($time <= $seconds)
+	{
+		$seconds = 1;
+	}
+	else
+	{
+		$seconds = $time - $seconds;
+	}
+		
+	$str = '';
+	$years = floor($seconds / 31536000);
+	
+	if ($years > 0)
+	{	
+		$str .= $years.' '.$obj->lang->line((($years	> 1) ? 'date_years' : 'date_year')).', ';
+	}	
+	
+	$seconds -= $years * 31536000;
+	$months = floor($seconds / 2628000);
+	
+	if ($years > 0 OR $months > 0)
+	{
+		if ($months > 0)
+		{	
+			$str .= $months.' '.$obj->lang->line((($months	> 1) ? 'date_months' : 'date_month')).', ';
+		}	
+	
+		$seconds -= $months * 2628000;
+	}
+
+	$weeks = floor($seconds / 604800);
+	
+	if ($years > 0 OR $months > 0 OR $weeks > 0)
+	{
+		if ($weeks > 0)
+		{	
+			$str .= $weeks.' '.$obj->lang->line((($weeks	> 1) ? 'date_weeks' : 'date_week')).', ';
+		}
+		
+		$seconds -= $weeks * 604800;
+	}			
+
+	$days = floor($seconds / 86400);
+	
+	if ($months > 0 OR $weeks > 0 OR $days > 0)
+	{
+		if ($days > 0)
+		{	
+			$str .= $days.' '.$obj->lang->line((($days	> 1) ? 'date_days' : 'date_day')).', ';
+		}
+	
+		$seconds -= $days * 86400;
+	}
+	
+	$hours = floor($seconds / 3600);
+	
+	if ($days > 0 OR $hours > 0)
+	{
+		if ($hours > 0)
+		{
+			$str .= $hours.' '.$obj->lang->line((($hours	> 1) ? 'date_hours' : 'date_hour')).', ';
+		}
+		
+		$seconds -= $hours * 3600;
+	}
+	
+	$minutes = floor($seconds / 60);
+	
+	if ($days > 0 OR $hours > 0 OR $minutes > 0)
+	{
+		if ($minutes > 0)
+		{	
+			$str .= $minutes.' '.$obj->lang->line((($minutes	> 1) ? 'date_minutes' : 'date_minutes')).', ';
+		}
+		
+		$seconds -= $minutes * 60;
+	}
+	
+	if ($str == '')
+	{
+		$str .= $seconds.' '.$obj->lang->line((($seconds	> 1) ? 'date_seconds' : 'date_second')).', ';
+	}
+			
+	return substr(trim($str), 0, -1);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Number of days in a month
+ *
+ * Takes a month/year as input and returns the number of days 
+ * for the given month/year. Takes leap years into consideration.
+ *
+ * @access	public
+ * @param	integer a numeric month
+ * @param	integer	a numeric year
+ * @return	integer
+ */	
+function days_in_month($month = 0, $year = '')
+{
+	if ($month < 1 OR $month > 12)
+	{
+		return 0;
+	}
+	
+	if ( ! ctype_digit($year) OR strlen($year) != 4)
+	{
+		$year = date('Y');
+	}
+	
+	if ($month == 2)
+	{        
+		if ($year % 400 == 0 OR ($year % 4 == 0 AND $year % 100 != 0))
+		{
+			return 29;
+		}
+	}
+
+	$days_in_month	= array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+	return $days_in_month[$month - 1];
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Converts a local Unix timestamp to GMT
+ *
+ * @access	public
+ * @param	integer Unix timestamp
+ * @return	integer
+ */	
+function local_to_gmt($time = '')
+{
+	if ($time == '')
+		$time = time();
+	
+	return mktime( gmdate("H", $time), gmdate("i", $time), gmdate("s", $time), gmdate("m", $time), gmdate("d", $time), gmdate("Y", $time));   
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Converts GMT time to a localized value
+ *
+ * Takes a Unix timestamp (in GMT) as input, and returns
+ * at the local value based on the timezone and DST setting
+ * submitted
+ *
+ * @access	public
+ * @param	integer Unix timestamp
+ * @param	string	timezone
+ * @param	bool	whether DST is active
+ * @return	integer
+ */	
+function gmt_to_local($time = '', $timezone = 'UTC', $dst = FALSE)
+{			
+	if ($time == '')
+	{
+		return now();
+	}
+	
+	$time += timezones($timezone) * 3600;
+
+	if ($dst == TRUE)
+	{
+		$time += 3600;
+	}
+	
+	return $time;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Converts a MySQL Timestamp to Unix
+ *
+ * @access	public
+ * @param	integer Unix timestamp
+ * @return	integer
+ */	
+function mysql_to_unix($time = '')
+{    
+	// We'll remove certain characters for backward compatibility
+	// since the formatting changed with MySQL 4.1
+	// YYYY-MM-DD HH:MM:SS
+	
+	$time = str_replace('-', '', $time);
+	$time = str_replace(':', '', $time);
+	$time = str_replace(' ', '', $time);
+	
+	// YYYYMMDDHHMMSS
+	return  mktime( 
+					substr($time, 8, 2),
+					substr($time, 10, 2),
+					substr($time, 12, 2),
+					substr($time, 4, 2),
+					substr($time, 6, 2),
+					substr($time, 0, 4)
+					);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Unix to "Human"
+ *
+ * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM
+ *
+ * @access	public
+ * @param	integer Unix timestamp
+ * @param	bool	whether to show seconds
+ * @param	string	format: us or euro
+ * @return	string
+ */	
+function unix_to_human($time = '', $seconds = FALSE, $fmt = 'us')
+{
+	$r  = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' ';
+		
+	if ($fmt == 'us')
+	{
+		$r .= date('h', $time).':'.date('i', $time);
+	}
+	else
+	{
+		$r .= date('H', $time).':'.date('i', $time);
+	}
+	
+	if ($seconds)
+	{
+		$r .= ':'.date('s', $time);
+	}
+	
+	if ($fmt == 'us')
+	{
+		$r .= ' '.date('A', $time);
+	}
+		
+	return $r;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Convert "human" date to GMT
+ *
+ * Reverses the above process
+ *
+ * @access	public
+ * @param	string	format: us or euro
+ * @return	integer
+ */	
+function human_to_unix($datestr = '')
+{
+	if ($datestr == '')
+	{
+		return FALSE;
+	}
+	
+	$datestr = trim($datestr);
+	$datestr = preg_replace("/\040+/", "\040", $datestr);
+
+	if ( ! ereg("^[0-9]{2,4}\-[0-9]{1,2}\-[0-9]{1,2}\040[0-9]{1,2}:[0-9]{1,2}.*$", $datestr))
+	{
+		return FALSE;
+	}
+
+	$split = preg_split("/\040/", $datestr);
+
+	$ex = explode("-", $split['0']);            
+	
+	$year  = (strlen($ex['0']) == 2) ? '20'.$ex['0'] : $ex['0'];
+	$month = (strlen($ex['1']) == 1) ? '0'.$ex['1']  : $ex['1'];
+	$day   = (strlen($ex['2']) == 1) ? '0'.$ex['2']  : $ex['2'];
+
+	$ex = explode(":", $split['1']); 
+	
+	$hour = (strlen($ex['0']) == 1) ? '0'.$ex['0'] : $ex['0'];
+	$min  = (strlen($ex['1']) == 1) ? '0'.$ex['1'] : $ex['1'];
+
+	if (isset($ex['2']) AND ereg("[0-9]{1,2}", $ex['2']))
+	{
+		$sec  = (strlen($ex['2']) == 1) ? '0'.$ex['2'] : $ex['2'];
+	}
+	else
+	{
+		// Unless specified, seconds get set to zero.
+		$sec = '00';
+	}
+	
+	if (isset($split['2']))
+	{
+		$ampm = strtolower($split['2']);
+		
+		if (substr($ampm, 0, 1) == 'p' AND $hour < 12)
+			$hour = $hour + 12;
+			
+		if (substr($ampm, 0, 1) == 'a' AND $hour == 12)
+			$hour =  '00';
+			
+		if (strlen($hour) == 1)
+			$hour = '0'.$hour;
+	}
+			
+	return mktime($hour, $min, $sec, $month, $day, $year);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Timezone Menu
+ *
+ * Generates a drop-down menu of timezones.
+ *
+ * @access	public
+ * @param	string	timezone
+ * @param	string	classname
+ * @param	string	menu name
+ * @return	string
+ */	
+function timezone_menu($default = 'UTC', $class = "", $name = 'timezones')
+{
+	$obj =& get_instance();
+	$obj->lang->load('date');
+	
+	if ($default == 'GMT')
+		$default = 'UTC';
+
+	$menu = '<select name="'.$name.'"';
+	
+	if ($class != '')
+	{
+		$menu .= ' class="'.$class.'"';
+	}
+	
+	$menu .= ">\n";
+	
+	foreach (timezones() as $key => $val)
+	{
+		$selected = ($default == $key) ? " selected='selected'" : '';
+		$menu .= "<option value='{$key}'{$selected}>".$obj->lang->line($key)."</option>\n";
+	}
+
+	$menu .= "</select>";
+
+	return $menu;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Timezones
+ *
+ * Returns an array of timezones.  This is a helper function
+ * for varios other ones in this library
+ *
+ * @access	public
+ * @param	string	timezone
+ * @return	string
+ */	
+function timezones($tz = '')
+{
+	// Note: Don't change the order of these even though 
+	// some items appear to be in the wrong order
+		
+	$zones = array( 
+					'UM12' => -12,
+					'UM11' => -11,
+					'UM10' => -10,
+					'UM9'  => -9,
+					'UM8'  => -8,
+					'UM7'  => -7,
+					'UM6'  => -6,
+					'UM5'  => -5,
+					'UM4'  => -4,
+					'UM25' => -2.5,
+					'UM3'  => -3,
+					'UM2'  => -2,
+					'UM1'  => -1,
+					'UTC'  => 0,
+					'UP1'  => +1,
+					'UP2'  => +2,
+					'UP3'  => +3,
+					'UP25' => +2.5,
+					'UP4'  => +4,
+					'UP35' => +3.5,
+					'UP5'  => +5,
+					'UP45' => +4.5,
+					'UP6'  => +6,
+					'UP7'  => +7,
+					'UP8'  => +8,
+					'UP9'  => +9,
+					'UP85' => +8.5,
+					'UP10' => +10,
+					'UP11' => +11,
+					'UP12' => +12                    
+				);
+				
+	if ($tz == '')
+	{
+		return $zones;
+	}
+	
+	if ($tz == 'GMT')
+		$tz = 'UTC';
+	
+	return ( ! isset($zones[$tz])) ? 0 : $zones[$tz];
+}
+
+
+?>
\ No newline at end of file
diff --git a/system/helpers/directory_helper.php b/system/helpers/directory_helper.php
new file mode 100644
index 0000000..69eb13d
--- /dev/null
+++ b/system/helpers/directory_helper.php
@@ -0,0 +1,69 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Directory Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/directory_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Create a Direcotry Map
+ *
+ * Reads the specified directory and builds an array
+ * representation of it.  Sub-folders contained with the
+ * directory will be mapped as well.
+ *
+ * @access	public
+ * @param	string	path to source
+ * @param	bool	whether to limit the result to the top level only
+ * @return	array
+ */	
+function directory_map($source_dir, $top_level_only = FALSE)
+{
+	if ( ! isset($filedata))
+		$filedata = array();
+	
+	if ($fp = @opendir($source_dir))
+	{ 
+		while (FALSE !== ($file = readdir($fp)))
+		{
+			if (@is_dir($source_dir.$file) && substr($file, 0, 1) != '.' AND $top_level_only == FALSE) 
+			{       
+				$temp_array = array();
+				 
+				$temp_array = directory_map($source_dir.$file."/");   
+				
+				$filedata[$file] = $temp_array;
+			}
+			elseif (substr($file, 0, 1) != ".")
+			{
+				$filedata[] = $file;
+			}
+		}         
+		return $filedata;        
+	} 
+}
+
+
+?>
\ No newline at end of file
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
new file mode 100644
index 0000000..93bddb0
--- /dev/null
+++ b/system/helpers/file_helper.php
@@ -0,0 +1,139 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter File Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/file_helpers.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Read File
+ *
+ * Opens the file specfied in the path and returns it as a string.
+ *
+ * @access	public
+ * @param	string	path to file
+ * @return	string
+ */	
+function read_file($file)
+{
+	if ( ! file_exists($file))
+	{
+		return FALSE;
+	}
+
+	if ( ! $fp = @fopen($file, 'rb'))
+	{
+		return FALSE;
+	}
+		
+	flock($fp, LOCK_SH);
+	
+	$data = '';
+	if (filesize($file) > 0) 
+	{
+		$data = fread($fp, filesize($file)); 
+	}
+
+	flock($fp, LOCK_UN);
+	fclose($fp); 
+
+	return $data;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Write File
+ *
+ * Writes data to the file specified in the path. 
+ * Creats a new file if non-existant.
+ *
+ * @access	public
+ * @param	string	path to file
+ * @param	string	file data
+ * @return	bool
+ */	
+function write_file($path, $data)
+{
+	if ( ! $fp = @fopen($path, 'wb'))
+	{
+		return FALSE;
+	}
+		
+	flock($fp, LOCK_EX);
+	fwrite($fp, $data);
+	flock($fp, LOCK_UN);
+	fclose($fp);	
+
+	return TRUE;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Delete Files
+ *
+ * Deletes all files contained in the supplied directory path.
+ * Files must be writable or owned by the system in order to be deleted.
+ * If the second parameter is set to TRUE, any direcotries contained
+ * within the supplied base directory will be nuked as well.
+ *
+ * @access	public
+ * @param	string	path to file
+ * @param	bool	whether to delete any directories found in the path
+ * @return	bool
+ */	
+function delete_files($path, $del_dir = FALSE)
+{	
+	// Trim the trailing slahs
+	$path = preg_replace("|^(.+?)/*$|", "\\1", $path);
+			
+	if ( ! $current_dir = @opendir($path))
+		return;
+	
+	while(FALSE !== ($filename = @readdir($current_dir)))
+	{ 
+		if ($filename != "." and $filename != "..")
+		{
+			if (is_dir($path.'/'.$filename))
+			{
+				delete_files($path.'/'.$filename, $del_dir);
+			}
+			else
+			{
+				unlink($path.'/'.$filename);
+			}
+		}
+	}
+	@closedir($current_dir);
+	
+	if ($del_dir == TRUE)
+	{
+		@rmdir($path);
+	}
+}
+
+
+?>
\ No newline at end of file
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
new file mode 100644
index 0000000..f82ad01
--- /dev/null
+++ b/system/helpers/form_helper.php
@@ -0,0 +1,382 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Form Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/form_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Form Declaration
+ *
+ * Creates the opening portion of the form.
+ *
+ * @access	public
+ * @param	string	the URI segments of the form destination
+ * @param	array	a key/value pair of attributes
+ * @param	array	a key/value pair hidden data
+ * @return	string
+ */	
+function form_open($action, $attributes = array(), $hidden = array())
+{
+	$obj =& get_instance();
+
+	$form = '<form method="post" action="'.$obj->config->site_url($action).'"';
+	
+	if (is_array($attributes) AND count($attributes) > 0)
+	{
+		foreach ($attributes as $key => $val)
+		{
+			$form .= ' '.$key.'="'.$val.'"';  
+		}
+	}
+	
+	$form .= '>';
+
+	if (is_array($hidden) AND count($hidden > 0))
+	{
+		$form .= form_hidden($hidden);
+	}
+	
+	return $form;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Form Declaration - Multipart type
+ *
+ * Creates the opening portion of the form, but with "multipart/form-data".
+ *
+ * @access	public
+ * @param	string	the URI segments of the form destination
+ * @param	array	a key/value pair of attributes
+ * @param	array	a key/value pair hidden data
+ * @return	string
+ */	
+function form_open_multipart($action, $attributes = array(), $hidden = array())
+{
+	$attributes['enctype'] = 'multipart/form-data';
+	return form_open($action, $attributes, $hidden);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Hidden Input Field
+ *
+ * Generates hidden fields.  You can pass a simple key/value string or an associative
+ * array with multiple values.
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @return	string
+ */	
+function form_hidden($name, $value = '')
+{        
+	if ( ! is_array($name))
+	{
+		return '<input type="hidden" name="'.$name.'" value="'.form_prep($value).'" />';
+	}
+
+	$form = '';
+	foreach ($name as $name => $value)
+	{
+		$form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value).'" />';
+	}
+	
+	return $form;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Text Input Field
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	string
+ * @return	string
+ */	
+function form_input($data = '', $value = '', $extra = '')
+{
+	$defaults = array('type' => 'text', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value, 'maxlength' => '500', 'size' => '50');
+
+	return "<input ".parse_form_attributes($data, $defaults).$extra." />\n";
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Password Field
+ *
+ * Identical to the input function but adds the "password" type
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	string
+ * @return	string
+ */	
+function form_password($data = '', $value = '', $extra = '')
+{
+	if ( ! is_array($data))
+	{
+		$data = array('name' => $data);
+	}
+
+	$data['type'] = 'password';
+	return form_input($data, $value, $extra);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Upload Field
+ *
+ * Identical to the input function but adds the "file" type
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	string
+ * @return	string
+ */	
+function form_upload($data = '', $value = '', $extra = '')
+{
+	if ( ! is_array($data))
+	{
+		$data = array('name' => $data);
+	}
+
+	$data['type'] = 'file';
+	return form_input($data, $value, $extra);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Textarea field
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	string
+ * @return	string
+ */	
+function form_textarea($data = '', $value = '', $extra = '')
+{
+	$defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '90', 'rows' => '12');
+	
+	$val = (( ! is_array($data) OR ! isset($data['value'])) ? $value : $data['value']);
+		
+	return "<textarea ".parse_form_attributes($data, $defaults).$extra.">".$val."</textarea>\n";
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Dropdown Menu
+ *
+ * @access	public
+ * @param	string
+ * @param	array
+ * @param	string
+ * @param	string
+ * @return	string
+ */	
+function form_dropdown($name = '', $options = array(), $selected = '', $extra = '')
+{
+	if ($extra != '') $extra = ' '.$extra;
+		
+	$form = '<select name="'.$name.'"'.$extra.">\n";
+	
+	foreach ($options as $key => $val)
+	{
+		$sel = ($selected != $key) ? '' : ' selected="selected"';
+		
+		$form .= '<option value="'.$key.'"'.$sel.'>'.$val."</option>\n";
+	}
+
+	$form .= '</select>';
+	
+	return $form;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Checkbox Field
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	bool
+ * @param	string
+ * @return	string
+ */	
+function form_checkbox($data = '', $value = '', $checked = TRUE, $extra = '')
+{
+	$defaults = array('type' => 'checkbox', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value);
+	
+	if (isset($data['checked']))
+	{
+		$checked = $data['checked'];
+		
+		if ($checked == FALSE) 
+			unset($data['checked']);
+	}
+	
+	if ($checked == TRUE)
+		$defaults['checked'] = ' checked="checked"';
+	else
+		unset($defaults['checked']);
+
+	return "<input ".parse_form_attributes($data, $defaults).$extra." />\n";
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Radio Button
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	bool
+ * @param	string
+ * @return	string
+ */	
+function form_radio($data = '', $value = '', $checked = TRUE, $extra = '')
+{
+	if ( ! is_array($data))
+	{	
+		$data = array('name' => $data);
+	}
+
+	$data['type'] = 'radio';
+	return form_checkbox($data, $value, $checked, $extra);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Submit Button
+ *
+ * @access	public
+ * @param	mixed
+ * @param	string
+ * @param	string
+ * @return	string
+ */	
+function form_submit($data = '', $value = '', $extra = '')
+{
+	$defaults = array('type' => 'submit', 'name' => (( ! is_array($data)) ? $data : ''), 'value' => $value);
+
+	return "<input ".parse_form_attributes($data, $defaults).$extra." />\n";
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Form Close Tag
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function form_close($extra = '')
+{
+	return "</form>\n".$extra;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Form Prep
+ *
+ * Formats text so that it can be safely placed in a form field in the event it has HTML tags.
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function form_prep($str = '')
+{
+	if ($str == '')
+	{
+		return '';
+	}
+	
+	return str_replace(array("'", '"'), array("&#39;", "&quot;"), htmlspecialchars($str));	
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Parse the form attributes
+ *
+ * Helper function used by some of the form helpers
+ *
+ * @access	private
+ * @param	array
+ * @parm	array
+ * @return	string
+ */	
+function parse_form_attributes($attributes, $default)
+{
+	if (is_array($attributes))
+	{
+		foreach ($default as $key => $val)
+		{
+			if (isset($attributes[$key]))
+			{
+				$default[$key] = $attributes[$key];
+				unset($attributes[$key]);
+			}
+		}
+		
+		if (count($attributes) > 0)
+		{	
+			$default = array_merge($default, $attributes);
+		}
+	}
+	
+	$att = '';
+	foreach ($default as $key => $val)
+	{
+		if ($key == 'value')
+		{
+			$val = form_prep($val);
+		}
+	
+		$att .= $key . '="' . $val . '" ';
+	}
+
+	return $att;
+}
+
+?>
\ No newline at end of file
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
new file mode 100644
index 0000000..1c97dda
--- /dev/null
+++ b/system/helpers/html_helper.php
@@ -0,0 +1,76 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter HTML Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.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
+ */	
+function heading($data = '', $h = '1')
+{
+	return "<h".$h.">".$data."</h".$h.">";
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Generates HTML BR tags based on number supplied
+ *
+ * @access	public
+ * @param	integer
+ * @return	string
+ */	
+function br($num = 1)
+{
+	return str_repeat("<br />", $num);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Generates non-breaking space entities based on number supplied
+ *
+ * @access	public
+ * @param	integer
+ * @return	string
+ */	
+function nbs($num = 1)
+{
+	return str_repeat("&nbsp;", $num);
+}
+
+
+
+?>
\ No newline at end of file
diff --git a/system/helpers/index.html b/system/helpers/index.html
new file mode 100644
index 0000000..5a1f5d6
--- /dev/null
+++ b/system/helpers/index.html
@@ -0,0 +1,15 @@
+<html>

+

+<head>

+

+<title>403 Forbidden</title>

+

+</head>

+

+<body bgcolor='#ffffff'>

+

+<p>Directory access is forbidden.<p>

+

+</body>

+

+</html>
\ No newline at end of file
diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php
new file mode 100644
index 0000000..918e4ae
--- /dev/null
+++ b/system/helpers/security_helper.php
@@ -0,0 +1,112 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Security Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/security_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * XSS Filtering
+ *
+ * @access	public
+ * @parm	string
+ * @parm	string	the character set of your data
+ * @return	string
+ */	
+function xss_clean($str, $charset = 'ISO-8859-1')
+{
+	$obj =& get_instance();
+	return $obj->input->xss_clean($str, $charset);
+}
+
+// --------------------------------------------------------------------
+
+/**
+ * Hash encode a string
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */		
+function hash($str, $type = 'sha1')
+{
+	if ($type == 'sha1')
+	{
+		if ( ! function_exists('sha1'))
+		{
+			if ( ! function_exists('mhash'))
+			{	
+				require_once(BASEPATH.'libraries/Sha1'.EXT);
+				$SH = new CI_SHA;
+				return $SH->generate($str);            
+			}
+			else
+			{
+				return bin2hex(mhash(MHASH_SHA1, $str));
+			}
+		}
+		else
+		{
+			return sha1($str);
+		}	
+	}
+	else
+	{
+		return md5($str);
+	}
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Strip Image Tags
+ *
+ * @access	public
+ * @parm	string
+ * @return	string
+ */	
+function strip_image_tags($str)
+{    
+	$str = preg_replace("#<img\s+.*?src\s*=\s*[\"'](.+?)[\"'].*?\>#", "\\1", $str);
+	$str = preg_replace("#<img\s+.*?src\s*=\s*(.+?).*?\>#", "\\1", $str);
+			
+	return $str;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Convert PHP tags to entities
+ *
+ * @access	public
+ * @parm	string
+ * @return	string
+ */	
+function encode_php_tags($str)
+{
+	return str_replace(array('<?php', '<?PHP', '<?', '?>'),  array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
+}
+
+?>
\ No newline at end of file
diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php
new file mode 100644
index 0000000..d5a3591
--- /dev/null
+++ b/system/helpers/string_helper.php
@@ -0,0 +1,154 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter String Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/string_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Trim Slashes
+ *
+ * Removes any leading/traling slashes from a string:
+ *
+ * /this/that/theother/
+ *
+ * becomes:
+ *
+ * this/that/theother
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function trim_slashes($str)
+{
+	return preg_replace("|^/*(.+?)/*$|", "\\1", $str);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Reduce Double Slashes
+ *
+ * Converts double slashes in a string to a single slash,
+ * except those found in http://
+ *
+ * http://www.some-site.com//index.php
+ *
+ * becomes:
+ *
+ * http://www.some-site.com/index.php
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function reduce_double_slashes($str)
+{
+	return preg_replace("#([^:])//+#", "\\1/", $str);  
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Create a Random String
+ *
+ * Useful for generating passwords or hashes.
+ *
+ * @access	public
+ * @param	string 	type of random string.  Options: alunum, numeric, nozero, unique
+ * @param	integer	number of characters
+ * @return	string
+ */	
+function random_string($type = 'alnum', $len = 8)
+{					
+	switch($type)
+	{
+		case 'alnum'	:
+		case 'numeric'	:
+		case 'nozero'	:
+		
+				switch ($type)
+				{
+					case 'alnum'	:	$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+						break;
+					case 'numeric'	:	$pool = '0123456789';
+						break;
+					case 'nozero'	:	$pool = '123456789';
+						break;
+				}
+
+				$str = '';
+				for ($i=0; $i < $len; $i++) 
+				{    
+					$str .= substr($pool, mt_rand(0, strlen($pool) -1), 1); 
+				}
+				return $str;      
+		  break;
+		case 'unique' : return md5(uniqid(mt_rand())); 
+		  break; 
+	}        
+}
+// ------------------------------------------------------------------------
+
+/**
+ * Alternator
+ *
+ * Allows strings to be alternated.  See docs...
+ *
+ * @access	public
+ * @param	string (as many parameters as needed)
+ * @return	string
+ */		
+function alternator()
+{
+	static $i;	
+
+	if (func_num_args() == 0)
+	{
+		$i = 0;
+		return '';
+	}
+	$args = func_get_args();
+	return $args[($i++ % count($args))];
+}
+
+// ------------------------------------------------------------------------
+
+/**
+ * Repeater function
+ *
+ * @access	public
+ * @param	string
+ * @param	integer	number of repeats
+ * @return	string
+ */	
+function repeater($data, $num = 1)
+{
+	return str_repeat($data, $num);
+}
+
+
+?>
\ No newline at end of file
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
new file mode 100644
index 0000000..15b5573
--- /dev/null
+++ b/system/helpers/text_helper.php
@@ -0,0 +1,386 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Text Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/text_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Word Limiter
+ *
+ * Limits a string to X number of words.
+ *
+ * @access	public
+ * @param	string
+ * @param	integer
+ * @param	string	the end character. Usually an ellipsis 
+ * @return	string
+ */	
+function word_limiter($str, $n = 100, $end_char = '&#8230;')
+{
+	if (strlen($str) < $n) 
+	{
+		return $str;
+	}
+	
+	$words = explode(' ', preg_replace("/\s+/", ' ', preg_replace("/(\r\n|\r|\n)/", " ", $str)));
+	
+	if (count($words) <= $n)
+	{
+		return $str;
+	}
+			
+	$str = '';
+	for ($i = 0; $i < $n; $i++) 
+	{
+		$str .= $words[$i].' ';
+	}
+
+	return trim($str).$end_char; 
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Character Limiter
+ *
+ * Limits the string based on the character count.  Preserves complete words
+ * so the character count may not be exactly as specified.
+ *
+ * @access	public
+ * @param	string
+ * @param	integer
+ * @param	string	the end character. Usually an ellipsis 
+ * @return	string
+ */	
+function character_limiter($str, $n = 500, $end_char = '&#8230;')
+{
+	if (strlen($str) < $n) 
+	{
+		return $str;
+	}
+		
+	$str = preg_replace("/\s+/", ' ', preg_replace("/(\r\n|\r|\n)/", " ", $str));
+
+	if (strlen($str) <= $n)
+	{
+		return $str;
+	}
+									
+	$out = "";
+	foreach (explode(' ', trim($str)) as $val)
+	{
+		$out .= $val.' ';			
+		if (strlen($out) >= $n)
+		{
+			return trim($out).$end_char; 
+		}		
+	}
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * High ASCII to Entities
+ *
+ * Converts High ascii text and MS Word special characters to character entities
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function ascii_to_entities($str)
+{
+   $count	= 1;
+   $out	= '';
+   $temp	= array();
+	   
+   for ($i = 0, $s = strlen($str); $i < $s; $i++)
+   {
+	   $ordinal = ord($str[$i]);
+	   
+	   if ($ordinal < 128)
+	   {
+		   $out .= $str[$i];            
+	   }
+	   else
+	   {
+		   if (count($temp) == 0)
+		   {
+			   $count = ($ordinal < 224) ? 2 : 3;
+		   }
+		   
+		   $temp[] = $ordinal;
+		   
+		   if (count($temp) == $count)
+		   {
+			   $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64);
+
+			   $out .= '&#'.$number.';';
+			   $count = 1;
+			   $temp = array();
+		   }   
+	   }   
+   }
+   
+   return $out;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Entities to ASCII
+ *
+ * Converts character entities back to ASCII
+ *
+ * @access	public
+ * @param	string
+ * @param	bool
+ * @return	string
+ */	
+function entities_to_ascii($str, $all = TRUE)
+{
+   if (preg_match_all('/\&#(\d+)\;/', $str, $matches))
+   {
+	   for ($i = 0, $s = count($matches['0']); $i < $s; $i++)
+	   {				
+		   $digits = $matches['1'][$i];
+
+		   $out = '';
+   
+		   if ($digits < 128)
+		   {
+			   $out .= chr($digits);
+		   
+		   } 
+		   elseif ($digits < 2048)
+		   {
+			   $out .= chr(192 + (($digits - ($digits % 64)) / 64));
+			   $out .= chr(128 + ($digits % 64));
+		   } 
+		   else
+		   {
+			   $out .= chr(224 + (($digits - ($digits % 4096)) / 4096));
+			   $out .= chr(128 + ((($digits % 4096) - ($digits % 64)) / 64));
+			   $out .= chr(128 + ($digits % 64));
+		   }
+   
+		   $str = str_replace($matches['0'][$i], $out, $str);				
+	   }
+   }
+   
+   if ($all)
+   {
+	   $str = str_replace(array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;", "&#45;"),
+						  array("&","<",">","\"", "'", "-"),
+						  $str);
+   }
+   
+   return $str;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Word Censoring Function
+ *
+ * Supply a string and an array of disallowed words and any
+ * matched words will be converted to #### or to the replacement
+ * word you've submitted.
+ *
+ * @access	public
+ * @param	string	the text string
+ * @param	string	the array of censoered words
+ * @param	string	the optional replacement value
+ * @return	string
+ */	
+function word_censor($str, $censored, $replacement = '')
+{
+	if ( ! is_array($censored))
+	{
+		return $str;
+	}
+
+	$str = ' '.$str.' ';
+	foreach ($censored as $badword)
+	{
+		if ($replacement != '')
+		{
+			$str = preg_replace("/\b(".str_replace('\*', '\w*?', preg_quote($badword)).")\b/i", $replacement, $str);
+		}
+		else
+		{
+			$str = preg_replace("/\b(".str_replace('\*', '\w*?', preg_quote($badword)).")\b/ie", "str_repeat('#', strlen('\\1'))", $str);
+		}
+	}
+	
+	return trim($str);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Code Highlighter
+ *
+ * Colorizes code strings
+ *
+ * @access	public
+ * @param	string	the text string
+ * @return	string
+ */	
+function highlight_code($str)
+{		
+	// The highlight string function encodes and highlights 
+	// brackets so we need them to start raw 
+	$str = str_replace(array('&lt;', '&gt;'), array('<', '>'), $str);
+	
+	// Replace any existing PHP tags to temporary markers so they don't accidentally
+	// break the string out of PHP, and thus, thwart the highlighting.
+	
+	$str = str_replace(array('&lt;?php', '?&gt;',  '\\'), array('phptagopen', 'phptagclose', 'backslashtmp'), $str);
+		
+	// The highlight_string function requires that the text be surrounded
+	// by PHP tags.  Since we don't know if A) the submitted text has PHP tags,
+	// or B) whether the PHP tags enclose the entire string, we will add our
+	// own PHP tags around the string along with some markers to make replacement easier later
+	
+	$str = '<?php //tempstart'."\n".$str.'//tempend ?>'; // <?
+	
+	// All the magic happens here, baby!
+	$str = highlight_string($str, TRUE);
+
+	// Prior to PHP 5, the highlight function used icky font tags
+	// so we'll replace them with span tags.	
+	if (abs(phpversion()) < 5)
+	{
+		$str = str_replace(array('<font ', '</font>'), array('<span ', '</span>'), $str);
+		$str = preg_replace('#color="(.*?)"#', 'style="color: \\1"', $str);
+	}
+	
+	// Remove our artificially added PHP
+	$str = preg_replace("#\<code\>.+?//tempstart\<br />\</span\>#is", "<code>\n", $str);
+	$str = preg_replace("#\<code\>.+?//tempstart\<br />#is", "<code>\n", $str);
+	$str = preg_replace("#//tempend.+#is", "</span>\n</code>", $str);
+	
+	// Replace our markers back to PHP tags.
+	$str = str_replace(array('phptagopen', 'phptagclose', 'backslashtmp'), array('&lt;?php', '?&gt;', '\\'), $str); //<?
+				
+	return $str;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Phrase Highlighter
+ *
+ * Highlights a phrase within a text string
+ *
+ * @access	public
+ * @param	string	the text string
+ * @param	string	the phrase you'd like to highlight
+ * @param	string	the openging tag to precede the phrase with
+ * @param	string	the closing tag to end the phrase with
+ * @return	string
+ */	
+function highlight_phrase($str, $phrase, $tag_open = '<strong>', $tag_close = '</strong>')
+{
+	if ($str == '')
+	{
+		return '';
+	}
+	
+	if ($phrase != '')
+	{
+		return preg_replace('/('.preg_quote($phrase).')/i', $tag_open."\\1".$tag_close, $str);
+	}
+
+	return $str;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Word Wrap
+ *
+ * Wraps text at the specified character.  Maintains the integrity of words.
+ *
+ * @access	public
+ * @param	string	the text string
+ * @param	integer	the number of characters to wrap at
+ * @return	string
+ */	
+function word_wrap($str, $chars = '76')
+{	
+	if ( ! ctype_digit($chars))
+		$chars = 76;
+	
+	$str = preg_replace("/(\r\n|\r|\n)/", "\n", $str);
+	$lines = split("\n", $str);
+	
+	$output = "";
+	while (list(, $thisline) = each($lines)) 
+	{
+		if (strlen($thisline) > $chars)
+		{
+			$line = "";
+			$words = split(" ", $thisline);
+			while(list(, $thisword) = each($words)) 
+			{
+				while((strlen($thisword)) > $chars) 
+				{
+					$cur_pos = 0;
+					for($i=0; $i < $chars - 1; $i++)
+					{
+						$output .= $thisword[$i];
+						$cur_pos++;
+					}
+					
+					$output .= "\n";
+					$thisword = substr($thisword, $cur_pos, (strlen($thisword) - $cur_pos));
+				}
+				
+				if ((strlen($line) + strlen($thisword)) > $chars) 
+				{
+					$output .= $line."\n";
+					$line = $thisword." ";
+				} 
+				else 
+				{
+					$line .= $thisword." ";
+				}
+			}
+
+			$output .= $line."\n";
+		} 
+		else 
+		{
+			$output .= $thisline."\n";
+		}
+	}
+
+	return $output;	
+}
+
+?>
\ No newline at end of file
diff --git a/system/helpers/typography_helper.php b/system/helpers/typography_helper.php
new file mode 100644
index 0000000..6a54952
--- /dev/null
+++ b/system/helpers/typography_helper.php
@@ -0,0 +1,490 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter Typography Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/typography_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * 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;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Auto Typography Wrapper Function
+ * 
+ *
+ * @access	public
+ * @parm	string
+ * @return	string
+ */
+function auto_typography($str)
+{
+	$TYPE = new Auto_typography();
+	return $TYPE->convert($str);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Auto Typography Class
+ * 
+ *
+ * @access		private
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @author		Paul Burdick
+ * @link		http://www.codeigniter.com/user_guide/helpers/
+ */
+class Auto_typography {
+
+	// Block level elements that should not be wrapped inside <p> tags
+	var $block_elements = 'div|blockquote|pre|code|h\d|script|ol|un';
+	
+	// Elements that should not have <p> and <br /> tags within them.
+	var $skip_elements	= 'pre|ol|ul';
+	
+	// Tags we want the parser to completely ignore when splitting the string.
+	var $ignore_elements = 'a|b|i|em|strong|span|img|li';	
+
+
+	/**
+	 * Main Processing Function
+	 *
+	 */
+	function convert($str)
+	{
+		if ($str == '')
+		{
+			return '';
+		}
+		
+		$str = ' '.$str.' ';
+		
+		// Standardize Newlines to make matching easier
+		$str = preg_replace("/(\r\n|\r)/", "\n", $str);
+		
+		/*
+		 * Reduce line breaks
+		 *
+		 * If there are more than two consecutive line 
+		 * breaks we'll compress them down to a maximum
+		 * of two since there's no benefit to more.
+		 *
+		 */
+		$str = preg_replace("/\n\n+/", "\n\n", $str);
+
+		/*
+		 * Convert quotes within tags to tempoarary marker
+		 *
+		 * We don't want quotes converted within 
+		 * tags so we'll temporarily convert them to 
+		 * {{{DQ}}} and {{{SQ}}}
+		 *
+		 */			
+		if (preg_match_all("#\<.+?>#si", $str, $matches))
+		{
+			for ($i = 0; $i < count($matches['0']); $i++)
+			{
+				$str = str_replace($matches['0'][$i], 
+									str_replace(array("'",'"'), array('{{{SQ}}}', '{{{DQ}}}'), $matches['0'][$i]),
+									$str);
+			}
+		}
+		
+		/*
+		 * Convert "ignore" tags to tempoarary 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 < temporarily to: {{{tag}}}
+		 *
+		 */			
+		$str = preg_replace("#<(/*)(".$this->ignore_elements.")#i", "{{{tag}}}\\1\\2", $str);	
+		
+		/*
+		 * Split the string at every tag
+		 *
+		 * This creates an array with this prototype:
+		 *
+		 *	[array]
+		 *	{
+		 *		[0] = <opening tag>
+		 *		[1] = Content contained between the tags
+		 *		[2] = <closing tag>
+		 *		Etc...
+		 *	}
+		 *
+		 */			
+		$chunks = preg_split('/(<(?:[^<>]+(?:"[^"]*"|\'[^\']*\')?)+>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
+		
+		/*
+		 * Build our finalized string
+		 *
+		 * We'll cycle through the array, skipping tags,
+		 * and processing the contained text
+		 *
+		 */			
+		$str = '';
+		$process = TRUE;
+		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;
+			}
+		
+			if ($process == FALSE)
+			{
+				$str .= $chunk;
+				continue;
+			}
+			
+			//  Convert Newlines into <p> and <br /> tags
+			$str .= $this->format_newlines($chunk);
+		}
+
+		// Convert Quotes and other characters
+		$str = $this->format_characters($str);
+
+		//  We'll swap our temporary markers back and do some clean up.
+		$str = preg_replace('#(<p>\n*</p>)#', '', $str);
+		$str = preg_replace('#(<p.*?>)<p>#', "\\1", $str);
+		
+		$str = str_replace(
+							array('</p></p>', '</p><p>', '{{{tag}}}', '{{{DQ}}}', '{{{SQ}}}'), 
+							array('</p>', '<p>', '<', '"', "'"), 
+							$str
+							);
+		
+		return trim($str);
+	}
+	
+	// --------------------------------------------------------------------
+
+	/**
+	 * Format Characters
+	 *
+	 * This function mainly converts double and single quotes
+	 * to entities, but since these are directional, it does
+	 * it based on some rules.  It also converts em-dashes
+	 * and a couple other things.
+	 */
+	function format_characters($str)
+	{	
+		$table = array(
+						' "'		=> " &#8220;",
+						'" '		=> "&#8221; ",
+						" '"		=> " &#8216;",
+						"' "		=> "&#8217; ",
+						
+						'>"'		=> ">&#8220;",
+						'"<'		=> "&#8221;<",
+						">'"		=> ">&#8216;",
+						"'<"		=> "&#8217;<",
+
+						"\"."		=> "&#8221;.",
+						"\","		=> "&#8221;,",
+						"\";"		=> "&#8221;;",
+						"\":"		=> "&#8221;:",
+						"\"!"		=> "&#8221;!",
+						"\"?"		=> "&#8221;?",
+						
+						".  "		=> ".&nbsp; ",
+						"?  "		=> "?&nbsp; ",
+						"!  "		=> "!&nbsp; ",
+						":  "		=> ":&nbsp; ",
+					);
+
+		// These deal with quotes within quotes, like:  "'hi here'"
+		$start = 0;
+		$space = array("\n", "\t", " ");
+		
+		while(TRUE)
+		{
+			$current = strpos(substr($str, $start), "\"'");
+			
+			if ($current === FALSE) break;
+			
+			$one_before = substr($str, $start+$current-1, 1);
+			$one_after = substr($str, $start+$current+2, 1);
+			
+			if ( ! in_array($one_after, $space) && $one_after != "<")
+			{
+				$str = str_replace(	$one_before."\"'".$one_after,
+									$one_before."&#8220;&#8216;".$one_after,
+									$str);
+			}
+			elseif ( ! in_array($one_before, $space) && (in_array($one_after, $space) OR $one_after == '<'))
+			{
+				$str = str_replace(	$one_before."\"'".$one_after,
+									$one_before."&#8221;&#8217;".$one_after,
+									$str);
+			}
+			
+			$start = $start+$current+2;
+		}
+		
+		$start = 0;
+		
+		while(TRUE)
+		{
+			$current = strpos(substr($str, $start), "'\"");
+			
+			if ($current === FALSE) break;
+			
+			$one_before = substr($str, $start+$current-1, 1);
+			$one_after = substr($str, $start+$current+2, 1);
+			
+			if ( in_array($one_before, $space) && ! in_array($one_after, $space) && $one_after != "<")
+			{
+				$str = str_replace(	$one_before."'\"".$one_after,
+									$one_before."&#8216;&#8220;".$one_after,
+									$str);
+			}
+			elseif ( ! in_array($one_before, $space) && $one_before != ">")
+			{
+				$str = str_replace(	$one_before."'\"".$one_after,
+									$one_before."&#8217;&#8221;".$one_after,
+									$str);
+			}
+			
+			$start = $start+$current+2;
+		}
+		
+		// Are there quotes within a word, as in:  ("something")
+		if (preg_match_all("/(.)\"(\S+?)\"(.)/", $str, $matches))
+		{
+			for ($i=0, $s=sizeof($matches['0']); $i < $s; ++$i)
+			{
+				if ( ! in_array($matches['1'][$i], $space) && ! in_array($matches['3'][$i], $space))
+				{
+					$str = str_replace(	$matches['0'][$i],
+										$matches['1'][$i]."&#8220;".$matches['2'][$i]."&#8221;".$matches['3'][$i],
+										$str);
+				}
+			}
+		}
+		
+		if (preg_match_all("/(.)\'(\S+?)\'(.)/", $str, $matches))
+		{
+			for ($i=0, $s=sizeof($matches['0']); $i < $s; ++$i)
+			{
+				if ( ! in_array($matches['1'][$i], $space) && ! in_array($matches['3'][$i], $space))
+				{
+					$str = str_replace(	$matches['0'][$i],
+										$matches['1'][$i]."&#8216;".$matches['2'][$i]."&#8217;".$matches['3'][$i],
+										$str);
+				}
+			}
+		}
+		
+		// How about one apostrophe, as in Rick's
+		$start = 0;
+		
+		while(TRUE)
+		{
+			$current = strpos(substr($str, $start), "'");
+			
+			if ($current === FALSE) break;
+			
+			$one_before = substr($str, $start+$current-1, 1);
+			$one_after = substr($str, $start+$current+1, 1);
+			
+			if ( ! in_array($one_before, $space) && ! in_array($one_after, $space))
+			{
+				$str = str_replace(	$one_before."'".$one_after,
+									$one_before."&#8217;".$one_after,
+									$str);
+			}
+			
+			$start = $start+$current+2;
+		}
+
+		// Em-dashes
+		$start = 0;
+		while(TRUE)
+		{
+			$current = strpos(substr($str, $start), "--");
+			
+			if ($current === FALSE) break;
+			
+			$one_before = substr($str, $start+$current-1, 1);
+			$one_after = substr($str, $start+$current+2, 1);
+			$two_before = substr($str, $start+$current-2, 1);
+			$two_after = substr($str, $start+$current+3, 1);
+			
+			if (( ! in_array($one_before, $space) && ! in_array($one_after, $space))
+				OR
+				( ! in_array($two_before, $space) && ! in_array($two_after, $space) && $one_before == ' ' && $one_after == ' ')
+				)
+			{
+				$str = str_replace(	$two_before.$one_before."--".$one_after.$two_after,
+									$two_before.trim($one_before)."&#8212;".trim($one_after).$two_after,
+									$str);
+			}
+			
+			$start = $start+$current+2;
+		}
+		
+		// Ellipsis
+		$str = preg_replace("#(\w)\.\.\.(\s|<br />|</p>)#", "\\1&#8230;\\2", $str); 
+		$str = preg_replace("#(\s|<br />|</p>)\.\.\.(\w)#", "\\1&#8230;\\2", $str); 
+		
+		// Run the translation array we defined above		
+		$str = str_replace(array_keys($table), array_values($table), $str);
+		
+		// If there are any stray double quotes we'll catch them here
+		
+		$start = 0;
+		
+		while(TRUE)
+		{
+			$current = strpos(substr($str, $start), '"');
+			
+			if ($current === FALSE) break;
+			
+			$one_before = substr($str, $start+$current-1, 1);
+			$one_after = substr($str, $start+$current+1, 1);
+			
+			if ( ! in_array($one_after, $space))
+			{
+				$str = str_replace(	$one_before.'"'.$one_after,
+									$one_before."&#8220;".$one_after,
+									$str);
+			}
+			elseif( ! in_array($one_before, $space))
+			{
+				$str = str_replace(	$one_before."'".$one_after,
+									$one_before."&#8221;".$one_after,
+									$str);
+			}
+			
+			$start = $start+$current+2;
+		}
+		
+		$start = 0;
+		
+		while(TRUE)
+		{
+			$current = strpos(substr($str, $start), "'");
+			
+			if ($current === FALSE) break;
+			
+			$one_before = substr($str, $start+$current-1, 1);
+			$one_after = substr($str, $start+$current+1, 1);
+			
+			if ( ! in_array($one_after, $space))
+			{
+				$str = str_replace(	$one_before."'".$one_after,
+									$one_before."&#8216;".$one_after,
+									$str);
+			}
+			elseif( ! in_array($one_before, $space))
+			{
+				$str = str_replace(	$one_before."'".$one_after,
+									$one_before."&#8217;".$one_after,
+									$str);
+			}
+			
+			$start = $start+$current+2;
+		}
+		
+		return $str;
+	}
+	
+	// --------------------------------------------------------------------
+
+	/**
+	 * Format Newlines
+	 *
+	 * Converts newline characters into either <p> tags or <br />
+	 *
+	 */	
+	function format_newlines($str)
+	{
+		if ($str == '')
+		{
+			return $str;
+		}
+
+		if (strpos($str, "\n") === FALSE)
+		{
+			return '<p>'.$str.'</p>';
+		}
+			
+		$str = str_replace("\n\n", "</p>\n\n<p>", $str);
+		$str = preg_replace("/([^\n])(\n)([^\n])/", "\\1<br />\\2\\3", $str);
+		
+		return '<p>'.$str.'</p>';
+	}	
+}
+
+ 
+?>
\ No newline at end of file
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
new file mode 100644
index 0000000..d2d2a59
--- /dev/null
+++ b/system/helpers/url_helper.php
@@ -0,0 +1,487 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter URL Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/url_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Site URL
+ *
+ * Create a local URL based on your basepath. Segments can be passed via the 
+ * first parameter either as a string or an array.
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function site_url($uri = '')
+{ 
+	$obj =& get_instance();
+	return $obj->config->site_url($uri);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Base URL
+ *
+ * Returns the "base_url" item from your config file
+ *
+ * @access	public
+ * @return	string
+ */	
+function base_url()
+{ 
+	$obj =& get_instance();
+	return $obj->config->item('base_url', 1);
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Index page
+ *
+ * Returns the "index_page" from your config file
+ *
+ * @access	public
+ * @return	string
+ */	
+function index_page()
+{ 
+	$obj =& get_instance();
+	return $obj->config->item('index_page');
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Anchor Link
+ *
+ * Creates an anchor based on the local URL.
+ *
+ * @access	public
+ * @param	string	the URL
+ * @param	string	the link title
+ * @param	mixed	any attributes
+ * @return	string
+ */	
+function anchor($uri = '', $title = '', $attributes = '')
+{
+	$site_url = site_url($uri);
+	
+	if ($title == '')
+	{
+		$title = $site_url;
+	}
+
+	if ($attributes == '')
+	{
+		$attributes = ' title="'.$title.'"';
+	}
+	else
+	{
+		if (is_array($attributes))
+		{
+			$attributes = parse_url_attributes($attributes);
+		}
+	}
+
+	return '<a href="'.$site_url.'"'.$attributes.'>'.$title.'</a>';
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Anchor Link - Pop-up version
+ *
+ * Creates an anchor based on the local URL. The link
+ * opens a new window based on the attributes specified.
+ *
+ * @access	public
+ * @param	string	the URL
+ * @param	string	the link title
+ * @param	mixed	any attributes
+ * @return	string
+ */
+function anchor_popup($uri = '', $title = '', $attributes = FALSE)
+{	
+	$site_url = site_url($uri);
+	
+	if ($title == '')
+	{
+		$title = $site_url;
+	}
+	
+	if ($attributes === FALSE)
+	{
+		return "<a href='javascript:void(0);' onclick=\"window.open('".$site_url."', '_blank');\">".$title."</a>";
+	}
+	
+	if ( ! is_array($attributes))
+	{
+		$attributes = array();
+	}
+		
+	foreach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0', ) as $key => $val)
+	{
+		$atts[$key] = ( ! isset($attributes[$key])) ? $val : $attributes[$key];
+	}
+
+	return "<a href='javascript:void(0);' onclick=\"window.open('".$site_url."', '_blank', '".parse_url_attributes($atts, TRUE)."');\">".$title."</a>";
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Mailto Link
+ *
+ * @access	public
+ * @param	string	the email address
+ * @param	string	the link title
+ * @param	mixed 	any attributes
+ * @return	string
+ */
+function mailto($email, $title = '', $attributes = '')
+{
+	if ($title == "") 
+	{
+		$title = $email;
+	}
+	
+	if (is_array($attributes))
+	{
+		$attributes = parse_url_attributes($attributes);
+	}
+	
+	return '<a href="mailto:'.$email.'"'.$attributes.'>'.$title.'</a>';
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Encoded Mailto Link
+ *
+ * Create a spam-protected mailto link written in Javascript
+ *
+ * @access	public
+ * @param	string	the email address
+ * @param	string	the link title
+ * @param	mixed 	any attributes
+ * @return	string
+ */
+function safe_mailto($email, $title = '', $attributes = '')
+{
+	if ($title == "") 
+	{
+		$title = $email;
+	}
+					
+	for ($i = 0; $i < 16; $i++)
+	{
+		$x[] = substr('<a href="mailto:', $i, 1);
+	}
+	
+	for ($i = 0; $i < strlen($email); $i++)
+	{
+		$x[] = "|".ord(substr($email, $i, 1));
+	}
+
+	$x[] = '"'; 
+
+	if ($attributes != '')
+	{
+		if (is_array($attributes))
+		{
+			foreach ($attributes as $key => $val)
+			{
+				$x[] =  ' '.$key.'="';
+				for ($i = 0; $i < strlen($val); $i++)
+				{
+					$x[] = "|".ord(substr($val, $i, 1));
+				}
+				$x[] = '"';
+			}
+		}
+		else
+		{	
+			for ($i = 0; $i < strlen($attributes); $i++)
+			{
+				$x[] = substr($attributes, $i, 1);
+			}
+		}
+	}	
+	
+	$x[] = '>';
+	
+	$temp = array();
+	for ($i = 0; $i < strlen($title); $i++)
+	{
+		$ordinal = ord($title[$i]);
+	
+		if ($ordinal < 128)
+		{
+			$x[] = "|".$ordinal;            
+		}
+		else
+		{
+			if (count($temp) == 0)
+			{
+				$count = ($ordinal < 224) ? 2 : 3;
+			}
+		
+			$temp[] = $ordinal;
+			if (count($temp) == $count)
+			{
+				$number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % 64) : (($temp['0'] % 32) * 64) + ($temp['1'] % 64);
+				$x[] = "|".$number;
+				$count = 1;
+				$temp = array();
+			}   
+		}
+	}
+	
+	$x[] = '<'; $x[] = '/'; $x[] = 'a'; $x[] = '>';
+	
+	$x = array_reverse($x);
+	ob_start();
+	
+?><script type="text/javascript">
+//<![CDATA[
+var l=new Array();
+<?php
+$i = 0;
+foreach ($x as $val){ ?>l[<?php echo $i++; ?>]='<?php echo $val; ?>';<?php } ?>
+
+for (var i = l.length-1; i >= 0; i=i-1){ 
+if (l[i].substring(0, 1) == '|') document.write("&#"+unescape(l[i].substring(1))+";"); 
+else document.write(unescape(l[i]));}
+//]]>
+</script><?php
+
+	$buffer = ob_get_contents();
+	ob_end_clean(); 
+	return $buffer;        
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Auto-linker
+ *
+ * Automatically links URL and Email addresses.
+ * Note: There's a bit of extra code here to deal with
+ * URLs or emails that end in a period.  We'll strip these
+ * off and add them after the link.
+ *
+ * @access	public
+ * @param	string	the string
+ * @param	string	the type: email, url, or both 
+ * @param	bool 	whether to create pop-up links
+ * @return	string
+ */
+function auto_link($str, $type = 'both', $popup = FALSE)
+{
+	if ($type != 'email')
+	{		
+		if (preg_match_all("#(^|\s|\()((http(s?)://)|(www\.))(\w+[^\s\)\<]+)#i", $str, $matches))
+		{
+			$pop = ($popup == TRUE) ? " target=\"_blank\" " : "";
+		
+			for ($i = 0; $i < sizeof($matches['0']); $i++)
+			{
+				$period = '';
+				if (preg_match("|\.$|", $matches['6'][$i]))
+				{
+					$period = '.';
+					$matches['6'][$i] = substr($matches['6'][$i], 0, -1);
+				}
+			
+				$str = str_replace($matches['0'][$i],
+									$matches['1'][$i].'<a href="http'.
+									$matches['4'][$i].'://'.
+									$matches['5'][$i].
+									$matches['6'][$i].'"'.$pop.'>http'.
+									$matches['4'][$i].'://'.
+									$matches['5'][$i].
+									$matches['6'][$i].'</a>'.
+									$period, $str);
+			}
+		}
+	}
+
+	if ($type != 'url')
+	{	
+		if (preg_match_all("/([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]*)/i", $str, $matches))
+		{
+			for ($i = 0; $i < sizeof($matches['0']); $i++)
+			{
+				$period = '';
+				if (preg_match("|\.$|", $matches['3'][$i]))
+				{
+					$period = '.';
+					$matches['3'][$i] = substr($matches['3'][$i], 0, -1);
+				}
+			
+				$str = str_replace($matches['0'][$i], safe_mailto($matches['1'][$i].'@'.$matches['2'][$i].'.'.$matches['3'][$i]).$period, $str);
+			}
+		
+		}
+	}
+	return $str;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Prep URL
+ *
+ * Simply adds the http:// part if missing
+ *
+ * @access	public
+ * @param	string	the URL
+ * @return	string
+ */
+function prep_url($str = '')
+{
+	if ($str == 'http://' OR $str == '')
+	{
+		return '';
+	}
+	
+	if (substr($str, 0, 7) != 'http://' && substr($str, 0, 8) != 'https://')
+	{
+		$str = 'http://'.$str;
+	}
+	
+	return $str;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Create URL Title
+ *
+ * Takes a "title" string as input and creates a
+ * human-friendly URL string with either a dash
+ * or an underscore as the word separator.
+ *
+ * @access	public
+ * @param	string	the string
+ * @param	string	the separator: dash, or underscore
+ * @return	string
+ */
+function url_title($str, $separator = 'dash')
+{
+	if ($separator == 'dash')
+	{
+		$search		= '_';
+		$replace	= '-';
+	}
+	else
+	{
+		$search		= '-';
+		$replace	= '_';
+	}
+		
+	$trans = array(
+					$search								=> $replace,
+					"\s+"								=> $replace,
+					"[^a-z0-9".$replace."]"				=> '',
+					$replace."+"						=> $replace,
+					$replace."$"						=> '',
+					"^".$replace						=> ''
+				   );
+
+	$str = strip_tags(strtolower($str));
+	
+	foreach ($trans as $key => $val)
+	{
+		$str = preg_replace("#".$key."#", $val, $str);
+	} 
+	
+	return trim(stripslashes($str));
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Header Redirect
+ *
+ * Header redirect in two flavors
+ *
+ * @access	public
+ * @param	string	the URL
+ * @param	string	the method: location or redirect
+ * @return	string
+ */
+function redirect($uri = '', $method = 'location')
+{  
+	switch($method)
+	{
+		case 'refresh' : header("Refresh:0;url=".site_url($uri));
+			break;
+		default        : header("location:".site_url($uri));
+			break;
+	}
+	exit;
+}
+	
+// ------------------------------------------------------------------------
+
+/**
+ * Parse out the attributes
+ *
+ * Some of the functions use this
+ *
+ * @access	private
+ * @param	array
+ * @param	bool
+ * @return	string
+ */
+function parse_url_attributes($attributes, $javascript = FALSE)
+{
+	$att = '';
+	foreach ($attributes as $key => $val)
+	{
+		if ($javascript == TRUE)
+		{
+			$att .= $key . '=' . $val . ',';
+		}
+		else
+		{
+			$att .= ' ' . $key . '="' . $val . '"';
+		}
+	}
+	
+	if ($javascript == TRUE)
+	{
+		$att = substr($att, 0, -1);
+	}
+	
+	return $att;
+}
+
+?>
\ No newline at end of file
diff --git a/system/helpers/xml_helper.php b/system/helpers/xml_helper.php
new file mode 100644
index 0000000..ee3fc28
--- /dev/null
+++ b/system/helpers/xml_helper.php
@@ -0,0 +1,55 @@
+<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * Code Igniter
+ *
+ * An open source application development framework for PHP 4.3.2 or newer
+ *
+ * @package		CodeIgniter
+ * @author		Rick Ellis
+ * @copyright	Copyright (c) 2006, pMachine, Inc.
+ * @license		http://www.codeignitor.com/user_guide/license.html 
+ * @link		http://www.codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+ 
+// ------------------------------------------------------------------------
+
+/**
+ * Code Igniter XML Helpers
+ *
+ * @package		CodeIgniter
+ * @subpackage	Helpers
+ * @category	Helpers
+ * @author		Rick Ellis
+ * @link		http://www.codeigniter.com/user_guide/helpers/xml_helper.html
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Convert Reserved XML characters to Entities
+ *
+ * @access	public
+ * @param	string
+ * @return	string
+ */	
+function xml_convert($str)
+{
+	$temp = '__TEMP_AMPERSANDS';
+	
+	$str = preg_replace("/&#(\d+);/", "$temp\\1;", $str);
+	$str = preg_replace("/&(\w+);/",  "$temp\\1;", $str);
+	
+	$str = str_replace(array("&","<",">","\"", "'", "-"),
+					   array("&amp;", "&lt;", "&gt;", "&quot;", "&#39;", "&#45;"),
+					   $str);
+		
+	$str = preg_replace("/$temp(\d+);/","&#\\1;",$str);
+	$str = preg_replace("/$temp(\w+);/","&\\1;", $str);
+		
+	return $str;
+}    
+
+
+?>
\ No newline at end of file