summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
authoradmin <devnull@localhost>2006-08-25 19:25:49 +0200
committeradmin <devnull@localhost>2006-08-25 19:25:49 +0200
commitb0dd10f8171945e0c1f3527dd1e9d18b043e01a7 (patch)
treec3583ba09e72217683c4304f4690df6ce39ba731 /system
Initial Import
Diffstat (limited to 'system')
-rw-r--r--system/application/config/autoload.php101
-rw-r--r--system/application/config/config.php244
-rw-r--r--system/application/config/database.php57
-rw-r--r--system/application/config/index.html15
-rw-r--r--system/application/config/mimes.php103
-rw-r--r--system/application/config/routes.php49
-rw-r--r--system/application/controllers/index.html15
-rw-r--r--system/application/controllers/welcome.php15
-rw-r--r--system/application/errors/error_404.php35
-rw-r--r--system/application/errors/error_db.php34
-rw-r--r--system/application/errors/error_general.php34
-rw-r--r--system/application/errors/error_php.php10
-rw-r--r--system/application/errors/index.html15
-rw-r--r--system/application/models/index.html15
-rw-r--r--system/application/scripts/index.html15
-rw-r--r--system/application/views/index.html15
-rw-r--r--system/application/views/welcome_message.php62
-rw-r--r--system/cache/index.html15
-rw-r--r--system/codeigniter/Base4.php58
-rw-r--r--system/codeigniter/Base5.php62
-rw-r--r--system/codeigniter/CodeIgniter.php256
-rw-r--r--system/codeigniter/Common.php238
-rw-r--r--system/codeigniter/index.html15
-rw-r--r--system/drivers/DB_active_record.php875
-rw-r--r--system/drivers/DB_driver.php948
-rw-r--r--system/drivers/DB_mssql.php472
-rw-r--r--system/drivers/DB_mysql.php495
-rw-r--r--system/drivers/DB_mysqli.php496
-rw-r--r--system/drivers/DB_odbc.php468
-rw-r--r--system/drivers/DB_postgre.php476
-rw-r--r--system/drivers/DB_sqlite.php501
-rw-r--r--system/drivers/index.html15
-rw-r--r--system/fonts/index.html15
-rw-r--r--system/fonts/texb.ttfbin0 -> 143830 bytes
-rw-r--r--system/helpers/array_helper.php47
-rw-r--r--system/helpers/cookie_helper.php77
-rw-r--r--system/helpers/date_helper.php530
-rw-r--r--system/helpers/directory_helper.php69
-rw-r--r--system/helpers/file_helper.php139
-rw-r--r--system/helpers/form_helper.php382
-rw-r--r--system/helpers/html_helper.php76
-rw-r--r--system/helpers/index.html15
-rw-r--r--system/helpers/security_helper.php112
-rw-r--r--system/helpers/string_helper.php154
-rw-r--r--system/helpers/text_helper.php386
-rw-r--r--system/helpers/typography_helper.php490
-rw-r--r--system/helpers/url_helper.php487
-rw-r--r--system/helpers/xml_helper.php55
-rw-r--r--system/init/index.html15
-rw-r--r--system/init/init_calendar.php19
-rw-r--r--system/init/init_email.php24
-rw-r--r--system/init/init_encrypt.php18
-rw-r--r--system/init/init_image_lib.php24
-rw-r--r--system/init/init_pagination.php24
-rw-r--r--system/init/init_parser.php19
-rw-r--r--system/init/init_session.php18
-rw-r--r--system/init/init_trackback.php18
-rw-r--r--system/init/init_unit_test.php18
-rw-r--r--system/init/init_upload.php24
-rw-r--r--system/init/init_validation.php18
-rw-r--r--system/init/init_xmlrpc.php24
-rw-r--r--system/init/init_xmlrpcs.php27
-rw-r--r--system/language/english/calendar_lang.php49
-rw-r--r--system/language/english/date_lang.php49
-rw-r--r--system/language/english/db_lang.php15
-rw-r--r--system/language/english/email_lang.php21
-rw-r--r--system/language/english/imglib_lang.php21
-rw-r--r--system/language/english/index.html15
-rw-r--r--system/language/english/scaffolding_lang.php15
-rw-r--r--system/language/english/unit_test_lang.php22
-rw-r--r--system/language/english/upload_lang.php16
-rw-r--r--system/language/english/validation_lang.php15
-rw-r--r--system/language/index.html15
-rw-r--r--system/libraries/Benchmark.php117
-rw-r--r--system/libraries/Calendar.php473
-rw-r--r--system/libraries/Config.php181
-rw-r--r--system/libraries/Controller.php445
-rw-r--r--system/libraries/Email.php1740
-rw-r--r--system/libraries/Encrypt.php378
-rw-r--r--system/libraries/Exceptions.php165
-rw-r--r--system/libraries/Hooks.php237
-rw-r--r--system/libraries/Image_lib.php1550
-rw-r--r--system/libraries/Input.php585
-rw-r--r--system/libraries/Language.php113
-rw-r--r--system/libraries/Loader.php611
-rw-r--r--system/libraries/Log.php117
-rw-r--r--system/libraries/Model.php72
-rw-r--r--system/libraries/Output.php241
-rw-r--r--system/libraries/Pagination.php207
-rw-r--r--system/libraries/Parser.php178
-rw-r--r--system/libraries/Router.php318
-rw-r--r--system/libraries/Session.php499
-rw-r--r--system/libraries/Sha1.php254
-rw-r--r--system/libraries/Trackback.php561
-rw-r--r--system/libraries/URI.php243
-rw-r--r--system/libraries/Unit_test.php331
-rw-r--r--system/libraries/Upload.php775
-rw-r--r--system/libraries/Validation.php692
-rw-r--r--system/libraries/Xmlrpc.php1409
-rw-r--r--system/libraries/Xmlrpcs.php492
-rw-r--r--system/libraries/index.html15
-rw-r--r--system/logs/index.html15
-rw-r--r--system/plugins/captcha_pi.php346
-rw-r--r--system/plugins/index.html15
-rw-r--r--system/plugins/js_calendar_pi.php604
-rw-r--r--system/scaffolding/Scaffolding.php285
-rw-r--r--system/scaffolding/images/background.jpgbin0 -> 410 bytes
-rw-r--r--system/scaffolding/images/index.html15
-rw-r--r--system/scaffolding/images/logo.jpgbin0 -> 4518 bytes
-rw-r--r--system/scaffolding/index.html15
-rw-r--r--system/scaffolding/views/add.php30
-rw-r--r--system/scaffolding/views/delete.php7
-rw-r--r--system/scaffolding/views/edit.php31
-rw-r--r--system/scaffolding/views/footer.php10
-rw-r--r--system/scaffolding/views/header.php31
-rw-r--r--system/scaffolding/views/index.html15
-rw-r--r--system/scaffolding/views/no_data.php6
-rw-r--r--system/scaffolding/views/stylesheet.css143
-rw-r--r--system/scaffolding/views/view.php25
119 files changed, 24393 insertions, 0 deletions
diff --git a/system/application/config/autoload.php b/system/application/config/autoload.php
new file mode 100644
index 000000000..a3ce4108e
--- /dev/null
+++ b/system/application/config/autoload.php
@@ -0,0 +1,101 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+/*
+| -------------------------------------------------------------------
+| AUTO-LOADER
+| -------------------------------------------------------------------
+| This file specifies which systems should be loaded by default.
+|
+| In order to keep the framework as light-weight as possible only the
+| absolute minimal resources are loaded by default. For example,
+| the database is not connected to automatically since no assumption
+| is made regarding whether you intend to use it. This file lets
+| you globally define which systems you would like loaded with every
+| request. In addition to core systems you can auto-load plugins,
+| helper files, config files, and your own scripts.
+|
+| -------------------------------------------------------------------
+| Instructions
+| -------------------------------------------------------------------
+|
+| These are the things you can load automatically:
+|
+| 1. Core classes
+| 2. Helper files
+| 3. Plugins
+| 4. Scripts
+| 5. Custom config files
+|
+| Note: The items will be loaded in the order that they are defined
+|
+| Please read the user guide for more detailed information
+*/
+
+/*
+| -------------------------------------------------------------------
+| Auto-load Core Classes
+| -------------------------------------------------------------------
+| Prototype:
+|
+| $autoload['core'] = array('database', 'session', 'xmlrpc');
+*/
+
+$autoload['core'] = array('session');
+
+
+/*
+| -------------------------------------------------------------------
+| Auto-load Helper Files
+| -------------------------------------------------------------------
+| Prototype:
+|
+| $autoload['helper'] = array('url', 'file');
+*/
+
+$autoload['helper'] = array();
+
+
+/*
+| -------------------------------------------------------------------
+| Auto-load Plugins
+| -------------------------------------------------------------------
+| Prototype:
+|
+| $autoload['plugin'] = array('captcha', 'js_calendar');
+*/
+
+$autoload['plugin'] = array();
+
+
+/*
+| -------------------------------------------------------------------
+| Auto-load Scripts
+| -------------------------------------------------------------------
+| The term "scripts" refers to you own PHP scripts that you've
+| placed in the application/scripts/ folder
+|
+| Prototype:
+|
+| $autoload['script'] = array('my_script1', 'my_script2');
+*/
+
+$autoload['script'] = array();
+
+
+/*
+| -------------------------------------------------------------------
+| Auto-load Config files
+| -------------------------------------------------------------------
+| Prototype:
+|
+| $autoload['config'] = array('config1', 'config2');
+|
+| NOTE: This item is intended for use ONLY if you have created custom
+| config files. Otherwise, leave it blank.
+|
+*/
+
+$autoload['config'] = array();
+
+
+
+?> \ No newline at end of file
diff --git a/system/application/config/config.php b/system/application/config/config.php
new file mode 100644
index 000000000..0b4f33f41
--- /dev/null
+++ b/system/application/config/config.php
@@ -0,0 +1,244 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/*
+|--------------------------------------------------------------------------
+| Base Site URL
+|--------------------------------------------------------------------------
+|
+| URL to your Code Igniter root. Typically this will be your base URL,
+| WITH a trailing slash:
+|
+| http://www.your-site.com/
+|
+*/
+$config['base_url'] = "http://127.0.0.1/CodeIgniter/";
+
+/*
+|--------------------------------------------------------------------------
+| Index File
+|--------------------------------------------------------------------------
+|
+| Typically this will be your index.php file, unless you've renamed it to
+| something else. If you are using mod_rewrite to remove the page set this
+| variable so that it is blank.
+|
+*/
+$config['index_page'] = "index.php";
+
+/*
+|--------------------------------------------------------------------------
+| URI PROTOCOL
+|--------------------------------------------------------------------------
+|
+| This item determines which server global should be used to retrieve the
+| URI string. The default setting of "auto" works for most servers.
+| If your links do not seem to work, try one of the other delicious flavors:
+|
+| 'auto' Default - auto detects
+| 'path_info' Uses the PATH_INFO
+| 'query_string' Uses the QUERY_STRING
+|
+*/
+$config['uri_protocol'] = "auto";
+
+/*
+|--------------------------------------------------------------------------
+| URL suffix
+|--------------------------------------------------------------------------
+|
+| This option allows you to add a suffix to all URLs generated by Code Igniter.
+| For more information please see the user guide:
+|
+| http://www.codeigniter.com/user_guide/general/urls.html
+*/
+
+$config['url_suffix'] = "";
+
+/*
+|--------------------------------------------------------------------------
+| Default Language
+|--------------------------------------------------------------------------
+|
+| This determines which set of language files should be used. Make sure
+| there is an available translation if you intend to use something other
+| than english.
+|
+*/
+$config['language'] = "english";
+
+
+/*
+|--------------------------------------------------------------------------
+| Enable/Disable System Hooks
+|--------------------------------------------------------------------------
+|
+| If you would like to use the "hooks" feature you must enable it by
+| setting this variable to TRUE (boolean). See the user guide for details.
+|
+*/
+$config['enable_hooks'] = TRUE;
+
+
+/*
+|--------------------------------------------------------------------------
+| Enable Query Strings
+|--------------------------------------------------------------------------
+|
+| By default Code Igniter uses search-engine friendly segment based URLs:
+| www.your-site.com/who/what/where/
+|
+| You can optionally enable standard query string based URLs:
+| www.your-site.com?who=me&what=something&where=here
+|
+| Options are: TRUE or FALSE (boolean)
+|
+| The two other items let you set the query string "words" that will
+| invoke your controllers and its functions:
+| www.your-site.com/index.php?c=controller&m=function
+|
+| Please note that some of the helpers won't work as expected when
+| this feature is enabled, since Code Igniter is designed primarily to
+| use segment based URLs.
+|
+*/
+$config['enable_query_strings'] = FALSE;
+$config['controller_trigger'] = 'c';
+$config['function_trigger'] = 'm';
+
+/*
+|--------------------------------------------------------------------------
+| Master Time Reference
+|--------------------------------------------------------------------------
+|
+| Options are "local" or "gmt". This pref tells the system whether to use
+| your server's local time as the master "now" reference, or convert it to
+| GMT. See the "date helper" page of the user guide for information
+| regarding date handling.
+|
+*/
+$config['time_reference'] = 'local';
+
+/*
+|--------------------------------------------------------------------------
+| Enable/Disable Error Logging
+|--------------------------------------------------------------------------
+|
+| If you would like errors or debug messages logged set this variable to
+| TRUE (boolean). Note: You must set the file permissions on the "logs" folder
+| such that it is writable.
+|
+*/
+$config['log_errors'] = FALSE;
+
+/*
+|--------------------------------------------------------------------------
+| Error Logging Threshold
+|--------------------------------------------------------------------------
+|
+| If you have enabled error logging, you can set an error threshold to
+| determine what gets logged. Threshold options are:
+|
+| 1 = Error Messages (including PHP errors)
+| 2 = Debug Messages
+| 3 = Informational Messages
+| 4 = All Messages
+|
+| For a live site you'll usually only enable Errors (1) to be logged otherwise
+| your log files will fill up very fast.
+|
+*/
+$config['log_threshold'] = 4;
+
+/*
+|--------------------------------------------------------------------------
+| Error Logging Directory Path
+|--------------------------------------------------------------------------
+|
+| Leave this BLANK unless you would like to set something other than the default
+| system/logs/ folder. Use a full server path with trailing slash.
+|
+*/
+$config['log_path'] = '';
+
+/*
+|--------------------------------------------------------------------------
+| Date Format for Logs
+|--------------------------------------------------------------------------
+|
+| Each item that is logged has an associated date. You can use PHP date
+| codes to set your own date formatting
+|
+*/
+$config['log_date_format'] = 'Y-m-d H:i:s';
+
+/*
+|--------------------------------------------------------------------------
+| Cache Directory Path
+|--------------------------------------------------------------------------
+|
+| Leave this BLANK unless you would like to set something other than the default
+| system/cache/ folder. Use a full server path with trailing slash.
+|
+*/
+$config['cache_path'] = '';
+
+
+/*
+|--------------------------------------------------------------------------
+| Encryption Key
+|--------------------------------------------------------------------------
+|
+| If you use the Encryption class or the Sessions class with encryption
+| enabled you MUST set an encryption key. See the user guide for info.
+|
+*/
+$config['encryption_key'] = "";
+
+
+/*
+|--------------------------------------------------------------------------
+| Session Variables
+|--------------------------------------------------------------------------
+|
+| 'session_cookie_name' = the name you want for the cookie
+| 'encrypt_sess_cookie' = TRUE/FALSE (boolean). Whether to encrypt the cookie
+| 'session_expiration' = the number of SECONDS you want the session to last.
+| by default sessions last 7200 seconds (two hours). Set to zero for no expiration.
+|
+*/
+$config['sess_cookie_name'] = 'ci_session';
+$config['sess_expiration'] = 7200;
+$config['sess_encrypt_cookie'] = FALSE;
+$config['sess_use_database'] = FALSE;
+$config['sess_table_name'] = '';
+$config['sess_match_ip'] = TRUE;
+$config['sess_match_useragent'] = TRUE;
+
+
+/*
+|--------------------------------------------------------------------------
+| Cookie Related Variables
+|--------------------------------------------------------------------------
+|
+| 'cookie_prefix' = Set a prefix if you need to avoid collisions
+| 'cookie_domain' = Set to .your-domain.com for site-wide cookies
+| 'cookie_path' = Typically will be a forward slash
+|
+*/
+$config['cookie_prefix'] = "";
+$config['cookie_domain'] = "";
+$config['cookie_path'] = "/";
+
+/*
+|--------------------------------------------------------------------------
+| Global XSS Filtering
+|--------------------------------------------------------------------------
+|
+| Determines whether the XSS filter is always active when GET, POST or
+| COOKIE data is encountered
+|
+*/
+$config['global_xss_filtering'] = FALSE;
+
+
+?> \ No newline at end of file
diff --git a/system/application/config/database.php b/system/application/config/database.php
new file mode 100644
index 000000000..610f6081d
--- /dev/null
+++ b/system/application/config/database.php
@@ -0,0 +1,57 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+/*
+| -------------------------------------------------------------------
+| DATABASE CONNECTIVITY SETTINGS
+| -------------------------------------------------------------------
+| This file will contain the settings needed to access your database.
+|
+| For complete instructions please consult the "Database Connection"
+| page of the User Guide.
+|
+| -------------------------------------------------------------------
+| EXPLANATION OF VARIABLES
+| -------------------------------------------------------------------
+|
+| ['hostname'] The hostname of your database server.
+| ['username'] The username used to connect to the database
+| ['password'] The password used to connect to the database
+| ['database'] The name of the database you want to connect to
+| ['dbdriver'] The database type. ie: mysql. Currently supported:
+ mysql, mysqli, postgre, odbc, mssql
+| ['dbprefix'] You can add an optional prefix, which will be added
+| to the table name when using the Active Record class
+| ['pconnect'] TRUE/FALSE - Whether to use a persistent connection
+| ['db_debug'] TRUE/FALSE - Whether database errors should be displayed.
+| ['active_r'] TRUE/FALSE - Whether to load the active record class
+|
+| The $active_group variable lets you choose which connection group to
+| make active. By default there is only one group (the "default" group).
+|
+*/
+
+$active_group = "test";
+
+$db['default']['hostname'] = "localhost";
+$db['default']['username'] = "root";
+$db['default']['password'] = "";
+$db['default']['database'] = "ellislab";
+$db['default']['dbdriver'] = "mysql";
+$db['default']['dbprefix'] = "";
+$db['default']['active_r'] = TRUE;
+$db['default']['pconnect'] = FALSE;
+$db['default']['db_debug'] = TRUE;
+
+
+
+$db['test']['hostname'] = "localhost";
+$db['test']['username'] = "root";
+$db['test']['password'] = "";
+$db['test']['database'] = "tester";
+$db['test']['dbdriver'] = "mysql";
+$db['test']['dbprefix'] = "";
+$db['test']['active_r'] = TRUE;
+$db['test']['pconnect'] = FALSE;
+$db['test']['db_debug'] = TRUE;
+
+
+?> \ No newline at end of file
diff --git a/system/application/config/index.html b/system/application/config/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/application/config/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/application/config/mimes.php b/system/application/config/mimes.php
new file mode 100644
index 000000000..06bfcc67b
--- /dev/null
+++ b/system/application/config/mimes.php
@@ -0,0 +1,103 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+/*
+| -------------------------------------------------------------------
+| MIME TYPES
+| -------------------------------------------------------------------
+| This file contains an array of mime types. It is used by the
+| Upload class to help identyfiy allowed file types.
+|
+*/
+
+$mimes = array( 'hqx' => 'application/mac-binhex40',
+ 'cpt' => 'application/mac-compactpro',
+ 'csv' => array('text/x-comma-separated-values', 'application/vnd.ms-excel'),
+ '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/x-photoshop',
+ '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' => array('application/excel', 'application/vnd.ms-excel'),
+ 'ppt' => 'application/powerpoint',
+ 'wbxml' => 'application/wbxml',
+ 'wmlc' => 'application/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' => array('application/zip', 'application/x-zip-compressed'),
+ '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' => array('image/jpeg', 'image/pjpeg'),
+ 'jpg' => array('image/jpeg', 'image/pjpeg'),
+ 'jpe' => array('image/jpeg', 'image/pjpeg'),
+ 'png' => array('image/png', 'image/x-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' => array('text/plain', 'text/x-log'),
+ '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'
+ );
+
+
+?> \ No newline at end of file
diff --git a/system/application/config/routes.php b/system/application/config/routes.php
new file mode 100644
index 000000000..622bf88e6
--- /dev/null
+++ b/system/application/config/routes.php
@@ -0,0 +1,49 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+/*
+| -------------------------------------------------------------------------
+| URI ROUTING
+| -------------------------------------------------------------------------
+| This file lets you re-map URI requests to specific controller functions.
+|
+| Typically there is a one-to-one relationship between a URL string
+| and its corresponding controller class/method. The segments in a
+| URL normally follow this pattern:
+|
+| www.your-site.com/class/method/id/
+|
+| In some instances, however, you may want to remap this relationship
+| so that a different class/function is called than the one
+| corresponding to the URL.
+|
+| Please see the user guide for complete details:
+|
+| http://www.codeigniter.com/user_guide/general/routing.html
+|
+| -------------------------------------------------------------------------
+| RESERVED ROUTES
+| -------------------------------------------------------------------------
+|
+| There are two reserved routes:
+|
+| $route['default_controller'] = 'welcome';
+|
+| This route indicates which controller class should be loaded if the
+| URI contains no data. In the above example, the "welcome" class
+| would be loaded.
+|
+| $route['scaffolding_trigger'] = 'scaffolding';
+|
+| This route lets you set a "secret" word that will trigger the
+| scaffolding feature for added security. Note: Scaffolding must be
+| enabled in the controller in which you intend to use it.
+|
+*/
+
+$route['default_controller'] = "welcome";
+
+$route['scaffolding_trigger'] = "scaffolding";
+
+// Define your own routes below -------------------------------------------
+
+
+?> \ No newline at end of file
diff --git a/system/application/controllers/index.html b/system/application/controllers/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/application/controllers/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/application/controllers/welcome.php b/system/application/controllers/welcome.php
new file mode 100644
index 000000000..7f7296d81
--- /dev/null
+++ b/system/application/controllers/welcome.php
@@ -0,0 +1,15 @@
+<?php
+
+class Welcome extends Controller {
+
+ function Welcome()
+ {
+ parent::Controller();
+ }
+
+ function index()
+ {
+ $this->load->view('welcome_message');
+ }
+}
+?> \ No newline at end of file
diff --git a/system/application/errors/error_404.php b/system/application/errors/error_404.php
new file mode 100644
index 000000000..e5fa8f9db
--- /dev/null
+++ b/system/application/errors/error_404.php
@@ -0,0 +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>
+</html> \ No newline at end of file
diff --git a/system/application/errors/error_db.php b/system/application/errors/error_db.php
new file mode 100644
index 000000000..5aab89074
--- /dev/null
+++ b/system/application/errors/error_db.php
@@ -0,0 +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> \ No newline at end of file
diff --git a/system/application/errors/error_general.php b/system/application/errors/error_general.php
new file mode 100644
index 000000000..213b8353a
--- /dev/null
+++ b/system/application/errors/error_general.php
@@ -0,0 +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> \ No newline at end of file
diff --git a/system/application/errors/error_php.php b/system/application/errors/error_php.php
new file mode 100644
index 000000000..2fb3f2b2e
--- /dev/null
+++ b/system/application/errors/error_php.php
@@ -0,0 +1,10 @@
+<div style="border:1px solid #990000;padding-left:20px;margin:10px;">
+
+<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>
diff --git a/system/application/errors/index.html b/system/application/errors/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/application/errors/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/application/models/index.html b/system/application/models/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/application/models/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/application/scripts/index.html b/system/application/scripts/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/application/scripts/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/application/views/index.html b/system/application/views/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/application/views/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/application/views/welcome_message.php b/system/application/views/welcome_message.php
new file mode 100644
index 000000000..815bef4db
--- /dev/null
+++ b/system/application/views/welcome_message.php
@@ -0,0 +1,62 @@
+<html>
+<head>
+<title>Welcome to Code Igniter</title>
+
+<style type="text/css">
+
+body {
+ background-color: #fff;
+ margin: 40px;
+ font-family: Lucida Grande, Verdana, Sans-serif;
+ font-size: 14px;
+ color: #4F5155;
+}
+
+a {
+ color: #003399;
+ background-color: transparent;
+ font-weight: normal;
+}
+
+h1 {
+ color: #444;
+ background-color: transparent;
+ border-bottom: 1px solid #D0D0D0;
+ font-size: 16px;
+ font-weight: bold;
+ margin: 24px 0 2px 0;
+ padding: 5px 0 6px 0;
+}
+
+code {
+ font-family: Monaco, Verdana, Sans-serif;
+ font-size: 12px;
+ background-color: #f9f9f9;
+ border: 1px solid #D0D0D0;
+ color: #002166;
+ display: block;
+ margin: 14px 0 14px 0;
+ padding: 12px 10px 12px 10px;
+}
+
+</style>
+</head>
+<body>
+
+<h1>Welcome to Code Igniter!</h1>
+
+<p>The page you are looking at is being generated dynamically by Code Igniter.</p>
+
+<p>If you would like to edit this page you'll find it located at:</p>
+<code>system/application/views/welcome_message.php</code>
+
+<p>The corresponding controller for this page is found at:</p>
+<code>system/application/controllers/welcome.php</code>
+
+<p>If you are exploring Code Igniter for the very first time, you should start by reading the <a href="user_guide/">User Guide</a>.</p>
+
+
+<p><br />Page rendered in {elapsed_time} seconds</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/cache/index.html b/system/cache/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/cache/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/codeigniter/Base4.php b/system/codeigniter/Base4.php
new file mode 100644
index 000000000..5d945c26a
--- /dev/null
+++ b/system/codeigniter/Base4.php
@@ -0,0 +1,58 @@
+<?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.3
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CI_BASE - For PHP 4
+ *
+ * This file is used only when Code Igniter is being run under PHP 4.
+ * Since PHP 4 has such poor object handling we had to come up with
+ * a hack to resolve some scoping problems. PHP 5 doesn't suffer from
+ * this problem so we load one of two files based on the version of
+ * PHP being run.
+ *
+ * @package CodeIgniter
+ * @subpackage codeigniter
+ * @category front-controller
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/
+ */
+ class CI_Base extends CI_Loader {
+
+ function CI_Base()
+ {
+ global $OBJ;
+ parent::CI_Loader();
+ $this->load =& $this;
+ $OBJ = $this->load;
+ }
+}
+
+function &get_instance()
+{
+ global $OBJ, $CI;
+
+ if (is_object($CI))
+ {
+ return $CI;
+ }
+ else
+ {
+ return $OBJ->load;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/system/codeigniter/Base5.php b/system/codeigniter/Base5.php
new file mode 100644
index 000000000..ef3fc67f4
--- /dev/null
+++ b/system/codeigniter/Base5.php
@@ -0,0 +1,62 @@
+<?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.3
+ * @filesource
+ */
+
+
+// ------------------------------------------------------------------------
+
+/**
+ * CI_BASE - For PHP 5
+ *
+ * This file contains some code used only when Code Igniter is being
+ * run under PHP 5. It allows us to manage the CI super object more
+ * gracefully than what is possible with PHP 4.
+ *
+ * @package CodeIgniter
+ * @subpackage codeigniter
+ * @category front-controller
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/
+ */
+
+class CI_Base {
+
+ public function CI_Base()
+ {
+ $instance =& _load_class('Instance');
+ $instance->set_instance($this);
+ }
+}
+
+class Instance {
+ public static $instance;
+
+ public function set_instance(&$object)
+ {
+ self::$instance =& $object;
+ }
+
+ public function &get_instance()
+ {
+ return self::$instance;
+ }
+}
+
+function &get_instance()
+{
+ $instance =& _load_class('Instance');
+ return $instance->get_instance();
+}
+
+?> \ No newline at end of file
diff --git a/system/codeigniter/CodeIgniter.php b/system/codeigniter/CodeIgniter.php
new file mode 100644
index 000000000..aef7618e9
--- /dev/null
+++ b/system/codeigniter/CodeIgniter.php
@@ -0,0 +1,256 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * System Front Controller
+ *
+ * Loads the base classes and executes the request.
+ *
+ * @package CodeIgniter
+ * @subpackage codeigniter
+ * @category Front-controller
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/
+ */
+
+define('APPVER', '1.4');
+
+/*
+ * ------------------------------------------------------
+ * Load the global functions
+ * ------------------------------------------------------
+ */
+require(BASEPATH.'codeigniter/Common'.EXT);
+
+/*
+ * ------------------------------------------------------
+ * Define a custom error handler so we can log errors
+ * ------------------------------------------------------
+ */
+set_error_handler('_exception_handler');
+set_magic_quotes_runtime(0); // Kill magic quotes
+
+/*
+ * ------------------------------------------------------
+ * Start the timer... tick tock tick tock...
+ * ------------------------------------------------------
+ */
+
+$BM =& _load_class('CI_Benchmark');
+$BM->mark('code_igniter_start');
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the hooks classe
+ * ------------------------------------------------------
+ */
+
+$EXT =& _load_class('CI_Hooks');
+
+/*
+ * ------------------------------------------------------
+ * Is there a "pre_system" hook?
+ * ------------------------------------------------------
+ */
+if ($EXT->_hook_exists('pre_system'))
+{
+ $EXT->_call_hook('pre_system');
+}
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the base classes
+ * ------------------------------------------------------
+ */
+
+$CFG =& _load_class('CI_Config');
+$RTR =& _load_class('CI_Router');
+$OUT =& _load_class('CI_Output');
+
+/*
+ * ------------------------------------------------------
+ * Is there a valid cache file? If so, we're done...
+ * ------------------------------------------------------
+ */
+
+if ($EXT->_hook_exists('cache_override'))
+{
+ $EXT->_call_hook('cache_override');
+}
+else
+{
+ if ($OUT->_display_cache() == TRUE)
+ {
+ exit;
+ }
+}
+
+/*
+ * ------------------------------------------------------
+ * Does the requested controller exist?
+ * ------------------------------------------------------
+ */
+if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_class().EXT))
+{
+ show_404();
+}
+
+/*
+ * ------------------------------------------------------
+ * Load the remaining base classes
+ * ------------------------------------------------------
+ */
+
+$IN =& _load_class('CI_Input');
+$URI =& _load_class('CI_URI');
+$LANG =& _load_class('CI_Language');
+
+/*
+ * ------------------------------------------------------
+ * Load the app controller and local controller
+ * ------------------------------------------------------
+ *
+ * Note: Due to the poor object handling in PHP 4 we'll
+ * contditionally load different versions of the base
+ * class. Retaining PHP 4 compatibility requires a bit of a hack.
+ *
+ * Note: The Loader class needs to be included first
+ *
+ */
+
+
+_load_class('CI_Loader');
+
+if (floor(phpversion()) < 5)
+{
+ require(BASEPATH.'codeigniter/Base4'.EXT);
+}
+else
+{
+ require(BASEPATH.'codeigniter/Base5'.EXT);
+}
+
+_load_class('CI_Controller');
+
+require(APPPATH.'controllers/'.$RTR->fetch_class().EXT);
+
+/*
+ * ------------------------------------------------------
+ * Security check
+ * ------------------------------------------------------
+ *
+ * None of the functions in the app controller or the
+ * loader class can be called via the URI, nor can
+ * controller functions that begin with an underscore
+ */
+$class = $RTR->fetch_class();
+$method = $RTR->fetch_method();
+
+if ( ! class_exists($class)
+ OR $method == 'controller'
+ OR substr($method, 0, 1) == '_'
+ OR in_array($method, get_class_methods('Controller'))
+ )
+{
+ show_404();
+}
+
+/*
+ * ------------------------------------------------------
+ * Is there a "pre_controller" hook?
+ * ------------------------------------------------------
+ */
+if ($EXT->_hook_exists('pre_controller'))
+{
+ $EXT->_call_hook('pre_controller');
+}
+
+/*
+ * ------------------------------------------------------
+ * Instantiate the controller and call requested method
+ * ------------------------------------------------------
+ */
+$CI = new $class();
+
+if ($RTR->scaffolding_request === TRUE)
+{
+ if ($EXT->_hook_exists('scaffolding_override'))
+ {
+ $EXT->_call_hook('scaffolding_override');
+ }
+ else
+ {
+ $CI->_ci_scaffolding();
+ }
+}
+else
+{
+ if ( ! method_exists($CI, $method))
+ {
+ show_404();
+ }
+
+ $CI->$method();
+}
+
+/*
+ * ------------------------------------------------------
+ * Is there a "post_controller" hook?
+ * ------------------------------------------------------
+ */
+if ($EXT->_hook_exists('post_controller'))
+{
+ $EXT->_call_hook('post_controller');
+}
+
+/*
+ * ------------------------------------------------------
+ * Send the final rendered output to the browser
+ * ------------------------------------------------------
+ */
+
+if ($EXT->_hook_exists('display_override'))
+{
+ $EXT->_call_hook('display_override');
+}
+else
+{
+ $OUT->_display();
+}
+
+/*
+ * ------------------------------------------------------
+ * Is there a "post_system" hook?
+ * ------------------------------------------------------
+ */
+if ($EXT->_hook_exists('post_system'))
+{
+ $EXT->_call_hook('post_system');
+}
+
+/*
+ * ------------------------------------------------------
+ * Close the DB connection of one exists
+ * ------------------------------------------------------
+ */
+if ($CI->_ci_is_loaded('db'))
+{
+ $CI->db->close();
+}
+
+
+?> \ No newline at end of file
diff --git a/system/codeigniter/Common.php b/system/codeigniter/Common.php
new file mode 100644
index 000000000..2ec1c3d38
--- /dev/null
+++ b/system/codeigniter/Common.php
@@ -0,0 +1,238 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Common Functions
+ *
+ * Loads the base classes and executes the request.
+ *
+ * @package CodeIgniter
+ * @subpackage codeigniter
+ * @category Common Functions
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+* Class registry
+*
+*
+* @access public
+* @return object
+*/
+function &_load_class($class, $instantiate = TRUE)
+{
+ static $objects;
+
+ if ( ! isset($objects[$class]))
+ {
+ if (FALSE !== strpos($class, 'CI_'))
+ {
+ if (file_exists(APPPATH.'libraries/'.str_replace('CI_', '', $class).EXT))
+ {
+ require(APPPATH.'libraries/'.str_replace('CI_', '', $class).EXT);
+ }
+ else
+ {
+ require(BASEPATH.'libraries/'.str_replace('CI_', '', $class).EXT);
+ }
+ }
+
+ if ($instantiate == TRUE)
+ {
+ if ($class == 'CI_Controller')
+ $class = 'Controller';
+
+ $objects[$class] =& new $class();
+ }
+ else
+ {
+ $objects[$class] = TRUE;
+ }
+ }
+
+
+ return $objects[$class];
+}
+
+/**
+* Loads the main config.php file
+*
+*
+* @access private
+* @return array
+*/
+function &_get_config()
+{
+ static $conf;
+
+ if ( ! isset($conf))
+ {
+ require(APPPATH.'config/config'.EXT);
+
+ if ( ! isset($config) OR ! is_array($config))
+ {
+ show_error('Your config file does not appear to be formatted correctly.');
+ }
+
+ $conf[0] =& $config;
+ }
+ return $conf[0];
+}
+
+
+/**
+* Error Handler
+*
+* This function lets us invoke the exception class and
+* display errors using the standard error template located
+* in application/errors/errors.php
+* This function will send the error page directly to the
+* browser and exit.
+*
+* @access public
+* @return void
+*/
+function show_error($message)
+{
+ if ( ! class_exists('CI_Exceptions'))
+ {
+ include_once(BASEPATH.'libraries/Exceptions.php');
+ }
+
+ $error = new CI_Exceptions();
+ echo $error->show_error('An Error Was Encountered', $message);
+ exit;
+}
+
+
+/**
+* 404 Page Handler
+*
+* This function is similar to the show_error() function above
+* However, instead of the standard error template it displays
+* 404 errors.
+*
+* @access public
+* @return void
+*/
+function show_404($page = '')
+{
+ if ( ! class_exists('CI_Exceptions'))
+ {
+ include_once(BASEPATH.'libraries/Exceptions.php');
+ }
+
+ $error = new CI_Exceptions();
+ $error->show_404($page);
+ exit;
+}
+
+
+/**
+* Error Logging Interface
+*
+* We use this as a simple mechanism to access the logging
+* class and send messages to be logged.
+*
+* @access public
+* @return void
+*/
+function log_message($level = 2, $message, $php_error = FALSE)
+{
+ $config =& _get_config();
+ if ($config['log_errors'] === FALSE)
+ {
+ return;
+ }
+
+ if ( ! class_exists('CI_Log'))
+ {
+ include_once(BASEPATH.'libraries/Log.php');
+ }
+
+ if ( ! isset($LOG))
+ {
+ $LOG = new CI_Log(
+ $config['log_path'],
+ $config['log_threshold'],
+ $config['log_date_format']
+ );
+ }
+
+ $LOG->write_log($level, $message, $php_error);
+}
+
+
+/**
+* Exception Handler
+*
+* This is the custom exception handler we defined at the
+* top of this file. The main reason we use this is permit
+* PHP errors to be logged in our own log files since we may
+* not have access to server logs. Since this function
+* effectively intercepts PHP errors, however, we also need
+* to display errors based on the current error_reporting level.
+* We do that with the use of a PHP error template.
+*
+* @access private
+* @return void
+*/
+function _exception_handler($severity, $message, $filepath, $line)
+{
+ // We don't bother with "strict" notices since they will fill up
+ // the log file with information that isn't normally very
+ // helpful. For example, if you are running PHP 5 and you
+ // use version 4 style class functions (without prefixes
+ // like "public", "private", etc.) you'll get notices telling
+ // you that these have been deprecated.
+
+ if ($severity == E_STRICT)
+ {
+ return;
+ }
+
+ // Send the PHP error to the log file...
+ if ( ! class_exists('CI_Exceptions'))
+ {
+ include_once(BASEPATH.'libraries/Exceptions.php');
+ }
+ $error = new CI_Exceptions();
+
+ // Should we display the error?
+ // We'll get the current error_reporting level and add its bits
+ // with the severity bits to find out.
+
+ if (($severity & error_reporting()) == $severity)
+ {
+ $error->show_php_error($severity, $message, $filepath, $line);
+ }
+
+ // Should we log the error? No? We're done...
+ $config =& _get_config();
+ if ($config['log_errors'] === FALSE)
+ {
+ return;
+ }
+
+ $error->log_exception($severity, $message, $filepath, $line);
+}
+
+
+?> \ No newline at end of file
diff --git a/system/codeigniter/index.html b/system/codeigniter/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/codeigniter/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/drivers/DB_active_record.php b/system/drivers/DB_active_record.php
new file mode 100644
index 000000000..373c0f626
--- /dev/null
+++ b/system/drivers/DB_active_record.php
@@ -0,0 +1,875 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Active Record Class
+ *
+ * This is the platform-independent base Active Record implementation class.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_active_record extends CI_DB_driver {
+
+ var $ar_select = array();
+ var $ar_distinct = FALSE;
+ var $ar_from = array();
+ var $ar_join = array();
+ var $ar_where = array();
+ var $ar_like = array();
+ var $ar_groupby = array();
+ var $ar_having = array();
+ var $ar_limit = FALSE;
+ var $ar_offset = FALSE;
+ var $ar_order = FALSE;
+ var $ar_orderby = array();
+ var $ar_set = array();
+
+
+ /**
+ * Select
+ *
+ * Generates the SELECT portion of the query
+ *
+ * @access public
+ * @param string
+ * @return object
+ */
+ function select($select = '*')
+ {
+ if (is_string($select))
+ {
+ $select = explode(',', $select);
+ }
+
+ foreach ($select as $val)
+ {
+ $val = trim($val);
+
+ if ($val != '')
+ $this->ar_select[] = $val;
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * DISTINCT
+ *
+ * Sets a flag which tells the query string compiler to add DISTINCT
+ *
+ * @access public
+ * @param bool
+ * @return object
+ */
+ function distinct($val = TRUE)
+ {
+ $this->ar_distinct = (is_bool($val)) ? $val : TRUE;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From
+ *
+ * Generates the FROM portion of the query
+ *
+ * @access public
+ * @param mixed can be a string or array
+ * @return object
+ */
+ function from($from)
+ {
+ foreach ((array)$from as $val)
+ {
+ $this->ar_from[] = $this->dbprefix.$val;
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Join
+ *
+ * Generates the JOIN portion of the query
+ *
+ * @access public
+ * @param string
+ * @param string the join condition
+ * @param string the type of join
+ * @return object
+ */
+ function join($table, $cond, $type = '')
+ {
+ if ($type != '')
+ {
+ $type = strtoupper(trim($type));
+
+ if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER')))
+ {
+ $type = '';
+ }
+ else
+ {
+ $type .= ' ';
+ }
+ }
+
+ $this->ar_join[] = $type.'JOIN '.$table.' ON '.$cond;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Where
+ *
+ * Generates the WHERE portion of the query. Separates
+ * multiple calls with AND
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ function where($key, $value = NULL)
+ {
+ return $this->_where($key, $value, 'AND ');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * OR Where
+ *
+ * Generates the WHERE portion of the query. Separates
+ * multiple calls with OR
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ function orwhere($key, $value = NULL)
+ {
+ return $this->_where($key, $value, 'OR ');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Where
+ *
+ * Called by where() or orwhere()
+ *
+ * @access private
+ * @param mixed
+ * @param mixed
+ * @param string
+ * @return object
+ */
+ function _where($key, $value = NULL, $type = 'AND ')
+ {
+ if ( ! is_array($key))
+ {
+ $key = array($key => $value);
+ }
+
+ foreach ($key as $k => $v)
+ {
+ $prefix = (count($this->ar_where) == 0) ? '' : $type;
+
+ if ( ! is_null($v))
+ {
+ if ( ! $this->_has_operator($k))
+ {
+ $k .= ' =';
+ }
+
+ $v = ' '.$this->escape($v);
+ }
+
+ $this->ar_where[] = $prefix.$k.$v;
+ }
+ return $this;
+ }
+
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Like
+ *
+ * Generates a %LIKE% portion of the query. Separates
+ * multiple calls with AND
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ function like($field, $match = '')
+ {
+ return $this->_like($field, $match, 'AND ');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * OR Like
+ *
+ * Generates a %LIKE% portion of the query. Separates
+ * multiple calls with OR
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @return object
+ */
+ function orlike($field, $match = '')
+ {
+ return $this->_like($field, $match, 'OR ');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Like
+ *
+ * Called by like() or olike()
+ *
+ * @access private
+ * @param mixed
+ * @param mixed
+ * @param string
+ * @return object
+ */
+ function _like($field, $match = '', $type = 'AND ')
+ {
+ if ( ! is_array($field))
+ {
+ $field = array($field => $match);
+ }
+
+ foreach ($field as $k => $v)
+ {
+ $prefix = (count($this->ar_like) == 0) ? '' : $type;
+
+ $v = $this->escape_str($v);
+
+ $this->ar_like[] = $prefix." $k LIKE '%{$v}%'";
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * GROUP BY
+ *
+ * @access public
+ * @param string
+ * @return object
+ */
+ function groupby($by)
+ {
+ if (is_string($by))
+ {
+ $by = explode(',', $by);
+ }
+
+ foreach ($by as $val)
+ {
+ $val = trim($val);
+
+ if ($val != '')
+ $this->ar_groupby[] = $val;
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the HAVING value
+ *
+ * Separates multiple calls with AND
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return object
+ */
+ function having($key, $value = '')
+ {
+ return $this->_having($key, $value, 'AND ');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the OR HAVING value
+ *
+ * Separates multiple calls with OR
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return object
+ */
+ function orhaving($key, $value = '')
+ {
+ return $this->_having($key, $value, 'OR ');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the OR HAVING value
+ *
+ * Called by having() or orhaving()
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @return object
+ */
+ function _having($key, $value = '', $type = 'AND ')
+ {
+ if ( ! is_array($key))
+ {
+ $key = array($key => $value);
+ }
+
+ foreach ($key as $k => $v)
+ {
+ $prefix = (count($this->ar_having) == 0) ? '' : $type;
+
+ if ($v != '')
+ {
+ $v = ' '.$this->escape($v);
+ }
+
+ $this->ar_having[] = $prefix.$k.$v;
+ }
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the ORDER BY value
+ *
+ * @access public
+ * @param string
+ * @param string direction: asc or desc
+ * @return object
+ */
+ function orderby($orderby, $direction = '')
+ {
+ if (trim($direction) != '')
+ {
+ $direction = (in_array(strtoupper(trim($direction)), array('ASC', 'DESC'))) ? ' '.$direction : ' ASC';
+ }
+
+ $this->ar_orderby[] = $orderby.$direction;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the LIMIT value
+ *
+ * @access public
+ * @param integer the limit value
+ * @param integer the offset value
+ * @return object
+ */
+ function limit($value, $offset = '')
+ {
+ $this->ar_limit = $value;
+
+ if ($offset != '')
+ $this->ar_offset = $offset;
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sets the OFFSET value
+ *
+ * @access public
+ * @param integer the offset value
+ * @return object
+ */
+ function offset($value)
+ {
+ $this->ar_offset = $value;
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The "set" function. Allows key/value pairs to be set for inserting or updating
+ *
+ * @access public
+ * @param mixed
+ * @param string
+ * @return object
+ */
+ function set($key, $value = '')
+ {
+ $key = $this->_object_to_array($key);
+
+ if ( ! is_array($key))
+ {
+ $key = array($key => $value);
+ }
+
+ foreach ($key as $k => $v)
+ {
+ $this->ar_set[$k] = $this->escape($v);
+ }
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get
+ *
+ * Compiles the select statement based on the other functions called
+ * and runs the query
+ *
+ * @access public
+ * @param string the limit clause
+ * @param string the offset clause
+ * @return object
+ */
+ function get($table = '', $limit = null, $offset = null)
+ {
+ if ($table != '')
+ {
+ $this->from($table);
+ }
+
+ if ( ! is_null($limit))
+ {
+ $this->limit($limit, $offset);
+ }
+
+ $sql = $this->_compile_select();
+
+ $this->_reset_select();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * GetWhere
+ *
+ * Allows the where clause, limit and offset to be added directly
+ *
+ * @access public
+ * @param string the where clause
+ * @param string the limit clause
+ * @param string the offset clause
+ * @return object
+ */
+ function getwhere($table = '', $where = null, $limit = null, $offset = null)
+ {
+ if ($table != '')
+ {
+ $this->from($table);
+ }
+
+ if ( ! is_null($where))
+ {
+ $this->where($where);
+ }
+
+ if ( ! is_null($limit))
+ {
+ $this->limit($limit, $offset);
+ }
+
+ $sql = $this->_compile_select();
+
+ $this->_reset_select();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert
+ *
+ * Compiles an insert string and runs the query
+ *
+ * @access public
+ * @param string the table to retrieve the results from
+ * @param array an associative array of insert values
+ * @return object
+ */
+ function insert($table = '', $set = NULL)
+ {
+ if ( ! is_null($set))
+ {
+ $this->set($set);
+ }
+
+ if (count($this->ar_set) == 0)
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_use_set');
+ }
+ return FALSE;
+ }
+
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[0];
+ }
+
+ $sql = $this->_insert($this->dbprefix.$table, array_keys($this->ar_set), array_values($this->ar_set));
+
+ $this->_reset_write();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update
+ *
+ * Compiles an update string and runs the query
+ *
+ * @access public
+ * @param string the table to retrieve the results from
+ * @param array an associative array of update values
+ * @param mixed the where clause
+ * @return object
+ */
+ function update($table = '', $set = NULL, $where = null)
+ {
+ if ( ! is_null($set))
+ {
+ $this->set($set);
+ }
+
+ if (count($this->ar_set) == 0)
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_use_set');
+ }
+ return FALSE;
+ }
+
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[0];
+ }
+
+ if ($where != null)
+ {
+ $this->where($where);
+ }
+
+ $sql = $this->_update($this->dbprefix.$table, $this->ar_set, $this->ar_where);
+
+ $this->_reset_write();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete
+ *
+ * Compiles a delete string and runs the query
+ *
+ * @access public
+ * @param string the table to retrieve the results from
+ * @param mixed the where clause
+ * @return object
+ */
+ function delete($table = '', $where = '')
+ {
+ if ($table == '')
+ {
+ if ( ! isset($this->ar_from[0]))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_must_set_table');
+ }
+ return FALSE;
+ }
+
+ $table = $this->ar_from[0];
+ }
+
+ if ($where != '')
+ {
+ $this->where($where);
+ }
+
+ if (count($this->ar_where) == 0)
+ {
+ if ($this->debug)
+ {
+ return $this->display_error('db_del_must_use_where');
+ }
+ return FALSE;
+ }
+
+ $sql = $this->_delete($this->dbprefix.$table, $this->ar_where);
+
+ $this->_reset_write();
+ return $this->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Use Table - DEPRECATED
+ *
+ * @deprecated use $this->db->from instead
+ */
+ function use_table($table)
+ {
+ return $this->from($table);
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY - DEPRECATED
+ *
+ * @deprecated use $this->db->orderby() instead
+ */
+ function order_by($orderby, $direction = '')
+ {
+ return $this->orderby($orderby, $direction);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Tests whether the string has an SQL operator
+ *
+ * @access private
+ * @param string
+ * @return bool
+ */
+ function _has_operator($str)
+ {
+ $str = trim($str);
+ if ( ! preg_match("/(\s|<|>|!|=|is null|is not null)/i", $str))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile the SELECT statement
+ *
+ * Generates a query string based on which functions were used.
+ * Should not be called directly. The get() function calls it.
+ *
+ * @access private
+ * @return string
+ */
+ function _compile_select()
+ {
+ $sql = ( ! $this->ar_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';
+
+ $sql .= (count($this->ar_select) == 0) ? '*' : implode(', ', $this->ar_select);
+
+ if (count($this->ar_from) > 0)
+ {
+ $sql .= "\nFROM ";
+ $sql .= implode(', ', $this->ar_from);
+ }
+
+ if (count($this->ar_join) > 0)
+ {
+ $sql .= "\n";
+ $sql .= implode("\n", $this->ar_join);
+ }
+
+ if (count($this->ar_where) > 0 OR count($this->ar_like) > 0)
+ {
+ $sql .= "\nWHERE ";
+ }
+
+ $sql .= implode("\n", $this->ar_where);
+
+ if (count($this->ar_like) > 0)
+ {
+ if (count($this->ar_where) > 0)
+ {
+ $sql .= " AND ";
+ }
+
+ $sql .= implode("\n", $this->ar_like);
+ }
+
+ if (count($this->ar_groupby) > 0)
+ {
+ $sql .= "\nGROUP BY ";
+ $sql .= implode(', ', $this->ar_groupby);
+ }
+
+ if (count($this->ar_having) > 0)
+ {
+ $sql .= "\nHAVING ";
+ $sql .= implode("\n", $this->ar_having);
+ }
+
+ if (count($this->ar_orderby) > 0)
+ {
+ $sql .= "\nORDER BY ";
+ $sql .= implode(', ', $this->ar_orderby);
+
+ if ($this->ar_order !== FALSE)
+ {
+ $sql .= ($this->ar_order == 'desc') ? ' DESC' : ' ASC';
+ }
+ }
+
+ if (ctype_digit($this->ar_limit))
+ {
+ $sql .= "\n";
+ $sql = $this->_limit($sql, $this->ar_limit, $this->ar_offset);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Object to Array
+ *
+ * Takes an object as input and convers the class variables to array key/vals
+ *
+ * @access public
+ * @param object
+ * @return array
+ */
+ function _object_to_array($object)
+ {
+ if ( ! is_object($object))
+ {
+ return $object;
+ }
+
+ $array = array();
+ foreach (get_object_vars($object) as $key => $val)
+ {
+ if ( ! is_object($val) AND ! is_array($val))
+ {
+ $array[$key] = $val;
+ }
+ }
+
+ return $array;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Resets the active record values. Called by the get() function
+ *
+ * @access private
+ * @return void
+ */
+ function _reset_select()
+ {
+ $this->ar_select = array();
+ $this->ar_distinct = FALSE;
+ $this->ar_from = array();
+ $this->ar_join = array();
+ $this->ar_where = array();
+ $this->ar_like = array();
+ $this->ar_groupby = array();
+ $this->ar_having = array();
+ $this->ar_limit = FALSE;
+ $this->ar_offset = FALSE;
+ $this->ar_order = FALSE;
+ $this->ar_orderby = array();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Resets the active record "write" values.
+ *
+ * Called by the insert() or update() functions
+ *
+ * @access private
+ * @return void
+ */
+ function _reset_write()
+ {
+ $this->ar_set = array();
+ $this->ar_from = array();
+ $this->ar_where = array();
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_driver.php b/system/drivers/DB_driver.php
new file mode 100644
index 000000000..ed18d54e5
--- /dev/null
+++ b/system/drivers/DB_driver.php
@@ -0,0 +1,948 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Database Driver Class
+ *
+ * This is the platform-independent base DB implementation class.
+ * This class will not be called directly. Rather, the adapter
+ * class for the specific database will extend and instantiate it.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_driver {
+
+ var $username;
+ var $password;
+ var $hostname;
+ var $database;
+ var $dbdriver = 'mysql';
+ var $dbprefix = '';
+ var $pconnect = FALSE;
+ var $conn_id = FALSE;
+ var $result_id = FALSE;
+ var $db_debug = FALSE;
+ var $benchmark = 0;
+ var $query_count = 0;
+ var $bind_marker = '?';
+ var $queries = array();
+
+ /**
+ * Constructor. Accepts one parameter containing the database
+ * connection settings.
+ *
+ * Database settings can be passed as discreet
+ * parameters or as a data source name in the first
+ * parameter. DSNs must have this prototype:
+ * $dsn = 'driver://username:password@hostname/database';
+ *
+ * @param mixed. Can be an array or a DSN string
+ */
+ function CI_DB_driver($params)
+ {
+ $this->initialize($params);
+ log_message('debug', 'Database Driver Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize Database Settings
+ *
+ * @access private Called by the constructor
+ * @param mixed
+ * @return void
+ */
+ function initialize($params = '')
+ {
+ if (is_array($params))
+ {
+ foreach (array('hostname' => '', 'username' => '', 'password' => '', 'database' => '', 'dbdriver' => 'mysql', 'dbprefix' => '', 'pconnect' => FALSE, 'db_debug' => FALSE) as $key => $val)
+ {
+ $this->$key = ( ! isset($params[$key])) ? $val : $params[$key];
+ }
+ }
+ elseif (strpos($params, '://'))
+ {
+ if (FALSE === ($dsn = @parse_url($params)))
+ {
+ log_message('error', 'Invalid DB Connection String');
+
+ if ($this->debug)
+ {
+ return $this->display_error('db_invalid_connection_str');
+ }
+ return FALSE;
+ }
+
+ $this->hostname = ( ! isset($dsn['host'])) ? '' : rawurldecode($dsn['host']);
+ $this->username = ( ! isset($dsn['user'])) ? '' : rawurldecode($dsn['user']);
+ $this->password = ( ! isset($dsn['pass'])) ? '' : rawurldecode($dsn['pass']);
+ $this->database = ( ! isset($dsn['path'])) ? '' : rawurldecode(substr($dsn['path'], 1));
+ }
+
+ if ($this->pconnect == FALSE)
+ {
+ $this->conn_id = $this->db_connect();
+ }
+ else
+ {
+ $this->conn_id = $this->db_pconnect();
+ }
+
+ if ( ! $this->conn_id)
+ {
+ log_message('error', 'Unable to connect to the database');
+
+ if ($this->db_debug)
+ {
+ $this->display_error('db_unable_to_connect');
+ }
+ }
+ else
+ {
+ if ( ! $this->db_select())
+ {
+ log_message('error', 'Unable to select database: '.$this->database);
+
+ if ($this->db_debug)
+ {
+ $this->display_error('db_unable_to_select', $this->database);
+ }
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database Version Number. Returns a string containing the
+ * version of the database being used
+ *
+ * @access public
+ * @return string
+ */
+ function version()
+ {
+ if (FALSE === ($sql = $this->_version()))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_unsupported_function');
+ }
+ return FALSE;
+ }
+
+ $query = $this->query($sql);
+ $row = $query->row();
+ return $row->ver;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * Accepts an SQL string as input and returns a result object upon
+ * successful execution of a "read" type query. Returns boolean TRUE
+ * upon successful execution of a "write" type query. Returns boolean
+ * FALSE upon failure, and if the $db_debug variable is set to TRUE
+ * will raise an error.
+ *
+ * @access public
+ * @param string An SQL query string
+ * @param array An array of binding data
+ * @return mixed
+ */
+ function query($sql, $binds = FALSE)
+ {
+ if ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ if ($sql == '')
+ {
+ if ($this->db_debug)
+ {
+ log_message('error', 'Invalid query: '.$sql);
+ return $this->display_error('db_invalid_query');
+ }
+ return FALSE;
+ }
+
+ // Compile binds if needed
+ if ($binds !== FALSE)
+ {
+ $sql = $this->compile_binds($sql, $binds);
+ }
+
+ // Start the Query Timer
+ $time_start = list($sm, $ss) = explode(' ', microtime());
+
+ // Save the query for debugging
+ $this->queries[] = $sql;
+
+ // Run the Query
+ if (FALSE === ($this->result_id = $this->execute($sql, $this->conn_id)))
+ {
+ if ($this->db_debug)
+ {
+ log_message('error', 'Query error: '.$this->error_message());
+ return $this->display_error(
+ array(
+ 'Error Number: '.$this->error_number(),
+ $this->error_message(),
+ $sql
+ )
+ );
+ }
+
+ return FALSE;
+ }
+
+ // Stop and aggregate the query time results
+ $time_end = list($em, $es) = explode(' ', microtime());
+ $this->benchmark += ($em + $es) - ($sm + $ss);
+
+ // Increment the query counter
+ $this->query_count++;
+
+ // Was the query a "write" type?
+ // If so we'll return simply return true
+ if ($this->is_write_type($sql) === TRUE)
+ {
+ return TRUE;
+ }
+
+ // Instantiate and return the DB result object
+ $result = 'CI_DB_'.$this->dbdriver.'_result';
+
+ $RES = new $result();
+ $RES->conn_id = $this->conn_id;
+ $RES->db_debug = $this->db_debug;
+ $RES->result_id = $this->result_id;
+
+ return $RES;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Enables a native PHP function to be run, using a platform agnostic wrapper.
+ *
+ * @access public
+ * @param string the function name
+ * @param mixed any parameters needed by the function
+ * @return mixed
+ */
+ function call_function($function)
+ {
+ $driver = ($this->dbdriver == 'postgre') ? 'pg_' : $this->dbdriver.'_';
+
+ if (FALSE === strpos($driver, $function))
+ {
+ $function = $driver.$function;
+ }
+
+ if ( ! function_exists($function))
+ {
+ if ($this->debug)
+ {
+ return $this->display_error('db_unsupported_function');
+ }
+ return FALSE;
+ }
+ else
+ {
+ $args = (func_num_args() > 1) ? array_shift(func_get_args()) : null;
+
+ return call_user_func_array($function, $args);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Determines if a query is a "write" type.
+ *
+ * @access public
+ * @param string An SQL query string
+ * @return boolean
+ */
+ function is_write_type($sql)
+ {
+ if ( ! preg_match('/^\s*"?(INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|LOAD DATA|COPY|ALTER|GRANT|REVOKE|LOCK|UNLOCK)\s+/i', $sql))
+ {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Calculate the aggregate query elapsed time
+ *
+ * @access public
+ * @param intiger The number of decimal places
+ * @return integer
+ */
+ function elapsed_time($decimals = 6)
+ {
+ return number_format($this->benchmark, $decimals);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the total number of queries
+ *
+ * @access public
+ * @return integer
+ */
+ function total_queries()
+ {
+ return $this->query_count;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the last query that was executed
+ *
+ * @access public
+ * @return void
+ */
+ function last_query()
+ {
+ return end($this->queries);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Smart" Escape String
+ *
+ * Escapes data based on type
+ * Sets boolean and null types
+ *
+ * @access public
+ * @param string
+ * @return integer
+ */
+ function escape($str)
+ {
+ if ( ! ctype_digit($str)) // bug fix to ensure that numbers are not treated as strings.
+ {
+ switch (gettype($str))
+ {
+ case 'string' : $str = "'".$this->escape_str($str)."'";
+ break;
+ case 'boolean' : $str = ($str === FALSE) ? 0 : 1;
+ break;
+ default : $str = ($str === NULL) ? 'NULL' : $str;
+ break;
+ }
+ }
+
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an array of table names
+ *
+ * @access public
+ * @return array
+ */
+ function tables()
+ {
+ if (FALSE === ($sql = $this->_show_tables()))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_unsupported_function');
+ }
+ return FALSE;
+ }
+
+ $retval = array();
+ $query = $this->query($sql);
+
+ if ($query->num_rows() > 0)
+ {
+ foreach($query->result_array() as $row)
+ {
+ $retval[] = array_shift($row);
+ }
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Determine if a particular table exists
+ * @access public
+ * @return boolean
+ */
+ function table_exists($table_name)
+ {
+ return ( ! in_array($this->dbprefix.$table_name, $this->tables())) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch MySQL Field Names
+ *
+ * @access public
+ * @param string the table name
+ * @return array
+ */
+ function field_names($table = '')
+ {
+ if ($table == '')
+ {
+ if ($this->debug)
+ {
+ return $this->display_error('db_field_param_missing');
+ }
+ return FALSE;
+ }
+
+ if (FALSE === ($sql = $this->_show_columns($this->dbprefix.$table)))
+ {
+ if ($this->db_debug)
+ {
+ return $this->display_error('db_unsupported_function');
+ }
+ return FALSE;
+ }
+
+ $query = $this->query($sql);
+
+ $retval = array();
+ foreach($query->result_array() as $row)
+ {
+ if ($this->dbdriver == 'mssql' AND isset($row['COLUMN_NAME']))
+ {
+ $retval[] = $row['COLUMN_NAME'];
+ }
+ else
+ {
+ $retval[] = current($row);
+ }
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function field_data($table = '')
+ {
+ if ($table == '')
+ {
+ if ($this->debug)
+ {
+ return $this->display_error('db_field_param_missing');
+ }
+ return FALSE;
+ }
+
+ return $this->_field_data($this->dbprefix.$table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Primary
+ *
+ * Retrieves the primary key. It assumes that the row in the first
+ * position is the primary key
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function primary($table = '')
+ {
+ $fields = $this->field_names($table);
+
+ if ( ! is_array($fields))
+ {
+ return FALSE;
+ }
+
+ return current($fields);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile Bindings
+ *
+ * @access public
+ * @param string the sql statement
+ * @param array an array of bind data
+ * @return string
+ */
+ function compile_binds($sql, $binds)
+ {
+ if (FALSE === strpos($sql, $this->bind_marker))
+ {
+ return $sql;
+ }
+
+ if ( ! is_array($binds))
+ {
+ $binds = array($binds);
+ }
+
+ foreach ($binds as $val)
+ {
+ $val = $this->escape($val);
+
+ // Just in case the replacement string contains the bind
+ // character we'll temporarily replace it with a marker
+ $val = str_replace($this->bind_marker, '{%bind_marker%}', $val);
+ $sql = preg_replace("#".preg_quote($this->bind_marker)."#", $val, $sql, 1);
+ }
+
+ return str_replace('{%bind_marker%}', $this->bind_marker, $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate an insert string
+ *
+ * @access public
+ * @param string the table upon which the query will be performed
+ * @param array an associative array data of key/values
+ * @return string
+ */
+ function insert_string($table, $data)
+ {
+ $fields = array();
+ $values = array();
+
+ foreach($data as $key => $val)
+ {
+ $fields[] = $key;
+ $values[] = $this->escape($val);
+ }
+
+ return $this->_insert($this->dbprefix.$table, $fields, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate an update string
+ *
+ * @access public
+ * @param string the table upon which the query will be performed
+ * @param array an associative array data of key/values
+ * @param mixed the "where" statement
+ * @return string
+ */
+ function update_string($table, $data, $where)
+ {
+ if ($where == '')
+ return false;
+
+ $fields = array();
+ foreach($data as $key => $val)
+ {
+ $fields[$key] = $this->escape($val);
+ }
+
+ if ( ! is_array($where))
+ {
+ $dest = array($where);
+ }
+ else
+ {
+ $dest = array();
+ foreach ($where as $key => $val)
+ {
+ $prefix = (count($dest) == 0) ? '' : ' AND ';
+
+ if ($val != '')
+ {
+ if ( ! $this->_has_operator($key))
+ {
+ $key .= ' =';
+ }
+
+ $val = ' '.$this->escape($val);
+ }
+
+ $dest[] = $prefix.$key.$val;
+ }
+ }
+
+ return $this->_update($this->dbprefix.$table, $fields, $dest);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @return void
+ */
+ function close()
+ {
+ if (is_resource($this->conn_id))
+ {
+ $this->destroy($this->conn_id);
+ }
+ $this->conn_id = FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Display an error message
+ *
+ * @access public
+ * @param string the error message
+ * @param string any "swap" values
+ * @param boolean whether to localize the message
+ * @return string sends the application/errror_db.php template
+ */
+ function display_error($error = '', $swap = '', $native = FALSE)
+ {
+ $LANG = new CI_Language();
+ $LANG->load('db');
+
+ $heading = 'MySQL Error';
+
+ if ($native == TRUE)
+ {
+ $message = $error;
+ }
+ else
+ {
+ $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
+ }
+
+ if ( ! class_exists('CI_Exceptions'))
+ {
+ include_once(BASEPATH.'libraries/Exceptions.php');
+ }
+
+ $error = new CI_Exceptions();
+ echo $error->show_error('An Error Was Encountered', $message, 'error_db');
+ exit;
+
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field Data - old version - DEPRECATED
+ *
+ * @deprecated use $this->db->field_data() instead
+ */
+ function fields($table = '')
+ {
+ return $this->field_data($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Smart Escape String - old version - DEPRECATED
+ *
+ * @deprecated use $this->db->escape() instead
+ */
+ function smart_escape_str($str)
+ {
+ return $this->escape($str);
+ }
+}
+
+
+/**
+ * Database Result Class
+ *
+ * This is the platform-independent result class.
+ * This class will not be called directly. Rather, the adapter
+ * class for the specific database will extend and instantiate it.
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_result {
+
+ var $conn_id = FALSE;
+ var $result_id = FALSE;
+ var $db_debug = FALSE;
+ var $result_array = array();
+ var $result_object = array();
+ var $current_row = 0;
+
+ /**
+ * Query result. Acts as a wrapper function for the following functions.
+ *
+ * @access public
+ * @param string can be "object" or "array"
+ * @return mixed either a result object or array
+ */
+ function result($type = 'object')
+ {
+ return ($type == 'object') ? $this->result_object() : $this->result_array();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Query result. "object" version.
+ *
+ * @access public
+ * @return object
+ */
+ function result_object()
+ {
+ if (count($this->result_object) > 0)
+ {
+ return $this->result_object;
+ }
+
+ while ($row = $this->_fetch_object())
+ {
+ $this->result_object[] = $row;
+ }
+
+ if (count($this->result_object) == 0)
+ {
+ return FALSE;
+ }
+
+ return $this->result_object;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Query result. "array" version.
+ *
+ * @access public
+ * @return array
+ */
+ function result_array()
+ {
+ if (count($this->result_array) > 0)
+ {
+ return $this->result_array;
+ }
+
+ while ($row = $this->_fetch_assoc())
+ {
+ $this->result_array[] = $row;
+ }
+
+ if (count($this->result_array) == 0)
+ {
+ return FALSE;
+ }
+
+ return $this->result_array;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Query result. Acts as a wrapper function for the following functions.
+ *
+ * @access public
+ * @param string can be "object" or "array"
+ * @return mixed either a result object or array
+ */
+ function row($n = 0, $type = 'object')
+ {
+ return ($type == 'object') ? $this->row_object($n) : $this->row_array($n);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns a single result row - object version
+ *
+ * @access public
+ * @return object
+ */
+ function row_object($n = 0)
+ {
+ if (FALSE === ($result = $this->result_object()))
+ {
+ return FALSE;
+ }
+
+ if ($n != $this->current_row AND isset($result[$n]))
+ {
+ $this->current_row = $n;
+ }
+
+ return $result[$this->current_row];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns a single result row - array version
+ *
+ * @access public
+ * @return array
+ */
+ function row_array($n = 0)
+ {
+ if (FALSE === ($result = $this->result_array()))
+ {
+ return FALSE;
+ }
+
+ if ($n != $this->current_row AND isset($result[$n]))
+ {
+ $this->current_row = $n;
+ }
+
+ return $result[$this->current_row];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the "next" row
+ *
+ * @access public
+ * @return object
+ */
+ function next_row($type = 'object')
+ {
+ if (FALSE === ($result = $this->result($type)))
+ {
+ return FALSE;
+ }
+
+ if (isset($result[$this->current_row + 1]))
+ {
+ ++$this->current_row;
+ }
+
+ return $result[$this->current_row];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the "previous" row
+ *
+ * @access public
+ * @return object
+ */
+ function previous_row($type = 'object')
+ {
+ if (FALSE === ($result = $this->result($type)))
+ {
+ return FALSE;
+ }
+
+ if (isset($result[$this->current_row - 1]))
+ {
+ --$this->current_row;
+ }
+ return $result[$this->current_row];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the "first" row
+ *
+ * @access public
+ * @return object
+ */
+ function first_row($type = 'object')
+ {
+ if (FALSE === ($result = $this->result($type)))
+ {
+ return FALSE;
+ }
+ return $result[0];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns the "last" row
+ *
+ * @access public
+ * @return object
+ */
+ function last_row($type = 'object')
+ {
+ if (FALSE === ($result = $this->result($type)))
+ {
+ return FALSE;
+ }
+ return $result[count($result) -1];
+ }
+
+}
+
+
+
+/**
+ * Database Field Class
+ *
+ * This class will contain the field meta-data. It
+ * is called by one of the field result functions
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_field {
+ var $name;
+ var $type;
+ var $default;
+ var $max_length;
+ var $primary_key;
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_mssql.php b/system/drivers/DB_mssql.php
new file mode 100644
index 000000000..6156ec3c9
--- /dev/null
+++ b/system/drivers/DB_mssql.php
@@ -0,0 +1,472 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * MS SQL Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_mssql extends CI_DB {
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ return mssql_connect($this->hostname, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return mssql_pconnect($this->hostname, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ return @mssql_select_db($this->database, $this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @mssql_query($sql, $this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function &_prep_query($sql)
+ {
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function escape_str($str)
+ {
+ // MS SQL doesn't require escaping
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function destroy($conn_id)
+ {
+ mssql_close($conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @mssql_rows_affected($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ // Not supported in MS SQL?
+ return 0;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ return '0';
+
+ $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
+
+ if ($query->num_rows() == 0)
+ return '0';
+
+ $row = $query->row();
+ return $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access public
+ * @return string
+ */
+ function error_message()
+ {
+ // Are errros even supported in MS SQL?
+ return '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access public
+ * @return integer
+ */
+ function error_number()
+ {
+ // Are error numbers supported?
+ return '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape Table Name
+ *
+ * This function adds backticks if the table name has a period
+ * in it. Some DBs will get cranky unless periods are escaped
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function escape_table($table)
+ {
+ if (stristr($table, '.'))
+ {
+ $table = preg_replace("/\./", "`.`", $table);
+ }
+
+ return $table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ $sql = "SELECT TOP 1 FROM ".$this->escape_table($table);
+ $query = $this->query($sql);
+ return $query->field_data();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update($table, $values, $where)
+ {
+ foreach($values as $key => $val)
+ {
+ $valstr[] = $key." = ".$val;
+ }
+
+ return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @return string
+ */
+ function _delete($table, $where)
+ {
+ return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ return "SELECT version() AS ver";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access public
+ * @return string
+ */
+ function _show_tables()
+ {
+ return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show columnn query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _show_columns($table = '')
+ {
+ return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->escape_table($table)."'";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ $i = $limit + $offset;
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);
+ }
+
+}
+
+
+
+/**
+ * MS SQL Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_mssql_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @mssql_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @mssql_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+ while ($field = mssql_fetch_field($this->result_id))
+ {
+ $F = new CI_DB_field();
+ $F->name = $field->name;
+ $F->type = $field->type;
+ $F->max_length = $field->max_length;
+ $F->primary_key = 0;
+ $F->default = '';
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return mssql_fetch_assoc($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return mssql_fetch_object($this->result_id);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_mysql.php b/system/drivers/DB_mysql.php
new file mode 100644
index 000000000..18c080b21
--- /dev/null
+++ b/system/drivers/DB_mysql.php
@@ -0,0 +1,495 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * MySQL Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_mysql extends CI_DB {
+
+ /**
+ * Whether to use the MySQL "delete hack" which allows the number
+ * of affected rows to be shown. Uses a preg_replace when enabled,
+ * adding a bit more processing to all queries.
+ */
+ var $delete_hack = TRUE;
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ return mysql_connect($this->hostname, $this->username, $this->password, TRUE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return mysql_pconnect($this->hostname, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ return @mysql_select_db($this->database, $this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @mysql_query($sql, $this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function &_prep_query($sql)
+ {
+ // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
+ // the query so that it returns the number of affected rows
+ if ($this->delete_hack === TRUE)
+ {
+ if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
+ {
+ $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
+ }
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function escape_str($str)
+ {
+ if (get_magic_quotes_gpc())
+ {
+ $str = stripslashes($str);
+ }
+ return mysql_real_escape_string($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function destroy($conn_id)
+ {
+ mysql_close($conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @mysql_affected_rows($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return @mysql_insert_id($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ return '0';
+
+ $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
+
+ if ($query->num_rows() == 0)
+ return '0';
+
+ $row = $query->row();
+ return $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access public
+ * @return string
+ */
+ function error_message()
+ {
+ return mysql_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access public
+ * @return integer
+ */
+ function error_number()
+ {
+ return mysql_errno($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape Table Name
+ *
+ * This function adds backticks if the table name has a period
+ * in it. Some DBs will get cranky unless periods are escaped
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function escape_table($table)
+ {
+ if (stristr($table, '.'))
+ {
+ $table = preg_replace("/\./", "`.`", $table);
+ }
+
+ return $table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ $sql = "SELECT * FROM ".$this->escape_table($table)." LIMIT 1";
+ $query = $this->query($sql);
+ return $query->field_data();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update($table, $values, $where)
+ {
+ foreach($values as $key => $val)
+ {
+ $valstr[] = $key." = ".$val;
+ }
+
+ return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @return string
+ */
+ function _delete($table, $where)
+ {
+ return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ return "SELECT version() AS ver";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access public
+ * @return string
+ */
+ function _show_tables()
+ {
+ return "SHOW TABLES FROM `".$this->database."`";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show columnn query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _show_columns($table = '')
+ {
+ return "SHOW COLUMNS FROM ".$this->escape_table($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ if ($offset == 0)
+ {
+ $offset = '';
+ }
+ else
+ {
+ $offset .= ", ";
+ }
+
+ return $sql."LIMIT ".$offset.$limit;
+ }
+
+}
+
+
+/**
+ * MySQL Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_mysql_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @mysql_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @mysql_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+ while ($field = mysql_fetch_field($this->result_id))
+ {
+ $F = new CI_DB_field();
+ $F->name = $field->name;
+ $F->type = $field->type;
+ $F->default = $field->def;
+ $F->max_length = $field->max_length;
+ $F->primary_key = $field->primary_key;
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return mysql_fetch_assoc($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return mysql_fetch_object($this->result_id);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_mysqli.php b/system/drivers/DB_mysqli.php
new file mode 100644
index 000000000..f8cb19dbe
--- /dev/null
+++ b/system/drivers/DB_mysqli.php
@@ -0,0 +1,496 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * MySQLi Database Adapter Class - MySQLi only works with PHP 5
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_mysqli extends CI_DB {
+
+ /**
+ * Whether to use the MySQL "delete hack" which allows the number
+ * of affected rows to be shown. Uses a preg_replace when enabled,
+ * adding a bit more processing to all queries.
+ */
+ var $delete_hack = TRUE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ return mysqli_connect($this->hostname, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return $this->db_connect();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ return @mysqli_select_db($this->conn_id, $this->database);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @mysqli_query($this->conn_id, $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function &_prep_query($sql)
+ {
+ // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
+ // the query so that it returns the number of affected rows
+ if ($this->delete_hack === TRUE)
+ {
+ if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
+ {
+ $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
+ }
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function escape_str($str)
+ {
+ if (get_magic_quotes_gpc())
+ {
+ $str = stripslashes($str);
+ }
+ return mysqli_real_escape_string($this->conn_id, $str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function destroy($conn_id)
+ {
+ mysqli_close($conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @mysqli_affected_rows($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return @mysqli_insert_id($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ return '0';
+
+ $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
+
+ if ($query->num_rows() == 0)
+ return '0';
+
+ $row = $query->row();
+ return $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access public
+ * @return string
+ */
+ function error_message()
+ {
+ return mysqli_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access public
+ * @return integer
+ */
+ function error_number()
+ {
+ return mysqli_errno($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape Table Name
+ *
+ * This function adds backticks if the table name has a period
+ * in it. Some DBs will get cranky unless periods are escaped
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function escape_table($table)
+ {
+ if (stristr($table, '.'))
+ {
+ $table = preg_replace("/\./", "`.`", $table);
+ }
+
+ return $table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ $sql = "SELECT * FROM ".$this->escape_table($table)." LIMIT 1";
+ $query = $this->query($sql);
+ return $query->field_data();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update($table, $values, $where)
+ {
+ foreach($values as $key => $val)
+ {
+ $valstr[] = $key." = ".$val;
+ }
+
+ return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @return string
+ */
+ function _delete($table, $where)
+ {
+ return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ return "SELECT version() AS ver";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access public
+ * @return string
+ */
+ function _show_tables()
+ {
+ return "SHOW TABLES FROM `".$this->database."`";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show columnn query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _show_columns($table = '')
+ {
+ return "SHOW COLUMNS FROM ".$this->escape_table($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ $sql .= "LIMIT ".$limit;
+
+ if ($offset > 0)
+ {
+ $sql .= " OFFSET ".$offset;
+ }
+
+ return $sql;
+ }
+
+}
+
+
+
+/**
+ * MySQLi Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_mysqli_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @mysqli_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @mysqli_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+ while ($field = mysqli_fetch_field($this->result_id))
+ {
+ $F = new CI_DB_field();
+ $F->name = $field->name;
+ $F->type = $field->type;
+ $F->default = $field->def;
+ $F->max_length = $field->max_length;
+ $F->primary_key = 0;
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return mysqli_fetch_assoc($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return mysqli_fetch_object($this->result_id);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_odbc.php b/system/drivers/DB_odbc.php
new file mode 100644
index 000000000..fac44904b
--- /dev/null
+++ b/system/drivers/DB_odbc.php
@@ -0,0 +1,468 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * ODBC Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_odbc extends CI_DB {
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ return odbc_connect($this->database, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return odbc_pconnect($this->database, $this->username, $this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ // Not needed for ODBC
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @odbc_exec($this->conn_id, $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function &_prep_query($sql)
+ {
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function escape_str($str)
+ {
+ // ODBC doesn't require escaping
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function destroy($conn_id)
+ {
+ odbc_close($conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @odbc_num_rows($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return @odbc_insert_id($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ return '0';
+
+ $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
+
+ if ($query->num_rows() == 0)
+ return '0';
+
+ $row = $query->row();
+ return $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access public
+ * @return string
+ */
+ function error_message()
+ {
+ return odbc_errormsg($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access public
+ * @return integer
+ */
+ function error_number()
+ {
+ return odbc_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape Table Name
+ *
+ * This function adds backticks if the table name has a period
+ * in it. Some DBs will get cranky unless periods are escaped
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function escape_table($table)
+ {
+ if (stristr($table, '.'))
+ {
+ $table = preg_replace("/\./", "`.`", $table);
+ }
+
+ return $table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ $sql = "SELECT TOP 1 FROM ".$this->escape_table($table);
+ $query = $this->query($sql);
+ return $query->field_data();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update($table, $values, $where)
+ {
+ foreach($values as $key => $val)
+ {
+ $valstr[] = $key." = ".$val;
+ }
+
+ return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @return string
+ */
+ function _delete($table, $where)
+ {
+ return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ return "SELECT version() AS ver";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access public
+ * @return string
+ */
+ function _show_tables()
+ {
+ return "SHOW TABLES FROM `".$this->database."`";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show columnn query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _show_columns($table = '')
+ {
+ return "SHOW COLUMNS FROM ".$this->escape_table($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ // Does ODBC doesn't use the LIMIT clause?
+ return $sql;
+ }
+
+}
+
+
+/**
+ * ODBC Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_odbc_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @odbc_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @odbc_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+ for ($i = 0; $i < $this->num_fields(); $i++)
+ {
+ $F = new CI_DB_field();
+ $F->name = odbc_field_name($this->result_id, $i);
+ $F->type = odbc_field_type($this->result_id, $i);
+ $F->max_length = odbc_field_len($this->result_id, $i);
+ $F->primary_key = 0;
+ $F->default = '';
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return odbc_fetch_array($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return odbc_fetch_object($this->result_id);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_postgre.php b/system/drivers/DB_postgre.php
new file mode 100644
index 000000000..01d4b3df0
--- /dev/null
+++ b/system/drivers/DB_postgre.php
@@ -0,0 +1,476 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Postgre Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_postgre extends CI_DB {
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ return pg_connect("host=".$this->hostname." dbname=".$this->database." user=".$this->username." password=".$this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return pg_pconnect("host=".$this->hostname." dbname=".$this->database." user=".$this->username." password=".$this->password);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ // Not needed for Postgre so we'll return TRUE
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @pg_query($this->conn_id, $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function &_prep_query($sql)
+ {
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function escape_str($str)
+ {
+ if (get_magic_quotes_gpc())
+ {
+ $str = stripslashes($str);
+ }
+ return pg_escape_string($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function destroy($conn_id)
+ {
+ pg_close($conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @pg_affected_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return pg_last_oid($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ return '0';
+
+ $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
+
+ if ($query->num_rows() == 0)
+ return '0';
+
+ $row = $query->row();
+ return $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access public
+ * @return string
+ */
+ function error_message()
+ {
+ return pg_last_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access public
+ * @return integer
+ */
+ function error_number()
+ {
+ return '';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape Table Name
+ *
+ * This function adds backticks if the table name has a period
+ * in it. Some DBs will get cranky unless periods are escaped
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function escape_table($table)
+ {
+ if (stristr($table, '.'))
+ {
+ $table = preg_replace("/\./", "`.`", $table);
+ }
+
+ return $table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ $sql = "SELECT * FROM ".$this->escape_table($table)." LIMIT 1";
+ $query = $this->query($sql);
+ return $query->field_data();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update($table, $values, $where)
+ {
+ foreach($values as $key => $val)
+ {
+ $valstr[] = $key." = ".$val;
+ }
+
+ return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @return string
+ */
+ function _delete($table, $where)
+ {
+ return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ return "SELECT version() AS ver";
+ }
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access public
+ * @return string
+ */
+ function _show_tables()
+ {
+ return "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show columnn query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _show_columns($table = '')
+ {
+ return "SELECT column_name FROM information_schema.columns WHERE table_name ='".$this->escape_table($table)."'";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ $sql .= "LIMIT ".$limit;
+
+ if ($offset > 0)
+ {
+ $sql .= " OFFSET ".$offset;
+ }
+
+ return $sql;
+ }
+
+}
+
+
+
+/**
+ * Postgres Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_postgre_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @pg_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @pg_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+ for ($i = 0; $i < $this->num_fields(); $i++)
+ {
+ $F = new CI_DB_field();
+ $F->name = pg_field_name($this->result_id, $i);
+ $F->type = pg_field_type($this->result_id, $i);
+ $F->max_length = pg_field_size($this->result_id, $i);
+ $F->primary_key = 0;
+ $F->default = '';
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return pg_fetch_assoc($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return pg_fetch_object($this->result_id);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/DB_sqlite.php b/system/drivers/DB_sqlite.php
new file mode 100644
index 000000000..6428dd5bb
--- /dev/null
+++ b/system/drivers/DB_sqlite.php
@@ -0,0 +1,501 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+
+
+/**
+ * SQLite Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_sqlite extends CI_DB {
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ if ( ! $conn_id = sqlite_open($this->database, 0666, $error))
+ {
+ log_message('error', $error);
+
+ if ($this->db_debug)
+ {
+ $this->display_error($error, '', TRUE);
+ }
+ }
+
+ return $conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ if ( ! $conn_id = sqlite_popen($this->database, 0666, $error))
+ {
+ log_message('error', $error);
+
+ if ($this->db_debug)
+ {
+ $this->display_error($error, '', TRUE);
+ }
+ }
+
+ return $conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @sqlite_query($this->conn_id, $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function &_prep_query($sql)
+ {
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function escape_str($str)
+ {
+ if (get_magic_quotes_gpc())
+ {
+ $str = stripslashes($str);
+ }
+ return sqlite_escape_string($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function destroy($conn_id)
+ {
+ sqlite_close($conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return sqlite_changes($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return @sqlite_last_insert_rowid($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified database
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ return '0';
+
+ $query = $this->query("SELECT COUNT(*) AS numrows FROM `".$this->dbprefix.$table."`");
+
+ if ($query->num_rows() == 0)
+ return '0';
+
+ $row = $query->row();
+ return $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access public
+ * @return string
+ */
+ function error_message()
+ {
+ return sqlite_error_string(sqlite_last_error($this->conn_id));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access public
+ * @return integer
+ */
+ function error_number()
+ {
+ return sqlite_last_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function version()
+ {
+ return sqlite_libversion();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape Table Name
+ *
+ * This function adds backticks if the table name has a period
+ * in it. Some DBs will get cranky unless periods are escaped
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function escape_table($table)
+ {
+ if (stristr($table, '.'))
+ {
+ $table = preg_replace("/\./", "`.`", $table);
+ }
+
+ return $table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ $sql = "SELECT * FROM ".$this->escape_table($table)." LIMIT 1";
+ $query = $this->query($sql);
+ return $query->field_data();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$this->escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update($table, $values, $where)
+ {
+ foreach($values as $key => $val)
+ {
+ $valstr[] = $key." = ".$val;
+ }
+
+ return "UPDATE ".$this->escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @return string
+ */
+ function _delete($table, $where)
+ {
+ return "DELETE FROM ".$this->escape_table($table)." WHERE ".implode(" ", $where);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access public
+ * @return string
+ */
+ function _show_tables()
+ {
+ return "SELECT name from sqlite_master WHERE type='table'";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show columnn query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _show_columns($table = '')
+ {
+ // Not supported
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ if ($offset == 0)
+ {
+ $offset = '';
+ }
+ else
+ {
+ $offset .= ", ";
+ }
+
+ return $sql."LIMIT ".$offset.$limit;
+ }
+
+}
+
+
+/**
+ * SQLite Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/database/
+ */
+class CI_DB_sqlite_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @sqlite_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @sqlite_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+ for ($i = 0; $i < $this->num_fields(); $i++)
+ {
+ $F = new CI_DB_field();
+ $F->name = sqlite_field_name($this->result_id, $i);
+ $F->type = 'varchar';
+ $F->max_length = 0;
+ $F->primary_key = 0;
+ $F->default = '';
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return sqlite_fetch_array($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return sqlite_fetch_object($this->result_id);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/system/drivers/index.html b/system/drivers/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/drivers/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/fonts/index.html b/system/fonts/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/fonts/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/fonts/texb.ttf b/system/fonts/texb.ttf
new file mode 100644
index 000000000..383c88b86
--- /dev/null
+++ b/system/fonts/texb.ttf
Binary files differ
diff --git a/system/helpers/array_helper.php b/system/helpers/array_helper.php
new file mode 100644
index 000000000..cccde1fc4
--- /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 000000000..24e243ddd
--- /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 000000000..2a3d50859
--- /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 000000000..69eb13d11
--- /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 000000000..93bddb029
--- /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 000000000..f82ad01a0
--- /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 000000000..1c97dda53
--- /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 000000000..5a1f5d6ae
--- /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 000000000..918e4ae90
--- /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 000000000..d5a3591f9
--- /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 000000000..15b5573bf
--- /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 000000000..6a5495239
--- /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 000000000..d2d2a5985
--- /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 000000000..ee3fc289b
--- /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
diff --git a/system/init/index.html b/system/init/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/init/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/init/init_calendar.php b/system/init/init_calendar.php
new file mode 100644
index 000000000..5cf663725
--- /dev/null
+++ b/system/init/init_calendar.php
@@ -0,0 +1,19 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates calendar class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Calendar'))
+{
+ require_once(BASEPATH.'libraries/Calendar'.EXT);
+}
+
+$obj =& get_instance();
+
+$obj->calendar = new CI_Calendar();
+$obj->ci_is_loaded[] = 'calendar';
+
+?> \ No newline at end of file
diff --git a/system/init/init_email.php b/system/init/init_email.php
new file mode 100644
index 000000000..6782310ef
--- /dev/null
+++ b/system/init/init_email.php
@@ -0,0 +1,24 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates email class
+ *
+ * @access private called by the app controller
+ */
+
+$config = array();
+if (file_exists(APPPATH.'config/email'.EXT))
+{
+ include_once(APPPATH.'config/email'.EXT);
+}
+
+if ( ! class_exists('CI_Email'))
+{
+ require_once(BASEPATH.'libraries/Email'.EXT);
+}
+
+$obj =& get_instance();
+$obj->email = new CI_Email($config);
+$obj->ci_is_loaded[] = 'email';
+
+?> \ No newline at end of file
diff --git a/system/init/init_encrypt.php b/system/init/init_encrypt.php
new file mode 100644
index 000000000..5eae533ba
--- /dev/null
+++ b/system/init/init_encrypt.php
@@ -0,0 +1,18 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates encryption class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Encrypt'))
+{
+ require_once(BASEPATH.'libraries/Encrypt'.EXT);
+}
+
+$obj =& get_instance();
+$obj->encrypt = new CI_Encrypt();
+$obj->ci_is_loaded[] = 'encrypt';
+
+?> \ No newline at end of file
diff --git a/system/init/init_image_lib.php b/system/init/init_image_lib.php
new file mode 100644
index 000000000..dcd702f0d
--- /dev/null
+++ b/system/init/init_image_lib.php
@@ -0,0 +1,24 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates image manipulation class
+ *
+ * @access private called by the app controller
+ */
+
+$config = array();
+if (file_exists(APPPATH.'config/image_lib'.EXT))
+{
+ include_once(APPPATH.'config/image_lib'.EXT);
+}
+
+if ( ! class_exists('CI_Image_lib'))
+{
+ require_once(BASEPATH.'libraries/Image_lib'.EXT);
+}
+
+$obj =& get_instance();
+$obj->image_lib = new CI_Image_lib($config);
+$obj->ci_is_loaded[] = 'image_lib';
+
+?> \ No newline at end of file
diff --git a/system/init/init_pagination.php b/system/init/init_pagination.php
new file mode 100644
index 000000000..3a7d9361c
--- /dev/null
+++ b/system/init/init_pagination.php
@@ -0,0 +1,24 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates pagination class
+ *
+ * @access private called by the app controller
+ */
+
+$config = array();
+if ( ! class_exists('CI_Pagination'))
+{
+ if (file_exists(APPPATH.'config/pagination'.EXT))
+ {
+ include_once(APPPATH.'config/pagination'.EXT);
+ }
+
+ require_once(BASEPATH.'libraries/Pagination'.EXT);
+}
+
+$obj =& get_instance();
+$obj->pagination = new CI_Pagination($config);
+$obj->ci_is_loaded[] = 'pagination';
+
+?> \ No newline at end of file
diff --git a/system/init/init_parser.php b/system/init/init_parser.php
new file mode 100644
index 000000000..17824b566
--- /dev/null
+++ b/system/init/init_parser.php
@@ -0,0 +1,19 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates parser class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Parser'))
+{
+ require_once(BASEPATH.'libraries/Parser'.EXT);
+}
+
+$obj =& get_instance();
+$obj->parser = new CI_Parser();
+$obj->ci_is_loaded[] = 'parser';
+
+
+?> \ No newline at end of file
diff --git a/system/init/init_session.php b/system/init/init_session.php
new file mode 100644
index 000000000..cf493e53c
--- /dev/null
+++ b/system/init/init_session.php
@@ -0,0 +1,18 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates session class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Session'))
+{
+ require_once(BASEPATH.'libraries/Session'.EXT);
+}
+
+$obj =& get_instance();
+$obj->session = new CI_Session();
+$obj->ci_is_loaded[] = 'session';
+
+?> \ No newline at end of file
diff --git a/system/init/init_trackback.php b/system/init/init_trackback.php
new file mode 100644
index 000000000..6a3778bcc
--- /dev/null
+++ b/system/init/init_trackback.php
@@ -0,0 +1,18 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates trackback class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Trackback'))
+{
+ require_once(BASEPATH.'libraries/Trackback'.EXT);
+}
+
+$obj =& get_instance();
+$obj->trackback = new CI_Trackback();
+$obj->ci_is_loaded[] = 'trackback';
+
+?> \ No newline at end of file
diff --git a/system/init/init_unit_test.php b/system/init/init_unit_test.php
new file mode 100644
index 000000000..61d5350b6
--- /dev/null
+++ b/system/init/init_unit_test.php
@@ -0,0 +1,18 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates unit testing class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Unit_test'))
+{
+ require_once(BASEPATH.'libraries/Unit_test'.EXT);
+}
+
+$obj =& get_instance();
+$obj->unit = new CI_Unit_test();
+$obj->ci_is_loaded[] = 'unit';
+
+?> \ No newline at end of file
diff --git a/system/init/init_upload.php b/system/init/init_upload.php
new file mode 100644
index 000000000..495975c7a
--- /dev/null
+++ b/system/init/init_upload.php
@@ -0,0 +1,24 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates file uploading class
+ *
+ * @access private called by the app controller
+ */
+
+$config = array();
+if ( ! class_exists('CI_Upload'))
+{
+ if (file_exists(APPPATH.'config/upload'.EXT))
+ {
+ include_once(APPPATH.'config/upload'.EXT);
+ }
+
+ require_once(BASEPATH.'libraries/Upload'.EXT);
+}
+
+$obj =& get_instance();
+$obj->upload = new CI_Upload($config);
+$obj->ci_is_loaded[] = 'upload';
+
+?> \ No newline at end of file
diff --git a/system/init/init_validation.php b/system/init/init_validation.php
new file mode 100644
index 000000000..a320c3e5b
--- /dev/null
+++ b/system/init/init_validation.php
@@ -0,0 +1,18 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates validation class
+ *
+ * @access private called by the app controller
+ */
+
+if ( ! class_exists('CI_Validation'))
+{
+ require_once(BASEPATH.'libraries/Validation'.EXT);
+}
+
+$obj =& get_instance();
+$obj->validation = new CI_Validation();
+$obj->ci_is_loaded[] = 'validation';
+
+?> \ No newline at end of file
diff --git a/system/init/init_xmlrpc.php b/system/init/init_xmlrpc.php
new file mode 100644
index 000000000..b75e9aad7
--- /dev/null
+++ b/system/init/init_xmlrpc.php
@@ -0,0 +1,24 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates XML-RPC request class
+ *
+ * @access private called by the app controller
+ */
+
+$config = array();
+if (file_exists(APPPATH.'config/xmlrpc'.EXT))
+{
+ include_once(APPPATH.'config/xmlrpc'.EXT);
+}
+
+if ( ! class_exists('CI_XML_RPC'))
+{
+ require_once(BASEPATH.'libraries/Xmlrpc'.EXT);
+}
+
+$obj =& get_instance();
+$obj->xmlrpc = new CI_XML_RPC($config);
+$obj->ci_is_loaded[] = 'xmlrpc';
+
+?> \ No newline at end of file
diff --git a/system/init/init_xmlrpcs.php b/system/init/init_xmlrpcs.php
new file mode 100644
index 000000000..7566e3826
--- /dev/null
+++ b/system/init/init_xmlrpcs.php
@@ -0,0 +1,27 @@
+<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * Loads and instantiates XML-RPC server class
+ *
+ * @access private called by the app controller
+ */
+
+$config = array();
+if (file_exists(APPPATH.'config/xmlrpcs'.EXT))
+{
+ include_once(APPPATH.'config/xmlrpcs'.EXT);
+}
+
+if ( ! class_exists('CI_XML_RPC_Server'))
+{
+ require_once(BASEPATH.'libraries/Xmlrpc'.EXT);
+ require_once(BASEPATH.'libraries/Xmlrpcs'.EXT);
+}
+
+$obj =& get_instance();
+$obj->xmlrpc = new CI_XML_RPC();
+$obj->xmlrpcs = new CI_XML_RPC_Server($config);
+$obj->ci_is_loaded[] = 'xmlrpc';
+$obj->ci_is_loaded[] = 'xmlrpcs';
+
+?> \ No newline at end of file
diff --git a/system/language/english/calendar_lang.php b/system/language/english/calendar_lang.php
new file mode 100644
index 000000000..4a399af8b
--- /dev/null
+++ b/system/language/english/calendar_lang.php
@@ -0,0 +1,49 @@
+<?php
+
+$lang['cal_s'] = "Su";
+$lang['cal_mo'] = "Mo";
+$lang['cal_tu'] = "Tu";
+$lang['cal_we'] = "We";
+$lang['cal_th'] = "Th";
+$lang['cal_fr'] = "Fr";
+$lang['cal_sa'] = "Sa";
+$lang['cal_sun'] = "Sun";
+$lang['cal_mon'] = "Mon";
+$lang['cal_tue'] = "Tue";
+$lang['cal_wed'] = "Wed";
+$lang['cal_thu'] = "Thu";
+$lang['cal_fri'] = "Fri";
+$lang['cal_sat'] = "Sat";
+$lang['cal_sunday'] = "Sunday";
+$lang['cal_monday'] = "Monday";
+$lang['cal_tuesday'] = "Tuesday";
+$lang['cal_wednesday'] = "Wednesday";
+$lang['cal_thursday'] = "Thursday";
+$lang['cal_friday'] = "Friday";
+$lang['cal_saturday'] = "Saturday";
+$lang['cal_jan'] = "Jan";
+$lang['cal_feb'] = "Feb";
+$lang['cal_mar'] = "Mar";
+$lang['cal_apr'] = "Apr";
+$lang['cal_may'] = "May";
+$lang['cal_jun'] = "Jun";
+$lang['cal_jul'] = "Jul";
+$lang['cal_aug'] = "Aug";
+$lang['cal_sep'] = "Sep";
+$lang['cal_oct'] = "Oct";
+$lang['cal_nov'] = "Nov";
+$lang['cal_dec'] = "Dec";
+$lang['cal_january'] = "January";
+$lang['cal_february'] = "February";
+$lang['cal_march'] = "March";
+$lang['cal_april'] = "April";
+$lang['cal_mayl'] = "May";
+$lang['cal_june'] = "June";
+$lang['cal_july'] = "July";
+$lang['cal_august'] = "August";
+$lang['cal_september'] = "September";
+$lang['cal_october'] = "October";
+$lang['cal_november'] = "November";
+$lang['cal_december'] = "December";
+
+?> \ No newline at end of file
diff --git a/system/language/english/date_lang.php b/system/language/english/date_lang.php
new file mode 100644
index 000000000..02ebe7386
--- /dev/null
+++ b/system/language/english/date_lang.php
@@ -0,0 +1,49 @@
+<?php
+
+$lang['date_year'] = "Year";
+$lang['date_years'] = "Years";
+$lang['date_month'] = "Month";
+$lang['date_months'] = "Months";
+$lang['date_week'] = "Week";
+$lang['date_weeks'] = "Weeks";
+$lang['date_day'] = "Day";
+$lang['date_days'] = "Days";
+$lang['date_hour'] = "Hour";
+$lang['date_hours'] = "Hours";
+$lang['date_minute'] = "Minute";
+$lang['date_minutes'] = "Minutes";
+$lang['date_second'] = "Second";
+$lang['date_seconds'] = "Seconds";
+
+$lang['UM12'] = "(UTC - 12:00) Enitwetok, Kwajalien";
+$lang['UM11'] = "(UTC - 11:00) Nome, Midway Island, Samoa";
+$lang['UM10'] = "(UTC - 10:00) Hawaii";
+$lang['UM9'] = "(UTC - 9:00) Alaska";
+$lang['UM8'] = "(UTC - 8:00) Pacific Time";
+$lang['UM7'] = "(UTC - 7:00) Mountain Time";
+$lang['UM6'] = "(UTC - 6:00) Central Time, Mexico City";
+$lang['UM5'] = "(UTC - 5:00) Eastern Time, Bogota, Lima, Quito";
+$lang['UM4'] = "(UTC - 4:00) Atlantic Time, Caracas, La Paz";
+$lang['UM25'] = "(UTC - 3:30) Newfoundland";
+$lang['UM3'] = "(UTC - 3:00) Brazil, Buenos Aires, Georgetown, Falkland Is.";
+$lang['UM2'] = "(UTC - 2:00) Mid-Atlantic, Ascention Is., St Helena";
+$lang['UM1'] = "(UTC - 1:00) Azores, Cape Verde Islands";
+$lang['UTC'] = "(UTC) Casablanca, Dublin, Edinburgh, London, Lisbon, Monrovia";
+$lang['UP1'] = "(UTC + 1:00) Berlin, Brussels, Copenhagen, Madrid, Paris, Rome";
+$lang['UP2'] = "(UTC + 2:00) Kaliningrad, South Africa, Warsaw";
+$lang['UP3'] = "(UTC + 3:00) Baghdad, Riyadh, Moscow, Nairobi";
+$lang['UP25'] = "(UTC + 3:30) Tehran";
+$lang['UP4'] = "(UTC + 4:00) Adu Dhabi, Baku, Muscat, Tbilisi";
+$lang['UP35'] = "(UTC + 4:30) Kabul";
+$lang['UP5'] = "(UTC + 5:00) Islamabad, Karachi, Tashkent";
+$lang['UP45'] = "(UTC + 5:30) Bombay, Calcutta, Madras, New Delhi";
+$lang['UP6'] = "(UTC + 6:00) Almaty, Colomba, Dhakra";
+$lang['UP7'] = "(UTC + 7:00) Bangkok, Hanoi, Jakarta";
+$lang['UP8'] = "(UTC + 8:00) Beijing, Hong Kong, Perth, Singapore, Taipei";
+$lang['UP9'] = "(UTC + 9:00) Osaka, Sapporo, Seoul, Tokyo, Yakutsk";
+$lang['UP85'] = "(UTC + 9:30) Adelaide, Darwin";
+$lang['UP10'] = "(UTC + 10:00) Melbourne, Papua New Guinea, Sydney, Vladivostok";
+$lang['UP11'] = "(UTC + 11:00) Magadan, New Caledonia, Solomon Islands";
+$lang['UP12'] = "(UTC + 12:00) Auckland, Wellington, Fiji, Marshall Island";
+
+?> \ No newline at end of file
diff --git a/system/language/english/db_lang.php b/system/language/english/db_lang.php
new file mode 100644
index 000000000..b210b61ba
--- /dev/null
+++ b/system/language/english/db_lang.php
@@ -0,0 +1,15 @@
+<?php
+
+$lang['db_invalid_connection_str'] = 'Unable to determine the database settings based on the connection string you submitted.';
+$lang['db_unable_to_connect'] = 'Unable to connect to your database server using the provided settings.';
+$lang['db_unable_to_select'] = 'Unable to select the specified database: %s';
+$lang['db_unable_to_create'] = 'Unable to create the specified database: %s';
+$lang['db_invalid_query'] = 'The query you submitted is not valid.';
+$lang['db_must_set_table'] = 'You must set the database table to be used with your query.';
+$lang['db_must_use_set'] = 'You must set use the "set" method to update an entry.';
+$lang['db_must_use_where'] = 'Updates are not allowed unless they contain a "where" clause.';
+$lang['db_del_must_use_where'] = 'Deletes are not allowed unless they contain a "where" clause.';
+$lang['db_field_param_missing'] = 'To fetch fields requires the name of the table as a parameter.';
+$lang['db_unsupported_function'] = 'This feature is not available for the database you are using.';
+
+?> \ No newline at end of file
diff --git a/system/language/english/email_lang.php b/system/language/english/email_lang.php
new file mode 100644
index 000000000..430ae4ab2
--- /dev/null
+++ b/system/language/english/email_lang.php
@@ -0,0 +1,21 @@
+<?php
+
+$lang['email_must_be_array'] = "The email validation method must be passed an array.";
+$lang['email_invalid_address'] = "Invalid email address: %s";
+$lang['email_attachment_missing'] = "Unable to locate the following email attachment: %s";
+$lang['email_attachment_unredable'] = "Unable to open this attachment: %s";
+$lang['email_no_recipients'] = "You must include recipients: To, Cc, or Bcc";
+$lang['email_send_failure_phpmail'] = "Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.";
+$lang['email_send_failure_sendmail'] = "Unable to send email using PHP Sendmail. Your server might not be configured to send mail using this method.";
+$lang['email_send_failure_smtp'] = "Unable to send email using PHP SMTP. Your server might not be configured to send mail using this method.";
+$lang['email_sent'] = "Your message has been successfully sent using the following protocol: %s";
+$lang['email_no_socket'] = "Unable to open a socket to Sendmail. Please check settings.";
+$lang['email_no_hostname'] = "You did not specify a SMTP hostname";
+$lang['email_smtp_error'] = "The following SMTP error was encountered: %s";
+$lang['email_no_smtp_unpw'] = "Error: You must assign a SMTP username and password.";
+$lang['email_filed_smtp_login'] = "Failed to send AUTH LOGIN command. Error: %s";
+$lang['email_smtp_auth_un'] = "Failed to authenticate username. Error: %s";
+$lang['email_smtp_auth_pw'] = "Failed to authenticate password. Error: %s";
+$lang['email_smtp_data_failure'] = "Unable to send data: %s";
+
+?> \ No newline at end of file
diff --git a/system/language/english/imglib_lang.php b/system/language/english/imglib_lang.php
new file mode 100644
index 000000000..68c5804a3
--- /dev/null
+++ b/system/language/english/imglib_lang.php
@@ -0,0 +1,21 @@
+<?php
+
+$lang['imglib_source_image_required'] = "You must specify a source image in your preferences.";
+$lang['imglib_gd_required'] = "The GD image library is required for this feature.";
+$lang['imglib_gd_required_for_props'] = "Your server must suppor the GD image library in order to determine the image properties";
+$lang['imglib_unsupported_imagecreate'] = "Your server does not support the GD function required to process this type of image.";
+$lang['imglib_gif_not_supported'] = "GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.";
+$lang['imglib_jpg_not_supported'] = "JPG images are not supported";
+$lang['imglib_png_not_supported'] = "PNG images are not supported";
+$lang['imglib_jpg_or_png_required'] = "The image resize protocol specified in your preferences only works with JPEG or PNG image types.";
+$lang['imglib_copy_error'] = "An error was encountered while attempting to replace the file. Please make sure your file directory is writable.";
+$lang['imglib_rotate_unsupported'] = "Image rotation does not appear to be supported by your server.";
+$lang['imglib_libpath_invalid'] = "The path to your image library is not correct. Please set the correct path in your image preferences.";
+$lang['imglib_image_process_failed'] = "Image processing failed. Please verify that your server supports the chosen protocol and that the path to your image library is correct.";
+$lang['imglib_rotation_angle_required'] = "An angle of rotation is required to rotate the image.";
+$lang['imglib_writing_failed_gif'] = "GIF image ";
+$lang['imglib_invalid_path'] = "The path to the image is not correct";
+$lang['imglib_copy_failed'] = "The image copy routine failed.";
+$lang['imglib_missing_font'] = "Unable to find a font to use.";
+
+?> \ No newline at end of file
diff --git a/system/language/english/index.html b/system/language/english/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/language/english/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/language/english/scaffolding_lang.php b/system/language/english/scaffolding_lang.php
new file mode 100644
index 000000000..96fe167e5
--- /dev/null
+++ b/system/language/english/scaffolding_lang.php
@@ -0,0 +1,15 @@
+<?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:';
+
+?> \ No newline at end of file
diff --git a/system/language/english/unit_test_lang.php b/system/language/english/unit_test_lang.php
new file mode 100644
index 000000000..b64ea6de9
--- /dev/null
+++ b/system/language/english/unit_test_lang.php
@@ -0,0 +1,22 @@
+<?php
+
+$lang['ut_test_name'] = 'Test Name';
+$lang['ut_test_datatype'] = 'Test Datatype ';
+$lang['ut_res_datatype'] = 'Expected Datatype';
+$lang['ut_result'] = 'Result';
+$lang['ut_undefined'] = 'Undefined Test Name';
+$lang['ut_file'] = 'File Name';
+$lang['ut_line'] = 'Line Number';
+$lang['ut_passed'] = 'Passed';
+$lang['ut_failed'] = 'Failed';
+$lang['ut_boolean'] = 'Boolean';
+$lang['ut_integer'] = 'Integer';
+$lang['ut_double'] = 'Float';
+$lang['ut_float'] = 'Floag';
+$lang['ut_string'] = 'String';
+$lang['ut_array'] = 'Array';
+$lang['ut_object'] = 'Object';
+$lang['ut_resource'] = 'Resource';
+$lang['ut_null'] = 'Null'
+
+?> \ No newline at end of file
diff --git a/system/language/english/upload_lang.php b/system/language/english/upload_lang.php
new file mode 100644
index 000000000..6837c8acf
--- /dev/null
+++ b/system/language/english/upload_lang.php
@@ -0,0 +1,16 @@
+<?php
+
+$lang['upload_userfile_not_set'] = "Unable to find a post variable called userfile.";
+$lang['upload_file_exceeds_limit'] = "The uploaded file exceeds the maximum allowed size in your PHP configuration file";
+$lang['upload_file_partial'] = "The file was only partially uploaded";
+$lang['upload_no_file_selected'] = "You did not select a file to upload";
+$lang['upload_invalid_filetype'] = "The filetype you are attempting to upload is not allowed";
+$lang['upload_invalid_filesize'] = "The file you are attempting to upload is larger than the permitted size";
+$lang['upload_invalid_dimensions'] = "The image you are attempting to upload exceedes the maximum height or width";
+$lang['upload_destination_error'] = "A problem was encountered while attempting to move the uploaded file to the final destination.";
+$lang['upload_no_filepath'] = "The upload path does not appear to be valid.";
+$lang['upload_no_file_types'] = "You have not specified any allowed file types.";
+$lang['upload_bad_filename'] = "The file name you submitted already exists on the server.";
+$lang['upload_not_writable'] = "The upload destination folder does not appear to be writable.";
+
+?> \ No newline at end of file
diff --git a/system/language/english/validation_lang.php b/system/language/english/validation_lang.php
new file mode 100644
index 000000000..326fe5579
--- /dev/null
+++ b/system/language/english/validation_lang.php
@@ -0,0 +1,15 @@
+<?php
+
+$lang['required'] = "The %s field is required.";
+$lang['isset'] = "The %s field must have a value.";
+$lang['valid_email'] = "The %s field must contain a valid email address.";
+$lang['valid_url'] = "The %s field must contain a valid URL.";
+$lang['min_length'] = "The %s field must be at least %s characters in length.";
+$lang['max_length'] = "The %s field can not exceed %s characters in length.";
+$lang['exact_length'] = "The %s field must be exactly %s characters in length.";
+$lang['alpha'] = "The %s field may only contain alpha-numeric characters.";
+$lang['alpha_dash'] = "The %s field may only contain alpha-numeric characters, underscores, and dashes.";
+$lang['numeric'] = "The %s field must contain a number.";
+$lang['matches'] = "The %s field does not match the %s field.";
+
+?> \ No newline at end of file
diff --git a/system/language/index.html b/system/language/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/language/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/libraries/Benchmark.php b/system/libraries/Benchmark.php
new file mode 100644
index 000000000..9dd9d4ac4
--- /dev/null
+++ b/system/libraries/Benchmark.php
@@ -0,0 +1,117 @@
+<?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 Benchmark Class
+ *
+ * This class enables you to mark points and calculate the time difference
+ * between them. Memory consumption can also be displayed.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/benchmark.html
+ */
+class CI_Benchmark {
+
+ var $marker = array();
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function CI_Benchmark()
+ {
+ }
+ // END CI_Benchmark()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set a benchmark marker
+ *
+ * Multiple calls to this function can be made so that several
+ * execution points can be timed
+ *
+ * @access public
+ * @param string $name name of the marker
+ * @return void
+ */
+ function mark($name)
+ {
+ $this->marker[$name] = microtime();
+ }
+ // END mark()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Calculates the time difference between two marked points.
+ *
+ * If the first parameter is empty this function instead returns the
+ * {elapsed_time} pseudo-variable. This permits the the full system
+ * execution time to be shown in a template. The output class will
+ * swap the real value for this variable.
+ *
+ * @access public
+ * @param string a paricular marked point
+ * @param string a paricular marked point
+ * @param integer the number of decimal places
+ * @return mixed
+ */
+ function elapsed_time($point1 = '', $point2 = '', $decimals = 4)
+ {
+ if ($point1 == '')
+ {
+ return '{elapsed_time}';
+ }
+
+ if ( ! isset($this->marker[$point2]))
+ $this->marker[$point2] = microtime();
+
+ list($sm, $ss) = explode(' ', $this->marker[$point1]);
+ list($em, $es) = explode(' ', $this->marker[$point2]);
+
+ return number_format(($em + $es) - ($sm + $ss), $decimals);
+ }
+ // END elapsed_time()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Memory Usage
+ *
+ * This function returns the {memory_usage} pseudo-variable.
+ * This permits it to be put it anywhere in a template
+ * without the memory being calculated until the end.
+ * The output class will swap the real value for this variable.
+ *
+ * @access public
+ * @return string
+ */
+ function memory_usage()
+ {
+ return '{memory_usage}';
+ }
+ // END memory_usage()
+
+}
+
+// END CI_Benchmark class
+?> \ No newline at end of file
diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php
new file mode 100644
index 000000000..013f06796
--- /dev/null
+++ b/system/libraries/Calendar.php
@@ -0,0 +1,473 @@
+<?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 Calendar Class
+ *
+ * This class enables the creation of calendars
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/calendar.html
+ */
+class CI_Calendar {
+
+ var $lang;
+ var $obj;
+ var $local_time;
+ var $template = '';
+ var $start_day = 'sunday';
+ var $month_type = 'long';
+ var $day_type = 'abr';
+ var $show_next_prev = FALSE;
+ var $next_prev_url = '';
+
+ /**
+ * Constructor
+ *
+ * Loads the calendar language file and sets the default time reference
+ *
+ * @access public
+ */
+ function CI_Calendar()
+ {
+ $this->obj =& get_instance();
+ if ( ! in_array('calendar_lang'.EXT, $this->obj->lang->is_loaded))
+ {
+ $this->obj->lang->load('calendar');
+ }
+
+ $this->local_time = time();
+ log_message('debug', "Calendar Class Initialized");
+ }
+ // END CI_Calendar()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize the user preferences
+ *
+ * Accepts an associative array as input, containing display preferences
+ *
+ * @access public
+ * @param array config preferences
+ * @return void
+ */
+ function initialize($config = array())
+ {
+ foreach ($config as $key => $val)
+ {
+ if (isset($this->$key))
+ {
+ $this->$key = $val;
+ }
+ }
+ }
+ // END initialize()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate the calendar
+ *
+ * @access public
+ * @param integer the year
+ * @param integer the month
+ * @param array the data to be shown in the calendar cells
+ * @return string
+ */
+ function generate($year = '', $month = '', $data = array())
+ {
+ // Set and validate the supplied month/year
+ if ($year == '')
+ $year = date("Y", $this->local_time);
+
+ if ($month == '')
+ $month = date("m", $this->local_time);
+
+ if (strlen($year) == 1)
+ $year = '200'.$year;
+
+ if (strlen($year) == 2)
+ $year = '20'.$year;
+
+ if (strlen($month) == 1)
+ $month = '0'.$month;
+
+ $adjusted_date = $this->adjust_date($month, $year);
+
+ $month = $adjusted_date['month'];
+ $year = $adjusted_date['year'];
+
+ // Determine the total days in the month
+ $total_days = $this->get_total_days($month, $year);
+
+ // Set the starting day of the week
+ $start_days = array('sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6);
+ $start_day = ( ! isset($start_days[$this->start_day])) ? 0 : $start_days[$this->start_day];
+
+ // Set the starting day number
+ $local_date = mktime(12, 0, 0, $month, 1, $year);
+ $date = getdate($local_date);
+ $day = $start_day + 1 - $date["wday"];
+
+ while ($day > 1)
+ {
+ $day -= 7;
+ }
+
+ // Set the current month/year/day
+ // We use this to determine the "today" date
+ $cur_year = date("Y", $this->local_time);
+ $cur_month = date("m", $this->local_time);
+ $cur_day = date("j", $this->local_time);
+
+ $is_current_month = ($cur_year == $year AND $cur_month == $month) ? TRUE : FALSE;
+
+ // Generate the template data array
+ $this->parse_template();
+
+ // Begin building the calendar output
+ $out = $this->temp['table_open'];
+ $out .= "\n";
+
+ $out .= "\n";
+ $out .= $this->temp['heading_row_start'];
+ $out .= "\n";
+
+ // "previous" month link
+ if ($this->show_next_prev == TRUE)
+ {
+ $adjusted_date = $this->adjust_date($month - 1, $year);
+ $out .= str_replace('{previous_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->temp['heading_previous_cell']);
+ $out .= "\n";
+ }
+
+ // Heading containing the month/year
+ $colspan = ($this->show_next_prev == TRUE) ? 5 : 7;
+
+ $this->temp['heading_title_cell'] = str_replace('{colspan}', $colspan, $this->temp['heading_title_cell']);
+ $this->temp['heading_title_cell'] = str_replace('{heading}', $this->get_month_name($month)."&nbsp;".$year, $this->temp['heading_title_cell']);
+
+ $out .= $this->temp['heading_title_cell'];
+ $out .= "\n";
+
+ // "next" month link
+ if ($this->show_next_prev == TRUE)
+ {
+ $adjusted_date = $this->adjust_date($month + 1, $year);
+ $out .= str_replace('{next_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->temp['heading_next_cell']);
+ }
+
+ $out .= "\n";
+ $out .= $this->temp['heading_row_end'];
+ $out .= "\n";
+
+ // Write the cells containing the days of the week
+ $out .= "\n";
+ $out .= $this->temp['week_row_start'];
+ $out .= "\n";
+
+ $day_names = $this->get_day_names();
+
+ for ($i = 0; $i < 7; $i ++)
+ {
+ $out .= str_replace('{week_day}', $day_names[($start_day + $i) %7], $this->temp['week_day_cell']);
+ }
+
+ $out .= "\n";
+ $out .= $this->temp['week_row_end'];
+ $out .= "\n";
+
+ // Build the main body of the calendar
+ while ($day <= $total_days)
+ {
+ $out .= "\n";
+ $out .= $this->temp['cal_row_start'];
+ $out .= "\n";
+
+ for ($i = 0; $i < 7; $i++)
+ {
+ $out .= ($is_current_month == TRUE AND $day == $cur_day) ? $this->temp['cal_cell_start_today'] : $this->temp['cal_cell_start'];
+
+ if ($day > 0 AND $day <= $total_days)
+ {
+ if (isset($data[$day]))
+ {
+ // Cells with content
+ $temp = ($is_current_month == TRUE AND $day == $cur_day) ? $this->temp['cal_cell_content_today'] : $this->temp['cal_cell_content'];
+ $out .= str_replace('{day}', $day, str_replace('{content}', $data[$day], $temp));
+ }
+ else
+ {
+ // Cells with no content
+ $temp = ($is_current_month == TRUE AND $day == $cur_day) ? $this->temp['cal_cell_no_content_today'] : $this->temp['cal_cell_no_content'];
+ $out .= str_replace('{day}', $day, $temp);
+ }
+ }
+ else
+ {
+ // Blank cells
+ $out .= $this->temp['cal_cell_blank'];
+ }
+
+ $out .= ($is_current_month == TRUE AND $day == $cur_day) ? $this->temp['cal_cell_end_today'] : $this->temp['cal_cell_end'];
+ $day++;
+ }
+
+ $out .= "\n";
+ $out .= $this->temp['cal_row_end'];
+ $out .= "\n";
+ }
+
+ $out .= "\n";
+ $out .= $this->temp['table_close'];
+
+ return $out;
+ }
+ // END generate()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Month Name
+ *
+ * Generates a texual month name based on the numeric
+ * month provided.
+ *
+ * @access public
+ * @parm integer the month
+ * @return string
+ */
+ function get_month_name($month)
+ {
+ if ($this->month_type == 'short')
+ {
+ $month_names = array('01' => 'cal_jan', '02' => 'cal_feb', '03' => 'cal_mar', '04' => 'cal_apr', '05' => 'cal_may', '06' => 'cal_jun', '07' => 'cal_jul', '08' => 'cal_aug', '09' => 'cal_sep', '10' => 'cal_oct', '11' => 'cal_nov', '12' => 'cal_dec');
+ }
+ else
+ {
+ $month_names = array('01' => 'cal_january', '02' => 'cal_february', '03' => 'cal_march', '04' => 'cal_april', '05' => 'cal_mayl', '06' => 'cal_june', '07' => 'cal_july', '08' => 'cal_august', '09' => 'cal_september', '10' => 'cal_october', '11' => 'cal_novermber', '12' => 'cal_december');
+ }
+
+ $month = $month_names[$month];
+
+ if ($this->obj->lang->line($month) === FALSE)
+ {
+ return ucfirst(str_replace('cal_', '', $month));
+ }
+
+ return $this->obj->lang->line($month);
+ }
+ // END get_month_name()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Day Names
+ *
+ * Returns an array of day names (Sunday, Monday, etc.) based
+ * on the type. Options: long, short, abrev
+ *
+ * @access public
+ * @param string
+ * @return array
+ */
+ function get_day_names($day_type = '')
+ {
+ if ($day_type != '')
+ $this->day_type = $day_type;
+
+ if ($this->day_type == 'long')
+ {
+ $day_names = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');
+ }
+ elseif ($this->day_type == 'short')
+ {
+ $day_names = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');
+ }
+ else
+ {
+ $day_names = array('su', 'mo', 'tu', 'we', 'th', 'fr', 'sa');
+ }
+
+ $days = array();
+ foreach ($day_names as $val)
+ {
+ $days[] = ($this->obj->lang->line('cal_'.$val) === FALSE) ? ucfirst($val) : $this->obj->lang->line('cal_'.$val);
+ }
+
+ return $days;
+ }
+ // END get_day_names()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Adjust Date
+ *
+ * This function makes sure that we have a valid month/year.
+ * For example, if you submit 13 as the month, the year will
+ * increment and the month will become January.
+ *
+ * @access public
+ * @param integer the month
+ * @param integer the year
+ * @return array
+ */
+ function adjust_date($month, $year)
+ {
+ $date = array();
+
+ $date['month'] = $month;
+ $date['year'] = $year;
+
+ while ($date['month'] > 12)
+ {
+ $date['month'] -= 12;
+ $date['year']++;
+ }
+
+ while ($date['month'] <= 0)
+ {
+ $date['month'] += 12;
+ $date['year']--;
+ }
+
+ if (strlen($date['month']) == 1)
+ {
+ $date['month'] = '0'.$date['month'];
+ }
+
+ return $date;
+ }
+ // END adjust_date()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Total days in a given month
+ *
+ * @access public
+ * @param integer the month
+ * @param integer the year
+ * @return integer
+ */
+ function get_total_days($month, $year)
+ {
+ $days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
+
+ if ($month < 1 OR $month > 12)
+ {
+ return 0;
+ }
+
+ if ($month == 2)
+ {
+ if ($year % 400 == 0 OR ($year % 4 == 0 AND $year % 100 != 0))
+ {
+ return 29;
+ }
+ }
+
+ return $days_in_month[$month - 1];
+ }
+ // END get_total_days()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Default Template Data
+ *
+ * This is used in the event that the user has not created their own template
+ *
+ * @access public
+ * @return array
+ */
+ function default_template()
+ {
+ return array (
+ 'table_open' => '<table border="0" cellpadding="4" cellspacing="0">',
+ 'heading_row_start' => '<tr>',
+ 'heading_previous_cell' => '<th><a href="{previous_url}">&lt;&lt;</a></th>',
+ 'heading_title_cell' => '<th colspan="{colspan}">{heading}</th>',
+ 'heading_next_cell' => '<th><a href="{next_url}">&gt;&gt;</a></th>',
+ 'heading_row_end' => '</tr>',
+ 'week_row_start' => '<tr>',
+ 'week_day_cell' => '<td>{week_day}</td>',
+ 'week_row_end' => '</tr>',
+ 'cal_row_start' => '<tr>',
+ 'cal_cell_start' => '<td>',
+ 'cal_cell_start_today' => '<td>',
+ 'cal_cell_content' => '<a href="{content}">{day}</a>',
+ 'cal_cell_content_today' => '<a href="{content}"><strong>{day}</strong></a>',
+ 'cal_cell_no_content' => '{day}',
+ 'cal_cell_no_content_today' => '<strong>{day}</strong>',
+ 'cal_cell_blank' => '&nbsp;',
+ 'cal_cell_end' => '</td>',
+ 'cal_cell_end_today' => '</td>',
+ 'cal_row_end' => '</tr>',
+ 'table_close' => '</table>'
+ );
+ }
+ // END default_template()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse Template
+ *
+ * Harvests the data within the template {pseudo-variables}
+ * used to display the calendar
+ *
+ * @access public
+ * @return void
+ */
+ function parse_template()
+ {
+ $this->temp = $this->default_template();
+
+ if ($this->template == '')
+ {
+ return;
+ }
+
+ $today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today');
+
+ foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today') as $val)
+ {
+ if (preg_match("/\{".$val."\}(.*?)\{\/".$val."\}/si", $this->template, $match))
+ {
+ $this->temp[$val] = $match['1'];
+ }
+ else
+ {
+ if (in_array($val, $today))
+ {
+ $this->temp[$val] = $this->temp[str_replace('_today', '', $val)];
+ }
+ }
+ }
+ }
+ // END parse_template()
+
+}
+
+// END CI_Calendar class
+?> \ No newline at end of file
diff --git a/system/libraries/Config.php b/system/libraries/Config.php
new file mode 100644
index 000000000..85b295796
--- /dev/null
+++ b/system/libraries/Config.php
@@ -0,0 +1,181 @@
+<?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 Config Class
+ *
+ * This class contains functions that enable config files to be managed
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/config.html
+ */
+class CI_Config {
+
+ var $config = array();
+ var $is_loaded = array();
+
+ /**
+ * Constructor
+ *
+ * Sets the $config data from the primary config.php file as a class variable
+ *
+ * @access public
+ */
+ function CI_Config()
+ {
+ $this->config =& _get_config();
+ log_message('debug', "Config Class Initialized");
+ }
+ // END CI_Config()
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Config File
+ *
+ * @access public
+ * @param string the config file name
+ * @return void
+ */
+ function load($file = '')
+ {
+ $file = ($file == '') ? 'config' : str_replace(EXT, '', $file);
+
+ if (in_array($file, $this->is_loaded))
+ {
+ return;
+ }
+
+ include_once(APPPATH.'config/'.$file.EXT);
+
+ if ( ! isset($config) OR ! is_array($config))
+ {
+ show_error('Your '.$file.EXT.' file does not appear to contain a valid configuration array.');
+ }
+
+ $this->config = array_merge($this->config, $config);
+
+ $this->is_loaded[] = $file;
+ unset($config);
+
+ log_message('debug', 'Config file loaded: config/'.$file.EXT);
+ }
+ // END load()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a config file item
+ *
+ * The second parameter allows a slash to be added to the end of
+ * the item, in the case of a path.
+ *
+ * @access public
+ * @param string the config item name
+ * @param bool
+ * @return string
+ */
+ function item($item, $slash = FALSE)
+ {
+ if ( ! isset($this->config[$item]))
+ {
+ return FALSE;
+ }
+
+ $pref = $this->config[$item];
+
+ if ($pref == '')
+ {
+ return $pref;
+ }
+
+ if ($slash !== FALSE AND ereg("/$", $pref) === FALSE)
+ {
+ $pref .= '/';
+ }
+
+ return $pref;
+ }
+ // END item()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Site URL
+ *
+ * @access public
+ * @param string the URI string
+ * @return string
+ */
+ function site_url($uri = '')
+ {
+ if (is_array($uri))
+ {
+ $uri = implode('/', $uri);
+ }
+
+ if ($uri == '')
+ {
+ return $this->item('base_url', 1).$this->item('index_page');
+ }
+ else
+ {
+ $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix');
+ return $this->item('base_url', 1).$this->item('index_page', 1).preg_replace("|^/*(.+?)/*$|", "\\1", $uri).$suffix;
+ }
+ }
+ // END site_url()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * System URL
+ *
+ * @access public
+ * @return string
+ */
+ function system_url()
+ {
+ $x = explode("/", preg_replace("|/*(.+?)/*$|", "\\1", BASEPATH));
+ return $this->item('base_url', 1).end($x).'/';
+ }
+ // END system_url()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set a config file item
+ *
+ * @access public
+ * @param string the config item key
+ * @param string the config item value
+ * @return void
+ */
+ function set_item($item, $value)
+ {
+ $this->config[$item] = $value;
+ }
+ // END set_item()
+
+}
+
+// END CI_Config class
+?> \ No newline at end of file
diff --git a/system/libraries/Controller.php b/system/libraries/Controller.php
new file mode 100644
index 000000000..ec21f8d66
--- /dev/null
+++ b/system/libraries/Controller.php
@@ -0,0 +1,445 @@
+<?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 Application Controller Class
+ *
+ * This class object is the the super class the every library in
+ * Code Igniter will be assigned to.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/general/controllers.html
+ */
+class Controller extends CI_Base {
+
+ var $ci_is_loaded = array();
+ var $_ci_models = array();
+ var $_ci_scaffolding = FALSE;
+ var $_ci_scaff_table = FALSE;
+
+ /**
+ * Constructor
+ *
+ * Loads the base classes needed to run CI, and runs the "autoload"
+ * routine which loads the systems specified in the "autoload" config file.
+ */
+ function Controller()
+ {
+ parent::CI_Base();
+
+ // Assign all the class objects that were instantiated by the
+ // front controller to local class variables so that CI can be
+ // run as one big super object.
+ $this->_ci_assign_core();
+
+ // Load everything specified in the autoload.php file
+ $this->load->_ci_autoloader($this->_ci_autoload());
+
+ // This allows anything loaded using $this->load (viwes, files, etc.)
+ // to become accessible from within the Controller class functions.
+ foreach ($this->ci_is_loaded as $val)
+ {
+ $this->load->$val =& $this->$val;
+ }
+
+ log_message('debug', "Controller Class Initialized");
+ }
+ // END Controller()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialization Handler
+ *
+ * Looks for the existence of a handler method and calls it
+ *
+ * @access private
+ * @param string the item that is being loaded
+ * @param mixed any additional parameters
+ * @return void
+ */
+ function _ci_initialize($what, $params = FALSE)
+ {
+ $method = '_ci_init_'.strtolower(str_replace(EXT, '', $what));
+
+ if ( ! method_exists($this, $method))
+ {
+ $method = substr($method, 4);
+
+ if ( ! file_exists(APPPATH.'init/'.$method.EXT))
+ {
+ if ( ! file_exists(BASEPATH.'init/'.$method.EXT))
+ {
+ log_message('error', "Unable to load the requested class: ".$what);
+ show_error("Unable to load the class: ".$what);
+ }
+
+ include(BASEPATH.'init/'.$method.EXT);
+ }
+ else
+ {
+ include(APPPATH.'init/'.$method.EXT);
+ }
+ }
+ else
+ {
+ if ($params === FALSE)
+ {
+ $this->$method();
+ }
+ else
+ {
+ $this->$method($params);
+ }
+ }
+ }
+ // END _ci_initialize()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Loads and instantiates the requested model class
+ *
+ * @access private
+ * @param string
+ * @return array
+ */
+ function _ci_load_model($model, $name = '', $db_conn = FALSE)
+ {
+ if ($name == '')
+ {
+ $name = $model;
+ }
+
+ if (isset($this->$name))
+ {
+ show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
+ }
+
+ $model = strtolower($model);
+
+ if ( ! file_exists(APPPATH.'models/'.$model.EXT))
+ {
+ show_error('Unable to locate the model you have specified: '.$model);
+ }
+
+ if ($db_conn !== FALSE)
+ {
+ if ($db_conn === TRUE)
+ $db_conn = '';
+
+ $this->_ci_init_database($db_conn, FALSE, TRUE);
+ }
+
+ if ( ! class_exists('Model'))
+ {
+ require_once(BASEPATH.'libraries/Model'.EXT);
+ }
+
+ require_once(APPPATH.'models/'.$model.EXT);
+
+ $model = ucfirst($model);
+ $this->$name = new $model();
+ $this->_ci_models[] = $name;
+ $this->_ci_assign_to_models();
+ }
+ // END _ci_load_model()
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Assign to Models
+ *
+ * Makes sure that anything loaded by the loader class (libraries, plugins, etc.)
+ * will be available to modles, if any exist.
+ *
+ * @access public
+ * @param object
+ * @return array
+ */
+ function _ci_assign_to_models()
+ {
+ $obj =& get_instance();
+ if (count($obj->_ci_models) == 0)
+ {
+ return;
+ }
+ foreach ($obj->_ci_models as $model)
+ {
+ $obj->$model->_assign_libraries();
+ }
+ }
+ // END _ci_assign_to_models()
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Auto-initialize Core Classes
+ *
+ * This initializes the core systems that are specified in the
+ * libraries/autoload.php file, as well as the systems specified in
+ * the $autoload class array above.
+ *
+ * It returns the "autoload" array so we can pass it to the Loader
+ * class since it needs to autoload plugins and helper files
+ *
+ * The config/autoload.php file contains an array that permits
+ * sub-systems to be loaded automatically.
+ *
+ * @access private
+ * @return array
+ */
+ function _ci_autoload()
+ {
+ include_once(APPPATH.'config/autoload'.EXT);
+
+ if ( ! isset($autoload))
+ {
+ return FALSE;
+ }
+
+ if (count($autoload['config']) > 0)
+ {
+ foreach ($autoload['config'] as $key => $val)
+ {
+ $this->config->load($val);
+ }
+ }
+ unset($autoload['config']);
+
+ if ( ! is_array($autoload['core']))
+ {
+ $autoload['core'] = array($autoload['core']);
+ }
+
+ foreach ($autoload['core'] as $item)
+ {
+ $this->_ci_initialize($item);
+ }
+
+ return $autoload;
+ }
+ // END _ci_autoload()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Assign the core classes to the global $CI object
+ *
+ * By assigning all the classes instantiated by the front controller
+ * local class variables we enable everything to be accessible using
+ * $this->class->function()
+ *
+ * @access private
+ * @return void
+ */
+ function _ci_assign_core()
+ {
+ foreach (array('Config', 'Input', 'Benchmark', 'URI', 'Output') as $val)
+ {
+ $class = strtolower($val);
+ $this->$class =& _load_class('CI_'.$val);
+ $this->ci_is_loaded[] = $class;
+ }
+
+ $this->lang =& _load_class('CI_Language');
+ $this->ci_is_loaded[] = 'lang';
+
+ // In PHP 4 the Controller class is a child of CI_Loader.
+ // In PHP 5 we run it as its own class.
+ if (floor(phpversion()) >= 5)
+ {
+ $this->load = new CI_Loader();
+ }
+
+ $this->ci_is_loaded[] = 'load';
+ }
+ // END _ci_assign_core()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize Scaffolding
+ *
+ * This initializing function works a bit different than the
+ * others. It doesn't load the class. Instead, it simply
+ * sets a flag indicating that scaffolding is allowed to be
+ * used. The actual scaffolding function below is
+ * called by the front controller based on whether the
+ * second segment of the URL matches the "secret" scaffolding
+ * word stored in the application/config/routes.php
+ *
+ * @access private
+ * @param string the table to scaffold
+ * @return void
+ */
+ function _ci_init_scaffolding($table = FALSE)
+ {
+ if ($table === FALSE)
+ {
+ show_error('You must include the name of the table you would like access when you initialize scaffolding');
+ }
+
+ $this->_ci_scaffolding = TRUE;
+ $this->_ci_scaff_table = $table;
+ }
+ // END _ci_init_scaffolding()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize Database
+ *
+ * @access private
+ * @param mixed database connection values
+ * @param bool whether to return the object for multiple connections
+ * @return void
+ */
+ function _ci_init_database($params = '', $return = FALSE, $active_record = FALSE)
+ {
+ if ($this->_ci_is_loaded('db') == TRUE AND $return == FALSE AND $active_record == FALSE)
+ {
+ return;
+ }
+
+ // Load the DB config file if needed
+ if (is_string($params) AND strpos($params, '://') === FALSE)
+ {
+ include(APPPATH.'config/database'.EXT);
+
+ $group = ($params == '') ? $active_group : $params;
+
+ if ( ! isset($db[$group]))
+ {
+ show_error('You have specified an invalid database connection group: '.$group);
+ }
+
+ $params = $db[$group];
+ }
+
+ // No DB specified yet? Beat them senseless...
+ if ( ! isset($params['dbdriver']) OR $params['dbdriver'] == '')
+ {
+ show_error('You have not selected a database type to connect to.');
+ }
+
+ // Load the DB classes. Note: Since the active record class is optional
+ // we need to dynamically create a class that extends proper parent class
+ // based on whether we're using the active record class or not.
+ // Kudos to Paul for discovering this clever use of eval()
+
+ if ($active_record == TRUE)
+ {
+ $params['active_r'] = TRUE;
+ }
+
+ require_once(BASEPATH.'drivers/DB_driver'.EXT);
+
+ if ( ! isset($params['active_r']) OR $params['active_r'] == TRUE)
+ {
+ require_once(BASEPATH.'drivers/DB_active_record'.EXT);
+
+ if ( ! class_exists('CI_DB'))
+ {
+ eval('class CI_DB extends CI_DB_active_record { }');
+ }
+ }
+ else
+ {
+ if ( ! class_exists('CI_DB'))
+ {
+ eval('class CI_DB extends CI_DB_driver { }');
+ }
+ }
+
+ require_once(BASEPATH.'drivers/DB_'.$params['dbdriver'].EXT);
+
+ // Instantiate the DB adapter
+ $driver = 'CI_DB_'. $params['dbdriver'];
+ $DB = new $driver($params);
+
+ if ($return === TRUE)
+ {
+ return $DB;
+ }
+
+ $obj =& get_instance();
+ $obj->ci_is_loaded[] = 'db';
+ $obj->db =& $DB;
+ }
+ // END _ci_init_database()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns TRUE if a class is loaded, FALSE if not
+ *
+ * @access public
+ * @param string the class name
+ * @return bool
+ */
+ function _ci_is_loaded($class)
+ {
+ return ( ! in_array($class, $this->ci_is_loaded)) ? FALSE : TRUE;
+ }
+ // END _ci_is_loaded()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Scaffolding
+ *
+ * Initializes the scaffolding.
+ *
+ * @access private
+ * @return void
+ */
+ function _ci_scaffolding()
+ {
+ if ($this->_ci_scaffolding === FALSE OR $this->_ci_scaff_table === FALSE)
+ {
+ show_404('Scaffolding unavailable');
+ }
+
+ if (class_exists('Scaffolding')) return;
+
+ if ( ! in_array($this->uri->segment(3), array('add', 'insert', 'edit', 'update', 'view', 'delete', 'do_delete')))
+ {
+ $method = 'view';
+ }
+ else
+ {
+ $method = $this->uri->segment(3);
+ }
+
+ $this->_ci_init_database("", FALSE, TRUE);
+
+ $this->_ci_initialize('pagination');
+ require_once(BASEPATH.'scaffolding/Scaffolding'.EXT);
+ $this->scaff = new Scaffolding($this->_ci_scaff_table);
+ $this->scaff->$method();
+ }
+ // END _ci_scaffolding()
+
+}
+// END _Controller class
+?> \ No newline at end of file
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
new file mode 100644
index 000000000..96dc0014d
--- /dev/null
+++ b/system/libraries/Email.php
@@ -0,0 +1,1740 @@
+<?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 Email Class
+ *
+ * Permits email to be sent using Mail, Sendmail, or SMTP.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/email.html
+ */
+class CI_Email {
+
+ var $useragent = "Code Igniter";
+ 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 $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 $_subject = "";
+ var $_body = "";
+ var $_finalbody = "";
+ var $_alt_boundary = "";
+ var $_atc_boundary = "";
+ var $_header_str = "";
+ var $_smtp_connect = "";
+ var $_encoding = "8bit";
+ var $_safe_mode = FALSE;
+ 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('iso-8859-1', 'us-ascii');
+ 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);
+ }
+
+ log_message('debug', "Email Class Initialized");
+ }
+ // END CI_Email()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 = (@ini_get("safe_mode") == 0) ? FALSE : TRUE;
+ }
+ // END initialize()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize the Email Data
+ *
+ * @access public
+ * @return void
+ */
+ function clear()
+ {
+ $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());
+ }
+ // END clear()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 != '' && substr($name, 0, 1) != '"')
+ {
+ $name = '"'.$name.'"';
+ }
+
+ $this->_set_header('From', $name.' <'.$from.'>');
+ $this->_set_header('Return-Path', '<'.$from.'>');
+ }
+ // END 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 (substr($name, 0, 1) != '"')
+ {
+ $name = '"'.$name.'"';
+ }
+
+ $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
+ $this->_replyto_flag = TRUE;
+ }
+ // END reply_to()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ }
+ // END to()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END cc()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set BCC
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return void
+ */
+ function bcc($bcc, $limit = '')
+ {
+ if ($limit != '' && ctype_digit($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));
+ }
+ // END bcc()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Email Subject
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function subject($subject)
+ {
+ $subject = preg_replace("/(\r\n)|(\r)|(\n)/", "", $subject);
+ $subject = preg_replace("/(\t)/", " ", $subject);
+
+ $this->_set_header('Subject', trim($subject));
+ }
+ // END subject()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Body
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function message($body)
+ {
+ $body = rtrim(str_replace("\r", "", $body));
+
+ if ($this->wordwrap === TRUE AND $this->mailtype != 'html')
+ $this->_body = $this->word_wrap($body);
+ else
+ $this->_body = $body;
+
+ $this->_body = stripslashes($this->_body);
+ }
+ // END message()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Assign file attachments
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function attach($filename, $disposition = 'attachment')
+ {
+ $this->_attach_name[] = $filename;
+ $this->_attach_type[] = $this->_mime_types(next(explode('.', basename($filename))));
+ $this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters
+ }
+ // END attach()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Add a Header Item
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return void
+ */
+ function _set_header($header, $value)
+ {
+ $this->_headers[$header] = $value;
+ }
+ // END _set_header()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Convert a String to an Array
+ *
+ * @access public
+ * @param string
+ * @return array
+ */
+ function _str_to_array($email)
+ {
+ if ( ! is_array($email))
+ {
+ if (ereg(',$', $email))
+ $email = substr($email, 0, -1);
+
+ if (ereg('^,', $email))
+ $email = substr($email, 1);
+
+ if (ereg(',', $email))
+ {
+ $x = explode(',', $email);
+ $email = array();
+
+ for ($i = 0; $i < count($x); $i ++)
+ $email[] = trim($x[$i]);
+ }
+ else
+ {
+ $email = trim($email);
+ settype($email, "array");
+ }
+ }
+ return $email;
+ }
+ // END _str_to_array()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Multipart Value
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_alt_message($str = '')
+ {
+ $this->alt_message = ($str == '') ? '' : $str;
+ }
+ // END set_alt_message()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Mailtype
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_mailtype($type = 'text')
+ {
+ $this->mailtype = ($type == 'html') ? 'html' : 'text';
+ }
+ // END set_mailtype()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Wordwrap
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_wordwrap($wordwrap = TRUE)
+ {
+ $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE;
+ }
+ // END set_wordwrap()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Protocal
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_protocol($protocol = 'mail')
+ {
+ $this->protocol = ( ! in_array($protocol, $this->_protocols)) ? 'mail' : strtolower($protocol);
+ }
+ // END set_protocol()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Priority
+ *
+ * @access public
+ * @param integer
+ * @return void
+ */
+ function set_priority($n = 3)
+ {
+ if ( ! ctype_digit($n))
+ {
+ $this->priority = 3;
+ return;
+ }
+
+ if ($n < 1 OR $n > 5)
+ {
+ $this->priority = 3;
+ return;
+ }
+
+ $this->priority = $n;
+ }
+ // END set_priority()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Newline Character
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_newline($newline = "\n")
+ {
+ if ($newline != "\n" OR $newline != "\r\n" OR $newline != "\r")
+ {
+ $this->newline = "\n";
+ return;
+ }
+
+ $this->newline = $newline;
+ }
+ // END set_newline()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Message Boundry
+ *
+ * @access private
+ * @return void
+ */
+ function _set_boundaries()
+ {
+ $this->_alt_boundary = "B_ALT_".uniqid(''); // mulipart/alternative
+ $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
+ }
+ // END _set_boundaries()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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, '@').">";
+ }
+ // END _get_message_id()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)) ? 'mail' : $this->protocol;
+
+ if ($return == true)
+ return $this->protocol;
+ }
+ // END _get_protocol()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Mail Encoding
+ *
+ * @access private
+ * @param bool
+ * @return string
+ */
+ function _get_encoding($return = true)
+ {
+ $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '7bit' : $this->_encoding;
+
+ if ( ! in_array($this->charset, $this->_base_charsets))
+ $this->_encoding = "8bit";
+
+ if ($return == true)
+ return $this->_encoding;
+ }
+ // END _get_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';
+ }
+ // END _get_content_type()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set RFC 822 Date
+ *
+ * @access public
+ * @return string
+ */
+ function _set_date()
+ {
+ $timezone = date("Z");
+ $operator = (substr($timezone, 0, 1) == '-') ? '-' : '+';
+ $timezone = abs($timezone);
+ $timezone = ($timezone/3600) * 100 + ($timezone % 3600) /60;
+
+ return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone);
+ }
+ // END _set_date()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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.";
+ }
+ // END _get_mime_message()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ }
+ }
+ // END validate_email()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Email Validation
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function valid_email($address)
+ {
+ if ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address))
+ return FALSE;
+ else
+ return TRUE;
+ }
+ // END valid_email()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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();
+
+ for ($i=0; $i < count($email); $i++)
+ {
+ if (preg_match( '/\<(.*)\>/', $email[$i], $match))
+ $clean_email[] = $match['1'];
+ else
+ $clean_email[] = $email[$i];
+ }
+
+ return $clean_email;
+ }
+ // END 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 (eregi( '\<body(.*)\</body\>', $this->_body, $match))
+ {
+ $body = $match['1'];
+ $body = substr($body, strpos($body, ">") + 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');
+ }
+ // END _get_alt_message()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Word Wrap
+ *
+ * @access public
+ * @param string
+ * @param integer
+ * @return string
+ */
+ function word_wrap($str, $chars = '')
+ {
+ if ($chars == '')
+ $chars = ($this->wrapchars == "") ? "76" : $this->wrapchars;
+
+ $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)
+ {
+ if (stristr($thisword, '{unwrap}') !== FALSE OR stristr($thisword, '{/unwrap}') !== FALSE)
+ {
+ break;
+ }
+
+ $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;
+ }
+ // END word_wrap()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Build final headers
+ *
+ * @access public
+ * @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');
+ }
+ // END _build_headers()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write Headers as a string
+ *
+ * @access public
+ * @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);
+ }
+ // END _write_headers()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Build Final Body and attachments
+ *
+ * @access public
+ * @return void
+ */
+ function _build_message()
+ {
+ $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' :
+
+ $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";
+
+ if ($this->_get_protocol() == 'mail')
+ {
+ $this->_header_str .= $hdr;
+ $this->_finalbody = $this->_body . $this->newline . $this->newline . "--" . $this->_alt_boundary . "--";
+
+ return;
+ }
+
+ $hdr .= $this->newline . $this->newline;
+ $hdr .= $this->_body . $this->newline . $this->newline . "--" . $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";
+
+ 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, 'r'))
+ {
+ $this->_set_error_message('email_attachment_unredable', $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;
+ }
+ // END _build_message()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END send()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Batch Bcc Send. Sends groups of Bccs in batches
+ *
+ * @access public
+ * @return bool
+ */
+ function batch_bcc_send()
+ {
+ $float = $this->bcc_batch_size -1;
+
+ $flag = 0;
+ $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();
+ }
+ }
+ // END batch_bcc_send()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+ }
+ // END _unwrap_specials()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Strip line-breaks via callback
+ *
+ * @access private
+ * @return string
+ */
+ function _remove_nl_callback($matches)
+ {
+ return preg_replace("/(\r\n)|(\r)|(\n)/", "", $matches['1']);
+ }
+ // END _remove_nl_callback()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Spool mail to the mail server
+ *
+ * @access private
+ * @return bol
+ */
+ 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;
+ }
+ // END _spool_email()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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
+ {
+ if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f".$this->clean_email($this->_headers['From'])))
+ return FALSE;
+ else
+ return TRUE;
+ }
+ }
+ // END _send_with_mail()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END _send_with_sendmail()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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');
+
+ $this->_send_data($this->_header_str . $this->_finalbody);
+
+ $this->_send_data('.');
+
+ $reply = $this->_get_smtp_data();
+
+ $this->_set_error_message($reply);
+
+ if (substr($reply, 0, 3) != '250')
+ {
+ $this->_set_error_message('email_smtp_error', $reply);
+ return FALSE;
+ }
+
+ $this->_send_command('quit');
+ return true;
+ }
+ // END _send_with_smtp()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * SMTP Connect
+ *
+ * @access public
+ * @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');
+ }
+ // END _smtp_connect()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END _send_command()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 (substr($reply, 0, 3) != '334')
+ {
+ $this->_set_error_message('email_filed_smtp_login', $reply);
+ return FALSE;
+ }
+
+ $this->_send_data(base64_encode($this->smtp_user));
+
+ $reply = $this->_get_smtp_data();
+
+ if (substr($reply, 0, 3) != '334')
+ {
+ $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 (substr($reply, 0, 3) != '235')
+ {
+ $this->_set_error_message('email_smtp_auth_pw', $reply);
+ return FALSE;
+ }
+
+ return true;
+ }
+ // END _smtp_authenticate()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END _send_data()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END _get_smtp_data()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Hostname
+ *
+ * @access private
+ * @return string
+ */
+ function _get_hostname()
+ {
+ return ($this->smtp_host != '') ? $this->smtp_host : $this->_get_ip();
+ }
+ // END _get_hostname()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END _get_ip()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Debugg 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".$this->_subject."\n".$this->_finalbody.'</pre>';
+ return $msg;
+ }
+ // print_debugger()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Message
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function _set_error_message($msg, $val = '')
+ {
+ $obj =& get_instance();
+ $obj->lang->load('email');
+
+ if (FALSE === ($line = $obj->lang->line($msg)))
+ {
+ $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
+ }
+ else
+ {
+ $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
+ }
+ }
+ // END _set_error_message()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 _mime_types()
+
+}
+// END CI_Email class
+?> \ No newline at end of file
diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php
new file mode 100644
index 000000000..532bfe1f1
--- /dev/null
+++ b/system/libraries/Encrypt.php
@@ -0,0 +1,378 @@
+<?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 Encryption Class
+ *
+ * Provides two-way keyed encoding using XOR Hashing and Mcrypt
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/encryption.html
+ */
+class CI_Encrypt {
+ var $_hash_type = 'sha1';
+ var $_mcrypt_exists = FALSE;
+ var $_mcrypt_cipher;
+ var $_mcrypt_mode;
+
+ /**
+ * Constructor
+ *
+ * Simply determines whether the mcrypt library exists.
+ *
+ */
+ function CI_Encrypt()
+ {
+ $this->_mcrypt_exists = ( ! function_exists('mcrypt_encrypt')) ? FALSE : TRUE;
+ log_message('debug', "Encrypt Class Initialized");
+ }
+ // END CI_Encrypt()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the encryption key
+ *
+ * Returns it as MD5 in order to have an exact-length 128 bit key.
+ * Mcrypt is sensitive to keys that are not the correct length
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function get_key($key = '')
+ {
+ if ($key == '')
+ {
+ $obj =& get_instance();
+ $key = $obj->config->item('encryption_key');
+
+ if ($key === FALSE)
+ {
+ show_error('In order to use the encryption class requires that you set an encryption key in your config file.');
+ }
+ }
+
+ return md5($key);
+ }
+ // END get_key()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Encode
+ *
+ * Encodes the message string using bitwise XOR encoding.
+ * The key is combined with a random hash, and then it
+ * too gets converted using XOR. The whole thing is then run
+ * through mcrypt (if supported) using the randomized key.
+ * The end result is a double-encrypted message string
+ * that is randomized with each call to this function,
+ * even if the supplied message and key are the same.
+ *
+ * @access public
+ * @param string the string to encode
+ * @param string the key
+ * @return string
+ */
+ function encode($string, $key = '')
+ {
+ $key = $this->get_key($key);
+ $enc = $this->_xor_encode($string, $key);
+
+ if ($this->_mcrypt_exists === TRUE)
+ {
+ $enc = $this->mcrypt_encode($enc, $key);
+ }
+ return base64_encode($enc);
+ }
+ // END encode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Decode
+ *
+ * Reverses the above process
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function decode($string, $key = '')
+ {
+ $key = $this->get_key($key);
+ $dec = base64_decode($string);
+
+ if ($dec === FALSE)
+ {
+ return FALSE;
+ }
+
+ if ($this->_mcrypt_exists === TRUE)
+ {
+ $dec = $this->mcrypt_decode($dec, $key);
+ }
+
+ return $this->_xor_decode($dec, $key);
+ }
+ // END decode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * XOR Encode
+ *
+ * Takes a plain-text string and key as input and generates an
+ * encoded bit-string using XOR
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @return string
+ */
+ function _xor_encode($string, $key)
+ {
+ $rand = '';
+ while (strlen($rand) < 32)
+ {
+ $rand .= mt_rand(0, mt_getrandmax());
+ }
+
+ $rand = $this->hash($rand);
+
+ $enc = '';
+ for ($i = 0; $i < strlen($string); $i++)
+ {
+ $enc .= substr($rand, ($i % strlen($rand)), 1).(substr($rand, ($i % strlen($rand)), 1) ^ substr($string, $i, 1));
+ }
+
+ return $this->_xor_merge($enc, $key);
+ }
+ // END _xor_encode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * XOR Decode
+ *
+ * Takes an encoded string and key as input and generates the
+ * plain-text original message
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @return string
+ */
+ function _xor_decode($string, $key)
+ {
+ $string = $this->_xor_merge($string, $key);
+
+ $dec = '';
+ for ($i = 0; $i < strlen($string); $i++)
+ {
+ $dec .= (substr($string, $i++, 1) ^ substr($string, $i, 1));
+ }
+
+ return $dec;
+ }
+ // END _xor_decode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * XOR key + string Combiner
+ *
+ * Takes a string and key as input and computes the difference using XOR
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @return string
+ */
+ function _xor_merge($string, $key)
+ {
+ $hash = $this->hash($key);
+ $str = '';
+ for ($i = 0; $i < strlen($string); $i++)
+ {
+ $str .= substr($string, $i, 1) ^ substr($hash, ($i % strlen($hash)), 1);
+ }
+
+ return $str;
+ }
+ // END _xor_merge()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Encrypt using Mcrypt
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function mcrypt_encode($data, $key)
+ {
+ $this->_get_mcrypt();
+ $init_size = mcrypt_get_iv_size($this->_mcrypt_cipher, $this->_mcrypt_mode);
+ $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
+ return mcrypt_encrypt($this->_mcrypt_cipher, $key, $data, $this->_mcrypt_mode, $init_vect);
+ }
+ // END mcrypt_encode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Decrypt using Mcrypt
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function mcrypt_decode($data, $key)
+ {
+ $this->_get_mcrypt();
+ $init_size = mcrypt_get_iv_size($this->_mcrypt_cipher, $this->_mcrypt_mode);
+ $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
+ return rtrim(mcrypt_decrypt($this->_mcrypt_cipher, $key, $data, $this->_mcrypt_mode, $init_vect), "\0");
+ }
+ // END mcrypt_decode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the Mcrypt Cypher
+ *
+ * @access public
+ * @param constant
+ * @return string
+ */
+ function set_cypher($cypher)
+ {
+ $this->_mcrypt_cipher = $cypher;
+ }
+ // END set_cypher()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the Mcrypt Mode
+ *
+ * @access public
+ * @param constant
+ * @return string
+ */
+ function set_mode($mode)
+ {
+ $this->_mcrypt_mode = $mode;
+ }
+ // END set_mode()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Mcrypt value
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _get_mcrypt()
+ {
+ if ($this->_mcrypt_cipher == '')
+ {
+ $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;
+ }
+ if ($this->_mcrypt_mode == '')
+ {
+ $this->_mcrypt_mode = MCRYPT_MODE_ECB;
+ }
+ }
+ // END _get_mcrypt()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the Hash type
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function set_hash($type = 'sha1')
+ {
+ $this->_hash_type = ($type != 'sha1' OR $type != 'md5') ? 'sha1' : $type;
+ }
+ // END set_hash()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Hash encode a string
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function hash($str)
+ {
+ return ($this->_hash_type == 'sha1') ? $this->sha1($str) : md5($str);
+ }
+ // END hash()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate an SHA1 Hash
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function sha1($str)
+ {
+ 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);
+ }
+ }
+ // END sha1()
+
+}
+
+// END CI_Encrypt class
+?> \ No newline at end of file
diff --git a/system/libraries/Exceptions.php b/system/libraries/Exceptions.php
new file mode 100644
index 000000000..a72dbf841
--- /dev/null
+++ b/system/libraries/Exceptions.php
@@ -0,0 +1,165 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Exceptions Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Exceptions
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/exceptions.html
+ */
+class CI_Exceptions {
+ var $action;
+ var $severity;
+ var $message;
+ var $filename;
+ var $line;
+
+ var $levels = array(
+ E_ERROR => 'Error',
+ E_WARNING => 'Warning',
+ E_PARSE => 'Parsing Error',
+ E_NOTICE => 'Notice',
+ E_CORE_ERROR => 'Core Error',
+ E_CORE_WARNING => 'Core Warning',
+ E_COMPILE_ERROR => 'Compile Error',
+ E_COMPILE_WARNING => 'Compile Warning',
+ E_USER_ERROR => 'User Error',
+ E_USER_WARNING => 'User Warning',
+ E_USER_NOTICE => 'User Notice',
+ E_STRICT => 'Runtime Notice'
+ );
+
+
+ /**
+ * Constructor
+ *
+ */
+ function CI_Exceptions()
+ {
+ log_message('debug', "Output Class Initialized");
+ }
+ // END CI_Exceptions()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Exception Logger
+ *
+ * This function logs PHP generated error messages
+ *
+ * @access private
+ * @param string the error severity
+ * @param string the error string
+ * @param string the error filepath
+ * @param string the error line number
+ * @return string
+ */
+ function log_exception($severity, $message, $filepath, $line)
+ {
+ $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity];
+
+ log_message('error', 'Severity: '.$severity.' '.$severity.' --> '.$message. ' '.$filepath.' '.$line, TRUE);
+ }
+ // END log_exception()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 404 Page Not Found Handler
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function show_404($page = '')
+ {
+ $heading = "404 Page Not Found";
+ $message = "The page you requested was not found.";
+
+ log_message('error', '404 Page Not Found --> '.$page);
+ echo $this->show_error($heading, $message, 'error_404');
+ exit;
+ }
+ // END show_404()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * General Error Page
+ *
+ * This function takes an error message as input
+ * (either as a string or an array) and displayes
+ * it using the specified template.
+ *
+ * @access private
+ * @param string the heading
+ * @param string the message
+ * @param string the template name
+ * @return string
+ */
+ function show_error($heading, $message, $template = 'error_general')
+ {
+ $message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
+
+ ob_start();
+ include_once(APPPATH.'errors/'.$template.EXT);
+ $buffer = ob_get_contents();
+ ob_end_clean();
+ return $buffer;
+ }
+ // END show_error()
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Native PHP error handler
+ *
+ * @access private
+ * @param string the error severity
+ * @param string the error string
+ * @param string the error filepath
+ * @param string the error line number
+ * @return string
+ */
+ function show_php_error($severity, $message, $filepath, $line)
+ {
+ $severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity];
+
+ $filepath = str_replace("\\", "/", $filepath);
+
+ // For safety reasons we do not show the full file path
+ if (FALSE !== strpos($filepath, '/'))
+ {
+ $x = explode('/', $filepath);
+ $filepath = $x[count($x)-2].'/'.end($x);
+ }
+
+ ob_start();
+ include_once(APPPATH.'errors/error_php'.EXT);
+ $buffer = ob_get_contents();
+ ob_end_clean();
+ echo $buffer;
+ }
+ // END show_php_error()
+
+// END Exceptions Class
+}
+?> \ No newline at end of file
diff --git a/system/libraries/Hooks.php b/system/libraries/Hooks.php
new file mode 100644
index 000000000..389e7ac14
--- /dev/null
+++ b/system/libraries/Hooks.php
@@ -0,0 +1,237 @@
+<?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 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 Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/encryption.html
+ */
+class CI_Hooks {
+
+ var $enabled = FALSE;
+ var $hooks = array();
+ var $in_progress = FALSE;
+
+ /**
+ * Constructor
+ *
+ */
+ function CI_Hooks()
+ {
+ log_message('debug', "Hooks Class Initialized");
+
+ $CFG =& _load_class('CI_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;
+ }
+ // END CI_Hooks()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Does a given hook exist?
+ *
+ * Returns TRUE/FALSE based on whether a given hook exists
+ *
+ * @access private
+ * @param string
+ * @return bool
+ */
+ function _hook_exists($which = '')
+ {
+ if ( ! $this->enabled)
+ {
+ return FALSE;
+ }
+
+ if ( ! isset($this->hooks[$which]))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ // END hook_exists()
+
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Call Hook
+ *
+ * Calls a particular hook
+ *
+ * @access private
+ * @param string the hook name
+ * @return mixed
+ */
+ function _call_hook($which = '')
+ {
+ 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]);
+ }
+ }
+ // END hook_exists()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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
+ // extension 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 _run_hook()
+
+
+}
+
+// END CI_Hooks class
+?> \ No newline at end of file
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
new file mode 100644
index 000000000..854f0484b
--- /dev/null
+++ b/system/libraries/Image_lib.php
@@ -0,0 +1,1550 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Image Manipulation class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Image_lib
+ * @author Rick Ellis
+ * @link http://www.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");
+ }
+ // END CI_Image_lib()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 = '';
+ }
+ }
+ // END clear()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * initialize image preferences
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function initialize($props = array())
+ {
+ /*
+ * Convert array elements into class variables
+ */
+ if (count($props) > 0)
+ {
+ foreach ($props as $key => $val)
+ {
+ $this->$key = $val;
+ }
+ }
+
+ /*
+ * Is there a source image?
+ *
+ * If not, there's no reason to continue
+ *
+ */
+ if ($this->source_image == '')
+ {
+ $this->set_error('imglib_source_image_required');
+ return FALSE;
+ }
+ /*
+ * Is getimagesize() Available?
+ *
+ * We use it to determine the image properties (width/height).
+ * Note: We need to figure out how to determine image
+ * properties using ImageMagick and NetPBM
+ *
+ */
+ if ( ! function_exists('getimagesize'))
+ {
+ $this->set_error('imglib_gd_required_for_props');
+ return FALSE;
+ }
+
+ $this->image_library = strtolower($this->image_library);
+
+ /*
+ * Set the full server path
+ *
+ * The source image may or may not contain a path.
+ * Either way, we'll try use realpath to generate the
+ * full server path in order to more reliably read it.
+ *
+ */
+ if (function_exists('realpath') AND @realpath($this->source_image) !== FALSE)
+ {
+ $full_source_path = str_replace("\\", "/", realpath($this->source_image));
+ }
+ else
+ {
+ $full_source_path = $this->source_image;
+ }
+
+ $x = explode('/', $full_source_path);
+ $this->source_image = end($x);
+ $this->source_folder = str_replace($this->source_image, '', $full_source_path);
+
+ // Set the Image Propterties
+ 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 ! ctype_digit($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;
+ }
+ // END initialize()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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');
+ }
+ // END 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');
+ }
+ // END 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))
+ {
+ $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();
+ }
+ }
+ // END rotate()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 ($action == 'crop')
+ {
+ // If the target width/height match the source then it's pointless to crop, right?
+ if ($this->width >= $this->orig_width AND $this->height >= $this->orig_width)
+ {
+ // We'll return true so the user thinks the process succeeded.
+ // It'll be our little secret...
+
+ return TRUE;
+ }
+
+ // 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 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
+ if (($this->orig_width == $this->width AND $this->orig_height == $this->height) AND ($this->source_image != $this->dest_image))
+ {
+ if ( ! @copy($this->full_src_path, $this->full_dst_path))
+ {
+ $this->set_error('imglib_copy_failed');
+ return FALSE;
+ }
+
+ @chmod($this->full_dst_path, 0777);
+ return TRUE;
+ }
+
+ // 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
+ if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor') AND $v2_override == FALSE)
+ {
+ $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, 0777);
+
+ return TRUE;
+ }
+ // END image_process_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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, 0777);
+
+ return TRUE;
+ }
+ // END image_process_imagemagick()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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($dst_image, 0777);
+
+ return TRUE;
+ }
+ // END image_process_netpbm()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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, 0777);
+
+ return true;
+ }
+ // END image_rotate_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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, 0777);
+
+ return TRUE;
+ }
+ // END image_mirror_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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();
+ }
+ }
+ // END image_mirror_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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
+ 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;
+ }
+ // END overlay_watermark()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END text_watermark()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END image_create_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write imge 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;
+ }
+ // END image_save_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Dynamically ouputs 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;
+ }
+ }
+ // END image_display_gd()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Reproportion 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 reproportion 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;
+ }
+ }
+ }
+ // END image_reproportion()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END get_image_properties()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END size_calculator()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END explode_name()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Is GD Installed?
+ *
+ * @access public
+ * @return bool
+ */
+ function gd_loaded()
+ {
+ if ( ! extension_loaded('gd'))
+ {
+ if ( ! dl('gd.so'))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+ // END gd_loaded()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END gd_version()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set error message
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_error($msg)
+ {
+ $obj =& get_instance();
+ $obj->lang->load('imglib');
+
+ if (is_array($msg))
+ {
+ foreach ($msg as $val)
+ {
+
+ $msg = ($obj->lang->line($val) == FALSE) ? $val : $obj->lang->line($val);
+ $this->error_msg[] = $msg;
+ log_message('error', $msg);
+ }
+ }
+ else
+ {
+ $msg = ($obj->lang->line($msg) == FALSE) ? $msg : $obj->lang->line($msg);
+ $this->error_msg[] = $msg;
+ log_message('error', $msg);
+ }
+ }
+ // END set_error()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 display_errors()
+}
+// END Image_lib Class
+?> \ No newline at end of file
diff --git a/system/libraries/Input.php b/system/libraries/Input.php
new file mode 100644
index 000000000..6aba5dd43
--- /dev/null
+++ b/system/libraries/Input.php
@@ -0,0 +1,585 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Input Class
+ *
+ * Pre-processes global input data for security
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Input
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/input.html
+ */
+class CI_Input {
+ var $use_xss_clean = FALSE;
+ var $ip_address = FALSE;
+ var $user_agent = FALSE;
+ var $allow_get_array = FALSE;
+
+ /**
+ * Constructor
+ *
+ * Sets whether to globally enable the XSS processing
+ * and whether to allow the $_GET array
+ *
+ * @access public
+ */
+ function CI_Input()
+ {
+ $CFG =& _load_class('CI_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;
+
+ log_message('debug', "Input Class Initialized");
+ $this->_sanitize_globals();
+ }
+ // END CI_Input()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Sanitize Globals
+ *
+ * This function does the folowing:
+ *
+ * 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()
+ {
+ // Unset globals. This is effectively the same as register_globals = off
+ foreach (array($_GET, $_POST, $_COOKIE) as $global)
+ {
+ if ( ! is_array($global))
+ {
+ unset($$global);
+ }
+ else
+ {
+ foreach ($global as $key => $val)
+ {
+ unset($$key);
+ }
+ }
+ }
+
+ // Is $_GET data allowed?
+ if ($this->allow_get_array == FALSE)
+ {
+ $_GET = array();
+ }
+
+ // Clean $_POST Data
+ if (is_array($_POST) AND count($_POST) > 0)
+ {
+ foreach($_POST as $key => $val)
+ {
+ if (is_array($val))
+ {
+ foreach($val as $k => $v)
+ {
+ $_POST[$this->_clean_input_keys($key)][$this->_clean_input_keys($k)] = $this->_clean_input_data($v);
+ }
+ }
+ else
+ {
+ $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+ }
+ }
+ }
+
+ // Clean $_COOKIE Data
+ if (is_array($_COOKIE) AND count($_COOKIE) > 0)
+ {
+ foreach($_COOKIE as $key => $val)
+ {
+ $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+ }
+ }
+
+ log_message('debug', "Global POST and COOKIE data sanitized");
+ }
+ // END _sanitize_globals()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Clean Intput 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[$key] = $this->_clean_input_data($val);
+ }
+ return $new_array;
+ }
+
+ if ($this->use_xss_clean === TRUE)
+ {
+ $str = $this->xss_clean($str);
+ }
+
+ return preg_replace("/\015\012|\015|\012/", "\n", $str);
+ }
+ // END _clean_input_data()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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: '.$str);
+ }
+
+ if ( ! get_magic_quotes_gpc())
+ {
+ return addslashes($str);
+ }
+
+ return $str;
+ }
+ // END _clean_input_keys()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the POST array
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function post($index = '', $xss_clean = FALSE)
+ {
+ if ( ! isset($_POST[$index]))
+ {
+ return FALSE;
+ }
+ else
+ {
+ if ($xss_clean === TRUE)
+ {
+ return $this->xss_clean($_POST[$index]);
+ }
+ else
+ {
+ return $_POST[$index];
+ }
+ }
+ }
+ // END post()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch an item from the COOKIE array
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function cookie($index = '', $xss_clean = FALSE)
+ {
+ if ( ! isset($_COOKIE[$index]))
+ {
+ return FALSE;
+ }
+ else
+ {
+ if ($xss_clean === TRUE)
+ {
+ return $this->xss_clean($_COOKIE[$index]);
+ }
+ else
+ {
+ return $_COOKIE[$index];
+ }
+ }
+ }
+ // END cookie()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the IP Address
+ *
+ * @access public
+ * @return string
+ */
+ function ip_address()
+ {
+ if ($this->ip_address !== FALSE)
+ {
+ return $this->ip_address;
+ }
+
+ $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_address = $cip;
+ elseif ($rip) $this->ip_address = $rip;
+ elseif ($cip) $this->ip_address = $cip;
+ elseif ($fip) $this->ip_address = $fip;
+
+ 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';
+ }
+
+ unset($cip);
+ unset($rip);
+ unset($fip);
+
+ return $this->ip_address;
+ }
+ // END ip_address()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Validate IP Address
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function valid_ip($ip)
+ {
+ return ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)) ? FALSE : TRUE;
+ }
+ // END valid_ip()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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;
+ }
+ // END user_agent()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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, $charset = 'ISO-8859-1')
+ {
+ /*
+ * Remove Null Characters
+ *
+ * This prevents sandwiching null characters
+ * between ascii characters, like Java\0script.
+ *
+ */
+ $str = preg_replace('/\0+/', '', $str);
+ $str = preg_replace('/(\\\\0)+/', '', $str);
+
+ /*
+ * Validate standard character entites
+ *
+ * Add a semicolon if missing. We do this to enable
+ * the conversion of entities to ASCII later.
+ *
+ */
+ $str = preg_replace('#(&\#*\w+)[\x00-\x20]+;#u',"\\1;",$str);
+
+ /*
+ * Validate UTF16 two byte encodeing (x00)
+ *
+ * Just as above, adds a semicolon if missing.
+ *
+ */
+ $str = preg_replace('#(&\#x*)([0-9A-F]+);*#iu',"\\1\\2;",$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: Normally urldecode() would be easier but it removes plus signs
+ *
+ */
+ $str = preg_replace("/%u0([a-z0-9]{3})/i", "&#x\\1;", $str);
+ $str = preg_replace("/%([a-z0-9]{2})/i", "&#x\\1;", $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.
+ *
+ */
+
+ if (preg_match_all("/<(.+?)>/si", $str, $matches))
+ {
+ for ($i = 0; $i < count($matches['0']); $i++)
+ {
+ $str = str_replace($matches['1'][$i],
+ $this->_html_entity_decode($matches['1'][$i], $charset),
+ $str);
+ }
+ }
+
+ /*
+ * Convert all tabs to spaces
+ *
+ * This prevents strings like this: ja vascript
+ * Note: we deal with spaces between characters later.
+ *
+ */
+ $str = preg_replace("#\t+#", " ", $str);
+
+ /*
+ * Makes PHP tags safe
+ *
+ * Note: XML tags are inadvertently replaced too:
+ *
+ * <?xml
+ *
+ * But it doesn't seem to pose a problem.
+ *
+ */
+ $str = str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str); // <?php BBEdit bug fix
+
+ /*
+ * 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', 'vbscript', 'script', 'applet', 'alert', 'document', 'write', 'cookie', 'window');
+ foreach ($words as $word)
+ {
+ $temp = '';
+ for ($i = 0; $i < strlen($word); $i++)
+ {
+ $temp .= substr($word, $i, 1)."\s*";
+ }
+
+ $temp = substr($temp, 0, -3);
+ $str = preg_replace('#'.$temp.'#s', $word, $str);
+ $str = preg_replace('#'.ucfirst($temp).'#s', ucfirst($word), $str);
+ }
+
+ /*
+ * Remove disallowed Javascript in links or img tags
+ */
+ $str = preg_replace("#<a.+?href=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>.*?</a>#si", "", $str);
+ $str = preg_replace("#<img.+?src=.*?(alert\(|alert&\#40;|javascript\:|window\.|document\.|\.cookie|<script|<xss).*?\>#si", "", $str);
+ $str = preg_replace("#<(script|xss).*?\>#si", "", $str);
+
+ /*
+ * 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 unlkely to be a problem.
+ *
+ */
+ $str = preg_replace('#(<[^>]+.*?)(onblur|onchange|onclick|onfocus|onload|onmouseover|onmouseup|onmousedown|onselect|onsubmit|onunload|onkeypress|onkeydown|onkeyup|onresize)[^>]*>#iU',"\\1>",$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;
+ *
+ */
+ $str = preg_replace('#<(/*\s*)(alert|applet|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|layer|link|meta|object|plaintext|style|script|textarea|title|xml|xss)([^>]*)>#is', "&lt;\\1\\2\\3&gt;", $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 unexecutable.
+ *
+ * For example: eval('some code')
+ * Becomes: eval&#40;'some code'&#41;
+ *
+ */
+ $str = preg_replace('#(alert|cmd|passthru|eval|exec|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
+ *
+ */
+ $bad = array(
+ 'document.cookie' => '',
+ 'document.write' => '',
+ 'window.location' => '',
+ "javascript\s*:" => '',
+ "Redirect\s+302" => '',
+ '<!--' => '&lt;!--',
+ '-->' => '--&gt;'
+ );
+
+ foreach ($bad as $key => $val)
+ {
+ $str = preg_replace("#".$key."#i", $val, $str);
+ }
+
+
+ log_message('debug', "XSS Filtering completed");
+ return $str;
+ }
+ // END xss_clean()
+
+
+ /**
+ * 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='ISO-8859-1')
+ {
+ 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-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-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;
+ }
+
+}
+// END Input class
+?> \ No newline at end of file
diff --git a/system/libraries/Language.php b/system/libraries/Language.php
new file mode 100644
index 000000000..b668aa060
--- /dev/null
+++ b/system/libraries/Language.php
@@ -0,0 +1,113 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Language Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Language
+ * @author Rick Ellis
+ * @link http://www.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");
+ }
+ // END CI_Language()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load a language file
+ *
+ * @access public
+ * @param mixed the name of the language file to be loaded. Can be an array
+ * @param string the language (english, etc.)
+ * @return void
+ */
+ function load($langfile = '', $idiom = '', $return = FALSE)
+ {
+ $langfile = str_replace(EXT, '', str_replace('_lang.', '', $langfile)).'_lang'.EXT;
+
+ if (in_array($langfile, $this->is_loaded))
+ {
+ return;
+ }
+
+ if ($idiom == '')
+ {
+ $obj =& get_instance();
+ $deft_lang = $obj->config->item('language');
+ $idiom = ($deft_lang == '') ? 'english' : $deft_lang;
+ }
+
+ if ( ! file_exists(BASEPATH.'language/'.$idiom.'/'.$langfile))
+ {
+ show_error('Unable to load the requested language file: language/'.$langfile.EXT);
+ }
+
+ include_once(BASEPATH.'language/'.$idiom.'/'.$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;
+ }
+ // END load()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a single line of text from the language array
+ *
+ * @access public
+ * @param string the language line
+ * @return string
+ */
+ function line($line = '')
+ {
+ return ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
+ }
+ // END line()
+
+}
+// END Language Class
+?> \ No newline at end of file
diff --git a/system/libraries/Loader.php b/system/libraries/Loader.php
new file mode 100644
index 000000000..e2467fa64
--- /dev/null
+++ b/system/libraries/Loader.php
@@ -0,0 +1,611 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Loader Class
+ *
+ * Loads views and files
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @author Rick Ellis
+ * @category Loader
+ * @link http://www.codeigniter.com/user_guide/libraries/loader.html
+ */
+class CI_Loader {
+
+ var $ob_level;
+ var $cached_vars = array();
+ var $helpers = array();
+ var $plugins = array();
+ var $scripts = array();
+ var $languages = array();
+ var $view_path = '';
+
+ /**
+ * Constructor
+ *
+ * Sets the path to the view files and gets the initial output
+ * buffering level
+ *
+ * @access public
+ */
+ function CI_Loader()
+ {
+ $this->view_path = APPPATH.'views/';
+ $this->ob_level = ob_get_level();
+
+ log_message('debug', "Loader Class Initialized");
+ }
+ // END CI_Loader()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class Loader
+ *
+ * This function lets users load and instantiate classes.
+ * It is designed to be called from a user's app controllers.
+ *
+ * @access public
+ * @param string the name of the class
+ * @param mixed any initialization parameters
+ * @return void
+ */
+ function library($class, $param = FALSE)
+ {
+ if ($class == '')
+ return;
+
+ $obj =& get_instance();
+ $obj->_ci_initialize($class, $param);
+ $obj->_ci_assign_to_models();
+ }
+ // END library()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Model Loader
+ *
+ * This function lets users load and instantiate models.
+ *
+ * @access public
+ * @param string the name of the class
+ * @param mixed any initialization parameters
+ * @return void
+ */
+ function model($model, $name = '', $db_conn = FALSE)
+ {
+ if ($model == '')
+ return;
+
+ $obj =& get_instance();
+ $obj->_ci_load_model($model, $name, $db_conn);
+ }
+ // END library()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database Loader
+ *
+ * @access public
+ * @param string the DB credentials
+ * @param bool whether to return the DB object
+ * @param bool whether to enable active record (this allows us to override the config setting)
+ * @return mixed
+ */
+ function database($db = '', $return = FALSE, $active_record = FALSE)
+ {
+ $obj =& get_instance();
+
+ if ($return === TRUE)
+ {
+ return $obj->_ci_init_database($db, TRUE, $active_record);
+ }
+ else
+ {
+ $obj->_ci_init_database($db, FALSE, $active_record);
+ $obj->_ci_assign_to_models();
+ }
+ }
+ // END database()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Scaffolding Loader
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function scaffolding($table = '')
+ {
+ if ($table == FALSE)
+ {
+ show_error('You must include the name of the table you would like access when you initialize scaffolding');
+ }
+
+ $obj =& get_instance();
+ $obj->_ci_init_scaffolding($table);
+ }
+ // END scaffolding()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load View
+ *
+ * This function is used to load a "view" file. It has three parameters:
+ *
+ * 1. The name of the "view" file to be included.
+ * 2. An associative array of data to be extracted for use in the view.
+ * 3. TRUE/FALSE - whether to return the data or load it. In
+ * some cases it's advantageous to be able to retun data so that
+ * a developer can process it in some way.
+ *
+ * @access public
+ * @param string
+ * @param array
+ * @param bool
+ * @return void
+ */
+ function view($view, $vars = array(), $return = FALSE)
+ {
+ return $this->_ci_load(array('view' => $view, 'vars' => $this->_ci_object_to_array($vars), 'return' => $return));
+ }
+ // END view()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load File
+ *
+ * This is a generic file loader
+ *
+ * @access public
+ * @param string
+ * @param bool
+ * @return string
+ */
+ function file($path, $return = FALSE)
+ {
+ return $this->_ci_load(array('path' => $path, 'return' => $return));
+ }
+ // END file()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Variables
+ *
+ * Once variables are set they become availabe within
+ * the controller class and its "view" files.
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function vars($vars = array())
+ {
+ $vars = $this->_ci_object_to_array($vars);
+
+ if (is_array($vars) AND count($vars) > 0)
+ {
+ foreach ($vars as $key => $val)
+ {
+ $this->cached_vars[$key] = $val;
+ }
+ }
+ }
+ // END vars()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Helper
+ *
+ * This function loads the specified helper file.
+ *
+ * @access public
+ * @param mixed
+ * @return void
+ */
+ function helper($helpers = array())
+ {
+ if ( ! is_array($helpers))
+ {
+ $helpers = array($helpers);
+ }
+
+ foreach ($helpers as $helper)
+ {
+ if (isset($this->helpers[$helper]))
+ {
+ continue;
+ }
+
+ $helper = strtolower(str_replace(EXT, '', str_replace('_helper', '', $helper)).'_helper');
+
+ if ( ! file_exists(BASEPATH.'helpers/'.$helper.EXT))
+ {
+ show_error('Unable to load the requested file: helpers/'.$helper.EXT);
+ }
+
+ include_once(BASEPATH.'helpers/'.$helper.EXT);
+
+ $this->helpers[$helper] = TRUE;
+ }
+
+ log_message('debug', 'Helpers loaded: '.implode(', ', $helpers));
+ }
+ // END helper()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Helpers
+ *
+ * This is simply an alias to the above function in case the
+ * user has written the plural form of this function.
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function helpers($helpers = array())
+ {
+ $this->helper($helpers);
+ }
+ // END helpers()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Plugin
+ *
+ * This function loads the specified plugin.
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function plugin($plugins = array())
+ {
+ if ( ! is_array($plugins))
+ {
+ $plugins = array($plugins);
+ }
+
+ foreach ($plugins as $plugin)
+ {
+ if (isset($this->plugins[$plugin]))
+ {
+ continue;
+ }
+
+ $plugin = strtolower(str_replace(EXT, '', str_replace('_plugin.', '', $plugin)).'_pi');
+
+ if ( ! file_exists(BASEPATH.'plugins/'.$plugin.EXT))
+ {
+ show_error('Unable to load the requested file: plugins/'.$plugin.EXT);
+ }
+
+ include_once(BASEPATH.'plugins/'.$plugin.EXT);
+
+ $this->plugins[$plugin] = TRUE;
+ }
+
+ log_message('debug', 'Plugins loaded: '.implode(', ', $plugins));
+ }
+ // END plugin()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Script
+ *
+ * This function loads the specified include file from the
+ * application/scripts/ folder
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function script($scripts = array())
+ {
+ if ( ! is_array($scripts))
+ {
+ $scripts = array($scripts);
+ }
+
+ foreach ($scripts as $script)
+ {
+ if (isset($this->scripts[$script]))
+ {
+ continue;
+ }
+
+ $script = strtolower(str_replace(EXT, '', $script));
+
+ if ( ! file_exists(APPPATH.'scripts/'.$script.EXT))
+ {
+ show_error('Unable to load the requested script: scripts/'.$script.EXT);
+ }
+
+ include_once(APPPATH.'scripts/'.$script.EXT);
+
+ $this->scripts[$script] = TRUE;
+ }
+
+ log_message('debug', 'Scripts loaded: '.implode(', ', $scripts));
+ }
+ // END script()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Load Plugins
+ *
+ * This is simply an alias to the above function in case the
+ * user has written the plural form of this function.
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function plugins($plugins = array())
+ {
+ $this->plugin($plugins);
+ }
+ // END plugins()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Loads a language file
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function language($file = '', $lang = '', $return = FALSE)
+ {
+ $obj =& get_instance();
+ return $obj->lang->load($file, $lang, $return);
+ }
+ // END language()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Loads a config file
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function config($file = '')
+ {
+ $obj =& get_instance();
+ $obj->config->load($file);
+ }
+ // END config()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the Path to the "views" folder
+ *
+ * @access private
+ * @param string
+ * @return void
+ */
+ function _ci_set_view_path($path)
+ {
+ $this->view_path = $path;
+ }
+ // END _ci_set_view_path()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Loader
+ *
+ * This function isn't called directly. It's called from
+ * the two functions above. It's used to load views and files
+ *
+ * @access private
+ * @param array
+ * @return void
+ */
+ function _ci_load($data)
+ {
+ $OUT =& _load_class('CI_Output');
+
+ // This allows anything loaded using $this->load (viwes, files, etc.)
+ // to become accessible from within the Controller and Model functions.
+ $obj =& get_instance();
+ foreach ($obj->ci_is_loaded as $val)
+ {
+ if ( ! isset($this->$val))
+ {
+ $this->$val =& $obj->$val;
+ }
+ }
+
+ // Set the default data variables
+ foreach (array('view', 'vars', 'path', 'return') as $val)
+ {
+ $$val = ( ! isset($data[$val])) ? FALSE : $data[$val];
+ }
+
+ /*
+ * Extract and cached variables
+ *
+ * You can either set variables using the dedicated
+ * $this->load_vars() function or via the second
+ * parameter of this function. We'll
+ * merge the two types and cache them so that
+ * views that are embedded within other views
+ * can have access to these variables.
+ *
+ */
+
+ if (is_array($vars))
+ {
+ $this->cached_vars = array_merge($this->cached_vars, $vars);
+ }
+ extract($this->cached_vars);
+
+ // Set the path to the requested file
+ if ($path == '')
+ {
+ $ext = pathinfo($view, PATHINFO_EXTENSION);
+ $file = ($ext == '') ? $view.EXT : $view;
+ $path = $this->view_path.$file;
+ }
+ else
+ {
+ $x = explode('/', $path);
+ $file = end($x);
+ }
+
+ /*
+ * Buffer the output
+ *
+ * We buffer the output for two reasons:
+ * 1. Speed. You get a significant speed boost.
+ * 2. So that the final rendered template can be
+ * post-processed by the output class. Why do we
+ * need post processing? For one thing, in order to
+ * show the elapsed page load time. Unless we
+ * can intercept the content right before it's sent to
+ * the browser and then stop the timer, it won't be acurate.
+ *
+ */
+
+ if ( ! file_exists($path))
+ {
+ show_error('Unable to load the requested file: '.$file);
+ }
+
+ ob_start();
+
+ include($path);
+ log_message('debug', 'File loaded: '.$path);
+
+ // Return the file data if requested to
+ if ($return === TRUE)
+ {
+ $buffer = ob_get_contents();
+ ob_end_clean();
+
+ return $buffer;
+ }
+
+ /*
+ * Flush the buffer... or buff the flusher?
+ *
+ * In order to permit templates (views) to be nested within
+ * other views, we need to flush the content back out whenever
+ * we are beyond the first level of output buffering so that
+ * it can be seen and included properly by the first included
+ * template and any subsequent ones. Oy!
+ *
+ */
+ if (ob_get_level() > $this->ob_level + 1)
+ {
+ ob_end_flush();
+ }
+ else
+ {
+ $OUT->set_output(ob_get_contents());
+ ob_end_clean();
+ }
+ }
+ // END _load()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Autoloader
+ *
+ * The config/autoload.php file contains an array that permits sub-systems,
+ * plugins, and helpers to be loaded automatically.
+ *
+ * @access private
+ * @param array
+ * @return void
+ */
+ function _ci_autoloader($autoload)
+ {
+ if ($autoload === FALSE)
+ {
+ return;
+ }
+
+ foreach (array('helper', 'plugin', 'script') as $type)
+ {
+ if (isset($autoload[$type]))
+ {
+ if ( ! is_array($autoload[$type]))
+ {
+ $autoload[$type] = array($autoload[$type]);
+ }
+
+ foreach ($autoload[$type] as $item)
+ {
+ $this->$type($item);
+ }
+ }
+ }
+ }
+ // END _ci_autoloader()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Object to Array
+ *
+ * Takes an object as input and convers the class variables to array key/vals
+ *
+ * @access public
+ * @param object
+ * @return array
+ */
+ function _ci_object_to_array($object)
+ {
+ if ( ! is_object($object))
+ {
+ return $object;
+ }
+
+ $array = array();
+ foreach (get_object_vars($object) as $key => $val)
+ {
+ $array[$key] = $val;
+ }
+
+ return $array;
+ }
+
+}
+// END Loader Class
+?> \ No newline at end of file
diff --git a/system/libraries/Log.php b/system/libraries/Log.php
new file mode 100644
index 000000000..35e30b64c
--- /dev/null
+++ b/system/libraries/Log.php
@@ -0,0 +1,117 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Logging Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Logging
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/general/errors.html
+ */
+class CI_Log {
+
+ var $log_path;
+ var $_threshold = 1;
+ var $_date_fmt = 'Y-m-d H:i:s';
+ var $_enabled = TRUE;
+ var $_levels = array('ERROR' => '1', 'DEBUG' => '2', 'INFO' => '3', 'ALL' => '4');
+
+ /**
+ * Constructor
+ *
+ * @access public
+ * @param string the log file path
+ * @param string the error threshold
+ * @param string the date formatting codes
+ */
+ function CI_Log($path = '', $threshold = '', $date_fmt = '')
+ {
+ $this->log_path = ($path != '') ? $path : BASEPATH.'logs/';
+
+ if ( ! is_dir($this->log_path) OR ! is_writable($this->log_path))
+ {
+ $this->_enabled = FALSE;
+ }
+
+ if (ctype_digit($threshold))
+ {
+ $this->_threshold = $threshold;
+ }
+
+ if ($date_fmt != '')
+ {
+ $this->_date_fmt = $date_fmt;
+ }
+ }
+ // END CI_Log()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write Log File
+ *
+ * Generally this function will be called using the global log_message() function
+ *
+ * @access public
+ * @param string the error level
+ * @param string the error message
+ * @param bool whether the error is a native PHP error
+ * @return bool
+ */
+ function write_log($level = 'error', $msg, $php_error = FALSE)
+ {
+ if ($this->_enabled === FALSE)
+ {
+ return FALSE;
+ }
+
+ $level = strtoupper($level);
+
+ if ( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
+ {
+ return FALSE;
+ }
+
+ $filepath = $this->log_path.'log-'.date('Y-m-d').'.php';
+ $message = '';
+
+ if ( ! file_exists($filepath))
+ {
+ $message .= "<"."?php if (!defined('BASEPATH')) exit('No direct script access allowed'); ?".">\n\n";
+ }
+
+ if ( ! $fp = @fopen($filepath, "a"))
+ {
+ return FALSE;
+ }
+
+ $message .= $level.' '.(($level == 'INFO') ? ' -' : '-').' '.date($this->_date_fmt). ' --> '.$msg."\n";
+
+ flock($fp, LOCK_EX);
+ fwrite($fp, $message);
+ flock($fp, LOCK_UN);
+ fclose($fp);
+
+ @chmod($filepath, 0666);
+ return TRUE;
+ }
+ // END write_log()
+}
+// END Log Class
+?> \ No newline at end of file
diff --git a/system/libraries/Model.php b/system/libraries/Model.php
new file mode 100644
index 000000000..9834f8278
--- /dev/null
+++ b/system/libraries/Model.php
@@ -0,0 +1,72 @@
+<?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 Model Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/config.html
+ */
+class Model {
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function Model()
+ {
+ $this->_assign_libraries(FALSE);
+ log_message('debug', "Model Class Initialized");
+ }
+ // END Model()
+
+ /**
+ * Assign Libraries
+ *
+ * Creates local references to all currently instantiated objects
+ * so that any syntax that can be legally used in a controller
+ * can be used within models.
+ *
+ * @access private
+ */
+ function _assign_libraries($use_reference = TRUE)
+ {
+ $obj =& get_instance();
+ foreach ($obj->ci_is_loaded as $val)
+ {
+ if ( ! isset($this->$val))
+ {
+ if ($use_reference === TRUE)
+ {
+ $this->$val =& $obj->$val;
+ }
+ else
+ {
+ $this->$val = $obj->$val;
+ }
+ }
+ }
+ }
+ // END _assign_libraries()
+
+}
+// END Model Class
+?> \ No newline at end of file
diff --git a/system/libraries/Output.php b/system/libraries/Output.php
new file mode 100644
index 000000000..f5db3e0d0
--- /dev/null
+++ b/system/libraries/Output.php
@@ -0,0 +1,241 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Output Class
+ *
+ * Responsible for sending final output to browser
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Output
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/output.html
+ */
+class CI_Output {
+
+ var $final_output;
+ var $cache_expiration = 0;
+
+ function CI_Output()
+ {
+ log_message('debug', "Output Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Output
+ *
+ * Returns the current output string
+ *
+ * @access public
+ * @return string
+ */
+ function get_output()
+ {
+ return $this->final_output;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Output
+ *
+ * Sets the output string
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_output($output)
+ {
+ $this->final_output = $output;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Cache
+ *
+ * @access public
+ * @param integer
+ * @return void
+ */
+ function cache($time)
+ {
+ $this->cache_expiration = ( ! ctype_digit($time)) ? 0 : $time;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Display Output
+ *
+ * All "view" data is automatically put into this variable
+ * by the controller class:
+ *
+ * $this->final_output
+ *
+ * This function simply echos the variable out. It also does the following:
+ *
+ * Stops the benchmark timer so the page rendering speed can be shown.
+ *
+ * Determines if the "memory_get_usage' function is available so that
+ * the memory usage can be shown.
+ *
+ * @access public
+ * @return void
+ */
+ function _display($output = '')
+ {
+ $BM =& _load_class('CI_Benchmark');
+
+ if ($output == '')
+ {
+ $output =& $this->final_output;
+ }
+
+ if ($this->cache_expiration > 0)
+ {
+ $this->_write_cache($output);
+ }
+
+ $elapsed = $BM->elapsed_time('code_igniter_start', 'code_igniter_end');
+ $memory = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB';
+
+ $output = str_replace('{memory_usage}', $memory, $output);
+ $output = str_replace('{elapsed_time}', $elapsed, $output);
+
+ echo $output;
+
+ log_message('debug', "Final output sent to browser");
+ log_message('debug', "Total execution time: ".$elapsed);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write a Cache File
+ *
+ * @access public
+ * @return void
+ */
+ function _write_cache($output)
+ {
+ $obj =& get_instance();
+ $path = $obj->config->item('cache_path');
+
+ $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
+
+ if ( ! is_dir($cache_path) OR ! is_writable($cache_path))
+ {
+ return;
+ }
+
+ $uri = $obj->config->item('base_url', 1).
+ $obj->config->item('index_page').
+ $obj->uri->uri_string();
+
+ $cache_path .= md5($uri);
+
+ if ( ! $fp = @fopen($cache_path, 'wb'))
+ {
+ log_message('error', "Unable to write ache file: ".$cache_path);
+ return;
+ }
+
+ $expire = time() + ($this->cache_expiration * 60);
+
+ flock($fp, LOCK_EX);
+ fwrite($fp, $expire.'TS--->'.$output);
+ flock($fp, LOCK_UN);
+ fclose($fp);
+ @chmod($cache_path, 0777);
+
+ log_message('debug', "Cache file written: ".$cache_path);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update/serve a cached file
+ *
+ * @access public
+ * @return void
+ */
+ function _display_cache()
+ {
+ $CFG =& _load_class('CI_Config');
+ $RTR =& _load_class('CI_Router');
+
+ $cache_path = ($CFG->item('cache_path') == '') ? BASEPATH.'cache/' : $CFG->item('cache_path');
+
+ if ( ! is_dir($cache_path) OR ! is_writable($cache_path))
+ {
+ return FALSE;
+ }
+
+ // Build the file path. The file name is an MD5 hash of the full URI
+ $uri = $CFG->item('base_url', 1).$CFG->item('index_page').$RTR->uri_string;
+
+ $filepath = $cache_path.md5($uri);
+
+ if ( ! @file_exists($filepath))
+ {
+ return FALSE;
+ }
+
+ if ( ! $fp = @fopen($filepath, 'rb'))
+ {
+ return FALSE;
+ }
+
+ flock($fp, LOCK_SH);
+
+ $cache = '';
+ if (filesize($filepath) > 0)
+ {
+ $cache = fread($fp, filesize($filepath));
+ }
+
+ flock($fp, LOCK_UN);
+ fclose($fp);
+
+ // Strip out the embedded timestamp
+ if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
+ {
+ return FALSE;
+ }
+
+ // Has the file expired? If so we'll delete it.
+ if (time() >= trim(str_replace('TS--->', '', $match['1'])))
+ {
+ @unlink($filepath);
+ log_message('debug', "Cache file has expired. File deleted");
+ return FALSE;
+ }
+
+ // Display the cache
+ $this->_display(str_replace($match['0'], '', $cache));
+ log_message('debug', "Cache file is current. Sending it to browser.");
+ return TRUE;
+ }
+
+}
+// END Output Class
+?> \ No newline at end of file
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
new file mode 100644
index 000000000..0bbb577a3
--- /dev/null
+++ b/system/libraries/Pagination.php
@@ -0,0 +1,207 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Pagination Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Pagination
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/pagination.html
+ */
+class CI_Pagination {
+
+ var $base_url = ''; // The page we are linking to
+ var $total_rows = ''; // Total number of items (database results)
+ var $per_page = 10; // Max number of items you want shown per page
+ var $num_links = 2; // Number of "digit" links to show before/after the currently viewed page
+ var $cur_page = 0; // The current page being viewed
+ var $first_link = '&lsaquo; First';
+ var $next_link = '&gt;';
+ var $prev_link = '&lt;';
+ var $last_link = 'Last &rsaquo;';
+ var $uri_segment = 3;
+ var $full_tag_open = '';
+ var $full_tag_close = '';
+ var $first_tag_open = '';
+ var $first_tag_close = '&nbsp;';
+ var $last_tag_open = '&nbsp;';
+ var $last_tag_close = '';
+ var $cur_tag_open = '&nbsp;<b>';
+ var $cur_tag_close = '</b>';
+ var $next_tag_open = '&nbsp;';
+ var $next_tag_close = '&nbsp;';
+ var $prev_tag_open = '&nbsp;';
+ var $prev_tag_close = '';
+ var $num_tag_open = '&nbsp;';
+ var $num_tag_close = '';
+
+ /**
+ * Constructor
+ *
+ * @access public
+ * @param array initialization parameters
+ */
+ function CI_Pagination($params = array())
+ {
+ if (count($params) > 0)
+ {
+ $this->initialize($params);
+ }
+
+ log_message('debug', "Pagination Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize Preferences
+ *
+ * @access public
+ * @param array initialization parameters
+ * @return void
+ */
+ function initialize($params = array())
+ {
+ if (count($params) > 0)
+ {
+ foreach ($params as $key => $val)
+ {
+ if (isset($this->$key))
+ {
+ $this->$key = $val;
+ }
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate the pagination links
+ *
+ * @access public
+ * @return string
+ */
+ function create_links()
+ {
+ // If our item count or per-page total is zero there is no need to continue.
+ if ($this->total_rows == 0 OR $this->per_page == 0)
+ {
+ return '';
+ }
+
+ // Calculate the total number of pages
+ $num_pages = intval($this->total_rows / $this->per_page);
+
+ // Use modulus to see if our division has a remainder.If so, add one to our page number.
+ if ($this->total_rows % $this->per_page)
+ {
+ $num_pages++;
+ }
+
+ // Is there only one page? Hm... nothing more to do here then.
+ if ($num_pages == 1)
+ {
+ return '';
+ }
+
+ // Determine the current page number.
+ $obj =& get_instance();
+ if ($obj->uri->segment($this->uri_segment) != 0)
+ {
+ $this->cur_page = $obj->uri->segment($this->uri_segment);
+ }
+
+ if ( ! ctype_digit($this->cur_page))
+ {
+ $this->cur_page = 0;
+ }
+
+ $uri_page_number = $this->cur_page;
+ $this->cur_page = floor(($this->cur_page/$this->per_page) + 1);
+
+ // Calculate the start and end numbers. These determine
+ // which number to start and end the digit links with
+ $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
+ $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;
+
+ // Add a trailing slash to the base URL if needed
+ $this->base_url = preg_replace("/(.+?)\/*$/", "\\1/", $this->base_url);
+
+ // And here we go...
+ $output = '';
+
+ // Render the "First" link
+ if ($this->cur_page > $this->num_links)
+ {
+ $output .= $this->first_tag_open.'<a href="'.$this->base_url.'">'.$this->first_link.'</a>'.$this->first_tag_close;
+ }
+
+ // Render the "previous" link
+ if (($this->cur_page - $this->num_links) >= 0)
+ {
+ $i = $uri_page_number - $this->per_page;
+ if ($i == 0) $i = '';
+ $output .= $this->prev_tag_open.'<a href="'.$this->base_url.$i.'">'.$this->prev_link.'</a>'.$this->prev_tag_close;
+ }
+
+ // Write the digit links
+ for ($loop = $start -1; $loop <= $end; $loop++)
+ {
+ $i = ($loop * $this->per_page) - $this->per_page;
+
+ if ($i >= 0)
+ {
+ if ($this->cur_page == $loop)
+ {
+ $output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page
+ }
+ else
+ {
+ $n = ($i == 0) ? '' : $i;
+ $output .= $this->num_tag_open.'<a href="'.$this->base_url.$n.'">'.$loop.'</a>'.$this->num_tag_close;
+ }
+ }
+ }
+
+ // Render the "next" link
+ if ($this->cur_page < $num_pages)
+ {
+ $output .= $this->next_tag_open.'<a href="'.$this->base_url.($this->cur_page * $this->per_page).'">'.$this->next_link.'</a>'.$this->next_tag_close;
+ }
+
+ // Render the "Last" link
+ if (($this->cur_page + $this->num_links) < $num_pages)
+ {
+ $i = (($num_pages * $this->per_page) - $this->per_page);
+ $output .= $this->last_tag_open.'<a href="'.$this->base_url.$i.'">'.$this->last_link.'</a>'.$this->last_tag_close;
+ }
+
+ // Kill double slashes. Note: Sometimes we can end up with a double slash
+ // in the penultimate link so we'll kill all double shashes.
+ $output = preg_replace("#([^:])//+#", "\\1/", $output);
+
+ // Add the wrapper HTML if exists
+ $output = $this->full_tag_open.$output.$this->full_tag_close;
+
+ return $output;
+ }
+}
+// END Pagination Class
+?> \ No newline at end of file
diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php
new file mode 100644
index 000000000..9f6a814ae
--- /dev/null
+++ b/system/libraries/Parser.php
@@ -0,0 +1,178 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Parser Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Parser
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/parser.html
+ */
+class CI_Parser {
+
+ var $l_delim = '{';
+ var $r_delim = '}';
+ var $object;
+
+ /**
+ * Parse a template
+ *
+ * Parses pseudo-variables contained in the specified template,
+ * replacing them with the data in the second param
+ *
+ * @access public
+ * @param string
+ * @param array
+ * @param bool
+ * @return string
+ */
+ function parse($template, $data, $return = FALSE)
+ {
+ $OUT =& _load_class('CI_Output');
+
+ $obj =& get_instance();
+ $template = $obj->load->view($template, '', TRUE);
+
+ if ($template == '')
+ {
+ return FALSE;
+ }
+
+ foreach ($data as $key => $val)
+ {
+ if ( ! is_array($val))
+ {
+ $template = $this->_parse_single($key, $val, $template);
+ }
+ else
+ {
+ $template = $this->_parse_pair($key, $val, $template);
+ }
+ }
+
+ if ($return == FALSE)
+ {
+ $OUT->final_output = $template;
+ }
+
+ return $template;
+ }
+ // END set_method()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the left/right variable delimiters
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return void
+ */
+ function set_delimiters($l = '{', $r = '}')
+ {
+ $this->l_delim = $l;
+ $this->r_delim = $r;
+ }
+ // END set_method()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse a single key/value
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
+ function _parse_single($key, $val, $string)
+ {
+ return str_replace($this->l_delim.$key.$this->r_delim, $val, $string);
+ }
+ // END set_method()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse a tag pair
+ *
+ * Parses tag pairs: {some_tag} string... {/some_tag}
+ *
+ * @access private
+ * @param string
+ * @param array
+ * @param string
+ * @return string
+ */
+ function _parse_pair($variable, $data, $string)
+ {
+ if (FALSE === ($match = $this->_match_pair($string, $variable)))
+ {
+ return $string;
+ }
+
+ $str = '';
+ foreach ($data as $row)
+ {
+ $temp = $match['1'];
+ foreach ($row as $key => $val)
+ {
+ if ( ! is_array($val))
+ {
+ $temp = $this->_parse_single($key, $val, $temp);
+ }
+ else
+ {
+ $temp = $this->_parse_pair($key, $val, $temp);
+ }
+ }
+
+ $str .= $temp;
+ }
+
+ return str_replace($match['0'], $str, $string);
+ }
+ // END set_method()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Matches a variable pair
+ *
+ * @access private
+ * @param string
+ * @param string
+ * @return mixed
+ */
+ function _match_pair($string, $variable)
+ {
+ if ( ! preg_match("|".$this->l_delim . $variable . $this->r_delim."(.+)".$this->l_delim . '/' . $variable . $this->r_delim."|s", $string, $match))
+ {
+ return FALSE;
+ }
+
+ return $match;
+ }
+ // END _match_pair()
+
+}
+// END Parser Class
+?> \ No newline at end of file
diff --git a/system/libraries/Router.php b/system/libraries/Router.php
new file mode 100644
index 000000000..abc253eff
--- /dev/null
+++ b/system/libraries/Router.php
@@ -0,0 +1,318 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Router Class
+ *
+ * Parses URIs and determines routing
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @author Rick Ellis
+ * @category Libraries
+ * @link http://www.codeigniter.com/user_guide/general/routing.html
+ */
+class CI_Router {
+
+ var $config;
+ var $uri_string = '';
+ var $segments = array();
+ var $routes = array();
+ var $class = '';
+ var $method = 'index';
+ var $uri_protocol = 'auto';
+ var $default_controller;
+ var $scaffolding_request = FALSE; // Must be set to FALSE
+
+ /**
+ * Constructor
+ *
+ * Runs the route mapping function.
+ */
+ function CI_Router()
+ {
+ $this->config =& _load_class('CI_Config');
+ $this->_set_route_mapping();
+ log_message('debug', "Router Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the route mapping
+ *
+ * This function determies what should be served based on the URI request,
+ * as well as any "routes" that have been set in the routing config file.
+ *
+ * @access private
+ * @return void
+ */
+ function _set_route_mapping()
+ {
+ // Are query strings enabled? If so we're done...
+ if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
+ {
+ $this->set_class($_GET[$this->config->item('controller_trigger')]);
+
+ if (isset($_GET[$this->config->item('function_trigger')]))
+ {
+ $this->set_method($_GET[$this->config->item('function_trigger')]);
+ }
+
+ return;
+ }
+
+ // Load the routes.php file
+ include_once(APPPATH.'config/routes'.EXT);
+ $this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
+ unset($route);
+
+ // Set the default controller
+ $this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);
+
+ // Fetch the URI string Depending on the server,
+ // the URI will be available in one of two globals
+ switch ($this->config->item('uri_protocol'))
+ {
+ case 'path_info' : $this->uri_string = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
+ break;
+ case 'query_string' : $this->uri_string = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
+ break;
+ default :
+ $path_info = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
+
+ if ($path_info != '' AND $path_info != "/".SELF)
+ {
+ $this->uri_string = $path_info;
+ }
+ else
+ {
+ $this->uri_string = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
+ }
+ break;
+ }
+
+ // Is there a URI string? If not, the default controller specified
+ // by the admin in the "routes" file will be shown.
+ if ($this->uri_string == '')
+ {
+ if ($this->default_controller === FALSE)
+ {
+ show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");
+ }
+
+ $this->set_class($this->default_controller);
+ $this->set_method('index');
+
+ log_message('debug', "No URI present. Default controller set.");
+ return;
+ }
+
+ // Do we need to remove the suffix specified in the config file?
+ 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.
+ $this->_compile_segments(explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)));
+
+
+ // Remap the class/method if a route exists
+ unset($this->routes['default_controller']);
+
+ if (count($this->routes) > 0)
+ {
+ $this->_parse_routes();
+ }
+ }
+ // END _set_route_mapping()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Compile Segments
+ *
+ * This function takes an array of URI segments as
+ * input, and puts it into the $this->segments array.
+ * It also sets the current class/method
+ *
+ * @access private
+ * @param array
+ * @param bool
+ * @return void
+ */
+ function _compile_segments($segs, $route = FALSE)
+ {
+ $segments = array();
+
+ $i = 1;
+ foreach($segs as $val)
+ {
+ $val = trim($this->_filter_uri($val));
+
+ if ($val != '')
+ $segments[$i++] = $val;
+ }
+
+ $this->set_class($segments['1']);
+
+ if (isset($segments['2']))
+ {
+ // A scaffolding request. No funny business with the URL
+ if ($this->routes['scaffolding_trigger'] == $segments['2'] AND $segments['2'] != '_ci_scaffolding')
+ {
+ $this->scaffolding_request = TRUE;
+ unset($this->routes['scaffolding_trigger']);
+ }
+ else
+ {
+ // A standard method request
+ $this->set_method($segments['2']);
+ }
+ }
+
+ if ($route == FALSE)
+ {
+ $this->segments = $segments;
+ }
+
+ unset($segments);
+ }
+ // END _compile_segments()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Filter segments for malicious characters
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _filter_uri($str)
+ {
+ if ( ! preg_match("/^[a-z0-9~\s\%\.:_-]+$/i", $str))
+ {
+ exit('The URI you submitted has disallowed characters: '.$str);
+ }
+
+ return $str;
+ }
+ // END _filter_uri()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the class name
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_class($class)
+ {
+ $this->class = $class;
+ }
+ // END _filter_uri()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the current class
+ *
+ * @access public
+ * @return string
+ */
+ function fetch_class()
+ {
+ return $this->class;
+ }
+ // END _filter_uri()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the method name
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_method($method)
+ {
+ $this->method = $method;
+ }
+ // END set_method()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the current method
+ *
+ * @access public
+ * @return string
+ */
+ function fetch_method()
+ {
+ return $this->method;
+ }
+ // END set_method()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse Routes
+ *
+ * This function matches any routes that may exist in
+ * the config/routes.php file against the URI to
+ * determine if the class/method need to be remapped.
+ *
+ * @access private
+ * @return void
+ */
+ function _parse_routes()
+ {
+ // Turn the segment array into a URI string
+ $uri = implode('/', $this->segments);
+ $num = count($this->segments);
+
+ // Is there a literal match? If so we're done
+ if (isset($this->routes[$uri]))
+ {
+ $this->_compile_segments(explode('/', $this->routes[$uri]), TRUE);
+ return;
+ }
+
+ // Loop through the route array looking for wildcards
+ foreach ($this->routes as $key => $val)
+ {
+ if (count(explode('/', $key)) != $num)
+ continue;
+
+ if (preg_match("|".str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key))."$|", $uri))
+ {
+ $this->_compile_segments(explode('/', $val), TRUE);
+ break;
+ }
+ }
+ }
+ // END set_method()
+}
+// END Router Class
+?> \ No newline at end of file
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
new file mode 100644
index 000000000..4f08cf692
--- /dev/null
+++ b/system/libraries/Session.php
@@ -0,0 +1,499 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Session Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Sessions
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/sessions.html
+ */
+class CI_Session {
+
+ var $now;
+ var $encryption = TRUE;
+ var $use_database = FALSE;
+ var $session_table = FALSE;
+ var $sess_length = 7200;
+ var $sess_cookie = 'ci_session';
+ var $userdata = array();
+ var $gc_probability = 5;
+ var $object;
+
+
+ /**
+ * Session Constructor
+ *
+ * The constructor runs the session routines automatically
+ * whenever the class is instantiated.
+ */
+ function CI_Session()
+ {
+ $this->object =& get_instance();
+
+ log_message('debug', "Session Class Initialized");
+ $this->sess_run();
+ }
+ // END display_errors()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Run the session routines
+ *
+ * @access public
+ * @return void
+ */
+ function sess_run()
+ {
+ /*
+ * Set the "now" time
+ *
+ * It can either set to GMT or time(). The pref
+ * is set in the config file. If the developer
+ * is doing any sort of time localization they
+ * might want to set the session time to GMT so
+ * they can offset the "last_activity" and
+ * "last_visit" times based on each user's locale.
+ *
+ */
+ if (strtolower($this->object->config->item('time_reference')) == 'gmt')
+ {
+ $now = time();
+ $this->now = mktime(gmdate("H", $now), gmdate("i", $now), gmdate("s", $now), gmdate("m", $now), gmdate("d", $now), gmdate("Y", $now));
+
+ if (strlen($this->now) < 10)
+ {
+ $this->now = time();
+ log_message('error', 'The session class could not set a proper GMT timestamp so the local time() value was used.');
+ }
+ }
+ else
+ {
+ $this->now = time();
+ }
+
+ /*
+ * Set the session length
+ *
+ * If the session expiration is set to zero in
+ * the config file we'll set the expiration
+ * two years from now.
+ *
+ */
+ $expiration = $this->object->config->item('sess_expiration');
+
+ if (ctype_digit($expiration))
+ {
+ if ($expiration > 0)
+ {
+ $this->sess_length = $this->object->config->item('sess_expiration');
+ }
+ else
+ {
+ $this->sess_length = (60*60*24*365*2);
+ }
+ }
+
+ // Do we need encryption?
+ $this->encryption = $this->object->config->item('sess_encrypt_cookie');
+
+ if ($this->encryption == TRUE)
+ {
+ $this->object->load->library('encrypt');
+ }
+
+ // Are we using a database?
+ if ($this->object->config->item('sess_use_database') === TRUE AND $this->object->config->item('sess_table_name') != '')
+ {
+ $this->use_database = TRUE;
+ $this->session_table = $this->object->config->item('sess_table_name');
+ $this->object->load->database();
+ }
+
+ // Set the cookie name
+ if ($this->object->config->item('sess_cookie_name') != FALSE)
+ {
+ $this->sess_cookie = $this->object->config->item('cookie_prefix').$this->object->config->item('sess_cookie_name');
+ }
+
+ /*
+ * Fetch the current session
+ *
+ * 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
+ {
+ // We only update the session every five minutes
+ if (($this->userdata['last_activity'] + 300) < $this->now)
+ {
+ $this->sess_update();
+ }
+ }
+
+ // Delete expired sessions if necessary
+ if ($this->use_database === TRUE)
+ {
+ $this->sess_gc();
+ }
+ }
+ // END sess_run()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the current session data if it exists
+ *
+ * @access public
+ * @return void
+ */
+ function sess_read()
+ {
+ // Fetch the cookie
+ $session = $this->object->input->cookie($this->sess_cookie);
+
+ if ($session === FALSE)
+ {
+ log_message('debug', 'A session cookie was not found.');
+ return FALSE;
+ }
+
+ // Decrypt and unserialize the data
+ if ($this->encryption == TRUE)
+ {
+ $session = $this->object->encrypt->decode($session);
+ }
+
+ $session = @unserialize($this->strip_slashes($session));
+
+ if ( ! is_array($session) OR ! isset($session['last_activity']))
+ {
+ log_message('error', 'The session cookie data did not contain a valid array. This could be a possible hacking attempt.');
+ return FALSE;
+ }
+
+ // Is the session current?
+ if (($session['last_activity'] + $this->sess_length) < $this->now)
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Does the IP Match?
+ if ($this->object->config->item('sess_match_ip') == TRUE AND $session['ip_address'] != $this->object->input->ip_address())
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Does the User Agent Match?
+ if ($this->object->config->item('sess_match_useragent') == TRUE AND $session['user_agent'] != substr($this->object->input->user_agent(), 0, 50))
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Is there a corresponding session in the DB?
+ if ($this->use_database === TRUE)
+ {
+ $this->object->db->where('session_id', $session['session_id']);
+
+ if ($this->object->config->item('sess_match_ip') == TRUE)
+ {
+ $this->object->db->where('ip_address', $session['ip_address']);
+ }
+
+ if ($this->object->config->item('sess_match_useragent') == TRUE)
+ {
+ $this->object->db->where('user_agent', $session['user_agent']);
+ }
+
+ $query = $this->object->db->get($this->session_table);
+
+ if ($query->num_rows() == 0)
+ {
+ $this->sess_destroy();
+ return FALSE;
+ }
+ else
+ {
+ $row = $query->row();
+ if (($row->last_activity + $this->sess_length) < $this->now)
+ {
+ $this->object->db->where('session_id', $session['session_id']);
+ $this->object->db->delete($this->session_table);
+ $this->sess_destroy();
+ return FALSE;
+ }
+ }
+ }
+
+ // Session is valid!
+ $this->userdata = $session;
+ unset($session);
+
+ return TRUE;
+ }
+ // END sess_read()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Write the session cookie
+ *
+ * @access public
+ * @return void
+ */
+ function sess_write()
+ {
+ $cookie_data = serialize($this->userdata);
+
+ if ($this->encryption == TRUE)
+ {
+ $cookie_data = $this->object->encrypt->encode($cookie_data);
+ }
+
+ setcookie(
+ $this->sess_cookie,
+ $cookie_data,
+ $this->sess_length + $this->now,
+ $this->object->config->item('cookie_path'),
+ $this->object->config->item('cookie_domain'),
+ 0
+ );
+ }
+ // END sess_read()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create a new session
+ *
+ * @access public
+ * @return void
+ */
+ function sess_create()
+ {
+ $sessid = '';
+ while (strlen($sessid) < 32)
+ {
+ $sessid .= mt_rand(0, mt_getrandmax());
+ }
+
+ $this->userdata = array(
+ 'session_id' => md5(uniqid($sessid, TRUE)),
+ 'ip_address' => $this->object->input->ip_address(),
+ 'user_agent' => substr($this->object->input->user_agent(), 0, 50),
+ 'last_activity' => $this->now
+ );
+
+
+ // Save the session in the DB if needed
+ if ($this->use_database === TRUE)
+ {
+ $this->object->db->query($this->object->db->insert_string($this->session_table, $this->userdata));
+ }
+
+ // Write the cookie
+ $this->userdata['last_visit'] = 0;
+ $this->sess_write();
+ }
+ // END sess_read()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update an existing session
+ *
+ * @access public
+ * @return void
+ */
+ function sess_update()
+ {
+ if (($this->userdata['last_activity'] + $this->sess_length) < $this->now)
+ {
+ $this->userdata['last_visit'] = $this->userdata['last_activity'];
+ }
+
+ $this->userdata['last_activity'] = $this->now;
+
+ // Update the session in the DB if needed
+ if ($this->use_database === TRUE)
+ {
+ $this->object->db->query($this->object->db->update_string($this->session_table, array('last_activity' => $this->now), array('session_id' => $this->userdata['session_id'])));
+ }
+
+ // Write the cookie
+ $this->sess_write();
+ }
+ // END sess_update()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Destroy the current session
+ *
+ * @access public
+ * @return void
+ */
+ function sess_destroy()
+ {
+ setcookie(
+ $this->sess_cookie,
+ addslashes(serialize(array())),
+ ($this->now - 31500000),
+ $this->object->config->item('cookie_path'),
+ $this->object->config->item('cookie_domain'),
+ 0
+ );
+ }
+ // END sess_destroy()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Garbage collection
+ *
+ * This deletes expired session rows from database
+ * if the probability percentage is met
+ *
+ * @access public
+ * @return void
+ */
+ function sess_gc()
+ {
+ srand(time());
+ if ((rand() % 100) < $this->gc_probability)
+ {
+ $expire = $this->now - $this->sess_length;
+
+ $this->object->db->where("last_activity < {$expire}");
+ $this->object->db->delete($this->session_table);
+
+ log_message('debug', 'Session garbage collection performed.');
+ }
+ }
+ // END sess_destroy()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a specific item form the session array
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function userdata($item)
+ {
+ return ( ! isset($this->userdata[$item])) ? FALSE : $this->userdata[$item];
+ }
+ // END sess_destroy()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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();
+ }
+ // END set_userdata()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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();
+ }
+ // END set_userdata()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Strip slashes
+ *
+ * @access public
+ * @param mixed
+ * @return mixed
+ */
+ function strip_slashes($vals)
+ {
+ if (is_array($vals))
+ {
+ foreach ($vals as $key=>$val)
+ {
+ $vals[$key] = $this->strip_slashes($val);
+ }
+ }
+ else
+ {
+ $vals = stripslashes($vals);
+ }
+
+ return $vals;
+ }
+ // END strip_slashes()
+}
+// END Session Class
+?> \ No newline at end of file
diff --git a/system/libraries/Sha1.php b/system/libraries/Sha1.php
new file mode 100644
index 000000000..13196eb69
--- /dev/null
+++ b/system/libraries/Sha1.php
@@ -0,0 +1,254 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * SHA1 Encoding Class
+ *
+ * Purpose: Provides 160 bit hashing using The Secure Hash Algorithm
+ * developed at the National Institute of Standards and Technology. The 40
+ * character SHA1 message hash is computationally infeasible to crack.
+ *
+ * This class is a fallback for servers that are not running PHP greater than
+ * 4.3, or do not have the MHASH library.
+ *
+ * This class is based on two scripts:
+ *
+ * Marcus Campbell's PHP implementation (GNU license)
+ * http://www.tecknik.net/sha-1/
+ *
+ * ...which is based on Paul Johnston's JavaScript version
+ * (BSD license). http://pajhome.org.uk/
+ *
+ * I encapsulated the functions and wrote one additional method to fix
+ * a hex conversion bug. - Rick Ellis
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Encryption
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/general/encryption.html
+ */
+class CI_SHA {
+
+ function CI_SHA()
+ {
+ log_message('debug', "SHA1 Class Initialized");
+ }
+
+ /**
+ * Generate the Hash
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function generate($str)
+ {
+ $n = ((strlen($str) + 8) >> 6) + 1;
+
+ for ($i = 0; $i < $n * 16; $i++)
+ {
+ $x[$i] = 0;
+ }
+
+ for ($i = 0; $i < strlen($str); $i++)
+ {
+ $x[$i >> 2] |= ord(substr($str, $i, 1)) << (24 - ($i % 4) * 8);
+ }
+
+ $x[$i >> 2] |= 0x80 << (24 - ($i % 4) * 8);
+
+ $x[$n * 16 - 1] = strlen($str) * 8;
+
+ $a = 1732584193;
+ $b = -271733879;
+ $c = -1732584194;
+ $d = 271733878;
+ $e = -1009589776;
+
+ for ($i = 0; $i < sizeof($x); $i += 16)
+ {
+ $olda = $a;
+ $oldb = $b;
+ $oldc = $c;
+ $oldd = $d;
+ $olde = $e;
+
+ for($j = 0; $j < 80; $j++)
+ {
+ if ($j < 16)
+ {
+ $w[$j] = $x[$i + $j];
+ }
+ else
+ {
+ $w[$j] = $this->_rol($w[$j - 3] ^ $w[$j - 8] ^ $w[$j - 14] ^ $w[$j - 16], 1);
+ }
+
+ $t = $this->_safe_add($this->_safe_add($this->_rol($a, 5), $this->_ft($j, $b, $c, $d)), $this->_safe_add($this->_safe_add($e, $w[$j]), $this->_kt($j)));
+
+ $e = $d;
+ $d = $c;
+ $c = $this->_rol($b, 30);
+ $b = $a;
+ $a = $t;
+ }
+
+ $a = $this->_safe_add($a, $olda);
+ $b = $this->_safe_add($b, $oldb);
+ $c = $this->_safe_add($c, $oldc);
+ $d = $this->_safe_add($d, $oldd);
+ $e = $this->_safe_add($e, $olde);
+ }
+
+ return $this->_hex($a).$this->_hex($b).$this->_hex($c).$this->_hex($d).$this->_hex($e);
+ }
+ // END generate()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Convert a decimal to hex
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _hex($str)
+ {
+ $str = dechex($str);
+
+ if (strlen($str) == 7)
+ {
+ $str = '0'.$str;
+ }
+
+ return $str;
+ }
+ // END _hex()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Return result based on iteration
+ *
+ * @access private
+ * @return string
+ */
+ function _ft($t, $b, $c, $d)
+ {
+ if ($t < 20)
+ return ($b & $c) | ((~$b) & $d);
+ if ($t < 40)
+ return $b ^ $c ^ $d;
+ if ($t < 60)
+ return ($b & $c) | ($b & $d) | ($c & $d);
+
+ return $b ^ $c ^ $d;
+ }
+ // END _ft()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Determine the additive constant
+ *
+ * @access private
+ * @return string
+ */
+ function _kt($t)
+ {
+ if ($t < 20)
+ {
+ return 1518500249;
+ }
+ else if ($t < 40)
+ {
+ return 1859775393;
+ }
+ else if ($t < 60)
+ {
+ return -1894007588;
+ }
+ else
+ {
+ return -899497514;
+ }
+ }
+ // END _kt()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Add integers, wrapping at 2^32
+ *
+ * @access private
+ * @return string
+ */
+ function _safe_add($x, $y)
+ {
+ $lsw = ($x & 0xFFFF) + ($y & 0xFFFF);
+ $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);
+
+ return ($msw << 16) | ($lsw & 0xFFFF);
+ }
+ // END _safe_add()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Bitwise rotate a 32-bit number
+ *
+ * @access private
+ * @return integer
+ */
+ function _rol($num, $cnt)
+ {
+ return ($num << $cnt) | $this->_zero_fill($num, 32 - $cnt);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Pad string with zero
+ *
+ * @access private
+ * @return string
+ */
+ function _zero_fill($a, $b)
+ {
+ $bin = decbin($a);
+
+ if (strlen($bin) < $b)
+ {
+ $bin = 0;
+ }
+ else
+ {
+ $bin = substr($bin, 0, strlen($bin) - $b);
+ }
+
+ for ($i=0; $i < $b; $i++)
+ {
+ $bin = "0".$bin;
+ }
+
+ return bindec($bin);
+ }
+}
+// END CI_SHA
+?> \ No newline at end of file
diff --git a/system/libraries/Trackback.php b/system/libraries/Trackback.php
new file mode 100644
index 000000000..583c6d28d
--- /dev/null
+++ b/system/libraries/Trackback.php
@@ -0,0 +1,561 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Trackback Class
+ *
+ * Trackback Sending/Receiving Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Trackbacks
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/trackback.html
+ */
+class CI_Trackback {
+
+ var $time_format = 'local';
+ var $charset = 'UTF-8';
+ var $data = array('url' => '', 'title' => '', 'excerpt' => '', 'blog_name' => '', 'charset' => '');
+ var $convert_ascii = TRUE;
+ var $response = '';
+ var $error_msg = array();
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function CI_Trackback()
+ {
+ log_message('debug', "Trackback Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Send Trackback
+ *
+ * @access public
+ * @param array
+ * @return bool
+ */
+ function send($tb_data)
+ {
+ if ( ! is_array($tb_data))
+ {
+ $this->set_error('The send() method must be passed an array');
+ return FALSE;
+ }
+
+ // Pre-process the Trackback Data
+ foreach (array('url', 'title', 'excerpt', 'blog_name', 'ping_url') as $item)
+ {
+ if ( ! isset($tb_data[$item]))
+ {
+ $this->set_error('Required item missing: '.$item);
+ return FALSE;
+ }
+
+ switch ($item)
+ {
+ case 'ping_url' : $$item = $this->extract_urls($tb_data[$item]);
+ break;
+ case 'excerpt' : $$item = $this->limit_characters($this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));
+ break;
+ case 'url' : $$item = str_replace('&#45;', '-', $this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));
+ break;
+ default : $$item = $this->convert_xml(strip_tags(stripslashes($tb_data[$item])));
+ break;
+ }
+
+ // Convert High ASCII Characters
+ if ($this->convert_ascii == TRUE)
+ {
+ if ($item == 'excerpt')
+ {
+ $$item = $this->convert_ascii($$item);
+ }
+ elseif ($item == 'title')
+ {
+ $$item = $this->convert_ascii($$item);
+ }
+ elseif($item == 'blog_name')
+ {
+ $$item = $this->convert_ascii($$item);
+ }
+ }
+ }
+
+ // Build the Trackback data string
+ $charset = ( ! isset($tb_data['charset'])) ? $this->charset : $tb_data['charset'];
+
+ $data = "url=".rawurlencode($url)."&title=".rawurlencode($title)."&blog_name=".rawurlencode($blog_name)."&excerpt=".rawurlencode($excerpt)."&charset=".rawurlencode($charset);
+
+ // Send Trackback(s)
+ $return = TRUE;
+ if (count($ping_url) > 0)
+ {
+ foreach ($ping_url as $url)
+ {
+ if ($this->process($url, $data) == FALSE)
+ {
+ $return = FALSE;
+ }
+ }
+ }
+
+ return $return;
+ }
+ // END send()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Receive Trackback Data
+ *
+ * This function simply validates the incoming TB data.
+ * It returns false on failure and true on success.
+ * If the data is valid it is set to the $this->data array
+ * so that it can be inserted into a database.
+ *
+ * @access public
+ * @return bool
+ */
+ function receive()
+ {
+ foreach (array('url', 'title', 'blog_name', 'excerpt') as $val)
+ {
+ if ( ! isset($_POST[$val]) OR $_POST[$val] == '')
+ {
+ $this->set_error('The following required POST variable is missing: '.$val);
+ return FALSE;
+ }
+
+ $this->data['charset'] = ( ! isset($_POST['charset'])) ? 'auto' : strtoupper(trim($_POST['charset']));
+
+ if ($val != 'url' && function_exists('mb_convert_encoding'))
+ {
+ $_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']);
+ }
+
+ $_POST[$val] = ($val != 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]);
+
+ if ($val == 'excerpt')
+ {
+ $_POST['excerpt'] = $this->limit_characters($_POST['excerpt']);
+ }
+
+ $this->data[$val] = $_POST[$val];
+ }
+
+ return TRUE;
+ }
+ // END receive()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Send Trackback Error Message
+ *
+ * Allows custom errros to be set. By default it
+ * sends the "incomplete information" error, as that's
+ * the most common one.
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function send_error($message = 'Incomplete Information')
+ {
+ echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>1</error>\n<message>".$message."</message>\n</response>";
+ exit;
+ }
+ // END send_error()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Send Trackback Success Message
+ *
+ * This should be called when a trackback has been
+ * successfully received and inserted.
+ *
+ * @access public
+ * @return void
+ */
+ function send_success()
+ {
+ echo "<?xml version=\"1.0\" encoding=\"utf-8\"?".">\n<response>\n<error>0</error>\n</response>";
+ exit;
+ }
+ // END send_success()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch a particular item
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function data($item)
+ {
+ return ( ! isset($this->data[$item])) ? '' : $this->data[$item];
+ }
+ // END data()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process Trackback
+ *
+ * Opens a socket connection and passes the data to
+ * the server. Returns true on success, false on failure
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return bool
+ */
+ function process($url, $data)
+ {
+ $target = parse_url($url);
+
+ // Open the socket
+ if ( ! $fp = @fsockopen($target['host'], 80))
+ {
+ $this->set_error('Invalid Connection: '.$url);
+ return FALSE;
+ }
+
+ // Build the path
+ $ppath = ( ! isset($target['path'])) ? $url : $target['path'];
+
+ $path = (isset($target['query']) && $target['query'] != "") ? $ppath.'?'.$target['query'] : $ppath;
+
+ // Add the Trackback ID to the data string
+ if ($id = $this->get_id($url))
+ {
+ $data = "tb_id=".$id."&".$data;
+ }
+
+ // Transfer the data
+ fputs ($fp, "POST " . $path . " HTTP/1.0\r\n" );
+ fputs ($fp, "Host: " . $target['host'] . "\r\n" );
+ fputs ($fp, "Content-type: application/x-www-form-urlencoded\r\n" );
+ fputs ($fp, "Content-length: " . strlen($data) . "\r\n" );
+ fputs ($fp, "Connection: close\r\n\r\n" );
+ fputs ($fp, $data);
+
+ // Was it successful?
+ $this->response = "";
+
+ while(!feof($fp))
+ {
+ $this->response .= fgets($fp, 128);
+ }
+ @fclose($fp);
+
+ if ( ! eregi("<error>0</error>", $this->response))
+ {
+ $message = 'An unknown error was encountered';
+
+ if (preg_match("/<message>(.*?)<\/message>/is", $this->response, $match))
+ {
+ $message = trim($match['1']);
+ }
+
+ $this->set_error($message);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ // END process()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Extract Trackback URLs
+ *
+ * This function lets multiple trackbacks be sent.
+ * It takes a string of URLs (separated by comma or
+ * space) and puts each URL into an array
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function extract_urls($urls)
+ {
+ // Remove the pesky white space and replace with a comma.
+ $urls = preg_replace("/\s*(\S+)\s*/", "\\1,", $urls);
+
+ // If they use commas get rid of the doubles.
+ $urls = str_replace(",,", ",", $urls);
+
+ // Remove any comma that might be at the end
+ if (substr($urls, -1) == ",")
+ {
+ $urls = substr($urls, 0, -1);
+ }
+
+ // Break into an array via commas
+ $urls = preg_split('/[,]/', $urls);
+
+ // Removes duplicates
+ $urls = array_unique($urls);
+
+ array_walk($urls, array($this, 'validate_url'));
+
+ return $urls;
+ }
+ // END extract_urls()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Validate URL
+ *
+ * Simply adds "http://" if missing
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function validate_url($url)
+ {
+ $url = trim($url);
+
+ if (substr($url, 0, 4) != "http")
+ {
+ $url = "http://".$url;
+ }
+ }
+ // END validate_url()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Find the Trackback URL's ID
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function get_id($url)
+ {
+ $tb_id = "";
+
+ if (strstr($url, '?'))
+ {
+ $tb_array = explode('/', $url);
+ $tb_end = $tb_array[count($tb_array)-1];
+
+ if ( ! ctype_digit($tb_end))
+ {
+ $tb_end = $tb_array[count($tb_array)-2];
+ }
+
+ $tb_array = explode('=', $tb_end);
+ $tb_id = $tb_array[count($tb_array)-1];
+ }
+ else
+ {
+ if (ereg("/$", $url))
+ {
+ $url = substr($url, 0, -1);
+ }
+
+ $tb_array = explode('/', $url);
+ $tb_id = $tb_array[count($tb_array)-1];
+
+ if ( ! ctype_digit($tb_id))
+ {
+ $tb_id = $tb_array[count($tb_array)-2];
+ }
+ }
+
+ if ( ! preg_match ("/^([0-9]+)$/", $tb_id))
+ {
+ return false;
+ }
+ else
+ {
+ return $tb_id;
+ }
+ }
+ // END get_id()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Convert Reserved XML characters to Entities
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function convert_xml($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;
+ }
+ // END get_id()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Character limiter
+ *
+ * Limits the string based on the character count. Will preserve complete words.
+ *
+ * @access public
+ * @param string
+ * @param integer
+ * @param string
+ * @return string
+ */
+ function limit_characters($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;
+ }
+ }
+ }
+ // END get_id()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * High ASCII to Entities
+ *
+ * Converts Hight ascii text and MS Word special chars
+ * to character entities
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function convert_ascii($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;
+ }
+ // END convert_ascii()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set error message
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_error($msg)
+ {
+ log_message('error', $msg);
+ $this->error_msg[] = $msg;
+ }
+ // END convert_ascii()
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show error messages
+ *
+ * @access public
+ * @param string
+ * @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 display_errors()
+}
+// END Trackback Class
+?> \ No newline at end of file
diff --git a/system/libraries/URI.php b/system/libraries/URI.php
new file mode 100644
index 000000000..4c2fa9c7f
--- /dev/null
+++ b/system/libraries/URI.php
@@ -0,0 +1,243 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * URI Class
+ *
+ * Parses URIs and determines routing
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category URI
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/uri.html
+ */
+class CI_URI {
+
+ var $uri;
+ var $keyval = 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->uri =& _load_class('CI_Router');
+ log_message('debug', "URI Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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->uri->segments[$n])) ? $no_result : $this->uri->segments[$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:
+ *
+ * www.your-site.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())
+ {
+ if ( ! ctype_digit($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 $default;
+ }
+
+ $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')
+ {
+ if ($where == 'trailing')
+ {
+ $trailing = '/';
+ $leading = '';
+ }
+ elseif ($where == 'leading')
+ {
+ $leading = '/';
+ $trailing = '';
+ }
+ else
+ {
+ $leading = '/';
+ $trailing = '/';
+ }
+ return ( ! isset($this->uri->segments[$n])) ? '' : $leading.$this->uri->segments[$n].$trailing;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Segment Array
+ *
+ * @access public
+ * @return array
+ */
+ function segment_array()
+ {
+ return $this->uri->segments;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Total number of segments
+ *
+ * @access public
+ * @return integer
+ */
+ function total_segments()
+ {
+ return count($this->uri->segments);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch the entire URI string
+ *
+ * @access public
+ * @return string
+ */
+ function uri_string()
+ {
+ return $this->uri->uri_string;
+ }
+
+}
+// END URI Class
+?> \ No newline at end of file
diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php
new file mode 100644
index 000000000..bf50350ae
--- /dev/null
+++ b/system/libraries/Unit_test.php
@@ -0,0 +1,331 @@
+<?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.3.1
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Unit Testing Class
+ *
+ * Simple testing class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category UnitTesting
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/uri.html
+ */
+class CI_Unit_test {
+
+ var $active = TRUE;
+ var $results = array();
+ var $strict = FALSE;
+ var $_template = NULL;
+ var $_template_rows = NULL;
+
+ function CI_Unit_test()
+ {
+ log_message('debug', "Unit Testing Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Run the tests
+ *
+ * Runs the supplied tests
+ *
+ * @access public
+ * @param mixed
+ * @param mixed
+ * @param string
+ * @return string
+ */
+ function run($test, $expected = TRUE, $test_name = 'undefined')
+ {
+ if ($this->active == FALSE)
+ return;
+
+ if (in_array($expected, array('is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null')))
+ {
+ $expected = str_replace('is_float', 'is_double', $expected);
+ $result = ($expected($test)) ? TRUE : FALSE;
+ $extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));
+ }
+ else
+ {
+ if ($this->strict == TRUE)
+ $result = ($test === $expected) ? TRUE : FALSE;
+ else
+ $result = ($test == $expected) ? TRUE : FALSE;
+
+ $extype = gettype($expected);
+ }
+
+ $back = $this->_backtrace();
+
+ $report[] = array (
+ 'test_name' => $test_name,
+ 'test_datatype' => gettype($test),
+ 'res_datatype' => $extype,
+ 'result' => ($result === TRUE) ? 'passed' : 'failed',
+ 'file' => $back['file'],
+ 'line' => $back['line']
+ );
+
+ $this->results[] = $report;
+
+ return($this->report($this->result($report)));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate a report
+ *
+ * Displays a table with the test data
+ *
+ * @access public
+ * @return string
+ */
+ function report($result = array())
+ {
+ if (count($result) == 0)
+ {
+ $result = $this->result();
+ }
+
+ $this->_parse_template();
+
+ $r = '';
+ foreach ($result as $res)
+ {
+ $table = '';
+
+ foreach ($res as $key => $val)
+ {
+ $temp = $this->_template_rows;
+ $temp = str_replace('{item}', $key, $temp);
+ $temp = str_replace('{result}', $val, $temp);
+ $table .= $temp;
+ }
+
+ $r .= str_replace('{rows}', $table, $this->_template);
+ }
+
+ return $r;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Use strict comparison
+ *
+ * Causes the evaluation to use === rather then ==
+ *
+ * @access public
+ * @param bool
+ * @return null
+ */
+ function use_strict($state = TRUE)
+ {
+ $this->strict = ($state == FALSE) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Make Unit testing active
+ *
+ * Enables/disables unit testing
+ *
+ * @access public
+ * @param bool
+ * @return null
+ */
+ function active($state = TRUE)
+ {
+ $this->active = ($state == FALSE) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result Array
+ *
+ * Returns the raw result data
+ *
+ * @access public
+ * @return array
+ */
+ function result($results = array())
+ {
+ $obj =& get_instance();
+ $obj->load->language('unit_test');
+
+ if (count($results) == 0)
+ {
+ $results = $this->results;
+ }
+
+ $retval = array();
+ foreach ($results as $result)
+ {
+ $temp = array();
+ foreach ($result as $key => $val)
+ {
+ if (is_array($val))
+ {
+ foreach ($val as $k => $v)
+ {
+ if (FALSE !== ($line = $obj->lang->line(strtolower('ut_'.$v))))
+ {
+ $v = $line;
+ }
+ $temp[$obj->lang->line('ut_'.$k)] = $v;
+ }
+ }
+ else
+ {
+ if (FALSE !== ($line = $obj->lang->line(strtolower('ut_'.$val))))
+ {
+ $val = $line;
+ }
+ $temp[$obj->lang->line('ut_'.$key)] = $val;
+ }
+ }
+
+ $retval[] = $temp;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the template
+ *
+ * This lets us set the template to be used to display results
+ *
+ * @access public
+ * @params string
+ * @return void
+ */
+ function set_template($tempalte)
+ {
+ $this->_template = $tempalte;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Generate a backtrace
+ *
+ * This lets us show file names and line numbers
+ *
+ * @access private
+ * @return array
+ */
+ function _backtrace()
+ {
+ if (function_exists('debug_backtrace'))
+ {
+ $back = debug_backtrace();
+
+ $file = ( ! isset($back['1']['file'])) ? '' : $back['1']['file'];
+ $line = ( ! isset($back['1']['line'])) ? '' : $back['1']['line'];
+
+ return array('file' => $file, 'line' => $line);
+ }
+ return array('file' => 'Unknown', 'line' => 'Unknown');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Get Default Template
+ *
+ * @access private
+ * @return string
+ */
+ function _default_template()
+ {
+ $this->_template = '
+ <div style="margin:15px;background-color:#ccc;">
+ <table border="0" cellpadding="4" cellspacing="1" style="width:100%;">
+ {rows}
+ </table></div>';
+
+ $this->_template_rows = '
+ <tr>
+ <td style="background-color:#fff;width:140px;font-size:12px;font-weight:bold;">{item}</td>
+ <td style="background-color:#fff;font-size:12px;">{result}</td>
+ </tr>
+ ';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse Template
+ *
+ * Harvests the data within the template {pseudo-variables}
+ *
+ * @access private
+ * @return void
+ */
+ function _parse_template()
+ {
+ if ( ! is_null($this->_template_rows))
+ {
+ return;
+ }
+
+ if (is_null($this->_template))
+ {
+ $this->_default_template();
+ return;
+ }
+
+ if ( ! preg_match("/\{rows\}(.*?)\{\/rows\}/si", $this->_template, $match))
+ {
+ $this->_default_template();
+ return;
+ }
+
+ $this->_template_rows = $match['1'];
+ $this->_template = str_replace($match['0'], '{rows}', $this->_template);
+ }
+
+}
+// END Unit_test Class
+
+/**
+ * Helper functions to test boolean true/false
+ *
+ *
+ * @access private
+ * @return bool
+ */
+function is_true($test)
+{
+ return (is_bool($test) AND $test === TRUE) ? TRUE : FALSE;
+}
+function is_false($test)
+{
+ return (is_bool($test) AND $test === FALSE) ? TRUE : FALSE;
+}
+
+?> \ No newline at end of file
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
new file mode 100644
index 000000000..6d12dbcd7
--- /dev/null
+++ b/system/libraries/Upload.php
@@ -0,0 +1,775 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * File Uploading Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Uploads
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/file_uploading.html
+ */
+class CI_Upload {
+
+ var $max_size = 0;
+ var $max_width = 0;
+ var $max_height = 0;
+ var $allowed_types = "";
+ var $file_temp = "";
+ var $file_name = "";
+ var $orig_name = "";
+ var $file_type = "";
+ var $file_size = "";
+ var $file_ext = "";
+ var $file_path = "";
+ var $overwrite = FALSE;
+ var $encrypt_name = FALSE;
+ var $is_image = FALSE;
+ var $image_width = '';
+ var $image_height = '';
+ var $image_type = '';
+ var $image_size_str = '';
+ var $error_msg = array();
+ var $mimes = array();
+ var $remove_spaces = TRUE;
+ var $xss_clean = FALSE;
+ var $temp_prefix = "temp_file_";
+
+ /**
+ * Constructor
+ *
+ * @access public
+ */
+ function CI_Upload($props = array())
+ {
+ if (count($props) > 0)
+ {
+ $this->initialize($props);
+ }
+
+ log_message('debug', "Upload Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Initialize preferences
+ *
+ * @access public
+ * @param array
+ * @return void
+ */
+ function initialize($config = array())
+ {
+ foreach ($config as $key => $val)
+ {
+ $method = 'set_'.$key;
+ if (method_exists($this, $method))
+ {
+ $this->$method($val);
+ }
+ else
+ {
+ $this->$key = $val;
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Perform the file upload
+ *
+ * @access public
+ * @return bool
+ */
+ function do_upload()
+ {
+ // Is $_FILES['userfile'] set? If not, no reason to continue.
+ if ( ! isset($_FILES['userfile']))
+ {
+ $this->set_error('upload_userfile_not_set');
+ return FALSE;
+ }
+
+ // Is the upload path valid?
+ if ( ! $this->validate_upload_path())
+ {
+ return FALSE;
+ }
+
+ // Was the file able to be uploaded? If not, determine the reason why.
+ if ( ! is_uploaded_file($_FILES['userfile']['tmp_name']))
+ {
+ $error = ( ! isset($_FILES['userfile']['error'])) ? 4 : $_FILES['userfile']['error'];
+
+ switch($error)
+ {
+ case 1 : $this->set_error('upload_file_exceeds_limit');
+ break;
+ case 3 : $this->set_error('upload_file_partial');
+ break;
+ case 4 : $this->set_error('upload_no_file_selected');
+ break;
+ default : $this->set_error('upload_no_file_selected');
+ break;
+ }
+
+ return FALSE;
+ }
+
+ // Set the uploaded data as class variables
+ $this->file_temp = $_FILES['userfile']['tmp_name'];
+ $this->file_name = $_FILES['userfile']['name'];
+ $this->file_size = $_FILES['userfile']['size'];
+ $this->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES['userfile']['type']);
+ $this->file_type = strtolower($this->file_type);
+ $this->file_ext = $this->get_extension($_FILES['userfile']['name']);
+
+ // Convert the file size to kilobytes
+ if ($this->file_size > 0)
+ {
+ $this->file_size = round($this->file_size/1024, 2);
+ }
+
+ // Is the file type allowed to be uploaded?
+ if ( ! $this->is_allowed_filetype())
+ {
+ $this->set_error('upload_invalid_filetype');
+ return FALSE;
+ }
+
+ // Is the file size within the allowed maximum?
+ if ( ! $this->is_allowed_filesize())
+ {
+ $this->set_error('upload_invalid_filesize');
+ return FALSE;
+ }
+
+ // Are the image dimensions within the allowed size?
+ // Note: This can fail if the server has an open_basdir restriction.
+ if ( ! $this->is_allowed_dimensions())
+ {
+ $this->set_error('upload_invalid_dimensions');
+ return FALSE;
+ }
+
+ // Sanitize the file name for security
+ $this->file_name = $this->clean_file_name($this->file_name);
+
+ // Remove white spaces in the name
+ if ($this->remove_spaces == TRUE)
+ {
+ $this->file_name = preg_replace("/\s+/", "_", $this->file_name);
+ }
+
+ /*
+ * Validate the file name
+ * This function appends an number onto the end of
+ * the file if one with the same name already exists.
+ * If it returns false there was a problem.
+ */
+ $this->orig_name = $this->file_name;
+
+ if ($this->overwrite == FALSE)
+ {
+ $this->file_name = $this->set_filename($this->file_path, $this->file_name);
+
+ if ($this->file_name === FALSE)
+ {
+ return FALSE;
+ }
+ }
+
+ /*
+ * Move the file to the final destination
+ * To deal with different server configurations
+ * we'll attempt to use copy() first. If that fails
+ * we'll use move_uploaded_file(). One of the two should
+ * reliably work in most environments
+ */
+ if ( ! @copy($this->file_temp, $this->file_path.$this->file_name))
+ {
+ if ( ! @move_uploaded_file($this->file_temp, $this->file_path.$this->file_name))
+ {
+ $this->set_error('upload_destination_error');
+ return FALSE;
+ }
+ }
+
+ /*
+ * Run the file through the XSS hacking filter
+ * This helps prevent malicious code from being
+ * embedded within a file. Scripts can easily
+ * be disguised as images or other file types.
+ */
+ if ($this->xss_clean == TRUE)
+ {
+ $this->do_xss_clean();
+ }
+
+ /*
+ * Set the finalized image dimensions
+ * This sets the image width/height (assuming the
+ * file was an image). We use this information
+ * in the "data" function.
+ */
+ $this->set_image_properties($this->file_path.$this->file_name);
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Finalized Data Array
+ *
+ * Returns an associative array containing all of the information
+ * related to the upload, allowing the developer easy access in one array.
+ *
+ * @access public
+ * @return array
+ */
+ function data()
+ {
+ return array (
+ 'file_name' => $this->file_name,
+ 'file_type' => $this->file_type,
+ 'file_path' => $this->file_path,
+ 'full_path' => $this->file_path.$this->file_name,
+ 'raw_name' => str_replace($this->file_ext, '', $this->file_name),
+ 'orig_name' => $this->orig_name,
+ 'file_ext' => $this->file_ext,
+ 'file_size' => $this->file_size,
+ 'is_image' => $this->is_image(),
+ 'image_width' => $this->image_width,
+ 'image_height' => $this->image_height,
+ 'image_type' => $this->image_type,
+ 'image_size_str' => $this->image_size_str,
+ );
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Upload Path
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_upload_path($path)
+ {
+ $this->file_path = $path;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set the file name
+ *
+ * This function takes a filename/path as input and looks for the
+ * existnace of a file with the same name. If found, it will append a
+ * number to the end of the filename to avoid overwritting a pre-existing file.
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function set_filename($path, $filename)
+ {
+ if ($this->encrypt_name == TRUE)
+ {
+ mt_srand();
+ $filename = md5(uniqid(mt_rand())).$this->file_ext;
+ }
+
+ if ( ! file_exists($path.$filename))
+ {
+ return $filename;
+ }
+
+ $filename = str_replace($this->file_ext, '', $filename);
+
+ $new_filename = '';
+ for ($i = 1; $i < 100; $i++)
+ {
+ if ( ! file_exists($path.$filename.$i.$this->file_ext))
+ {
+ $new_filename = $filename.$i.$this->file_ext;
+ break;
+ }
+ }
+
+ if ($new_filename == '')
+ {
+ $this->set_error('upload_bad_filename');
+ return FALSE;
+ }
+ else
+ {
+ return $new_filename;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Maximum File Size
+ *
+ * @access public
+ * @param integer
+ * @return void
+ */
+ function set_max_filesize($n)
+ {
+ $this->max_size = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Maximum Image Width
+ *
+ * @access public
+ * @param integer
+ * @return void
+ */
+ function set_max_width($n)
+ {
+ $this->max_width = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Maximum Image Height
+ *
+ * @access public
+ * @param integer
+ * @return void
+ */
+ function set_max_height($n)
+ {
+ $this->max_height = ( ! eregi("^[[:digit:]]+$", $n)) ? 0 : $n;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Allowed File Types
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_allowed_types($types)
+ {
+ $this->allowed_types = explode('|', $types);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Image Properties
+ *
+ * Uses GD to determine the width/height/type of image
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_image_properties($path = '')
+ {
+ if ( ! $this->is_image())
+ {
+ return;
+ }
+
+ if (function_exists('getimagesize'))
+ {
+ if (FALSE !== ($D = @getimagesize($path)))
+ {
+ $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
+
+ $this->image_width = $D['0'];
+ $this->image_height = $D['1'];
+ $this->image_type = ( ! isset($types[$D['2']])) ? 'unknown' : $types[$D['2']];
+ $this->image_size_str = $D['3']; // string containing height and width
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set XSS Clean
+ *
+ * Enables the XSS flag so that the file that was uploaded
+ * will be run through the XSS filter.
+ *
+ * @access public
+ * @param bool
+ * @return void
+ */
+ function set_xss_clean($flag = FALSE)
+ {
+ $this->xss_clean = ($flag == TRUE) ? TRUE : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Validate the image
+ *
+ * @access public
+ * @return bool
+ */
+ function is_image()
+ {
+ $img_mimes = array(
+ 'image/gif',
+ 'image/jpg',
+ 'image/jpe',
+ 'image/jpeg',
+ 'image/pjpeg',
+ 'image/png',
+ 'image/x-png'
+ );
+
+
+ return (in_array($this->file_type, $img_mimes)) ? TRUE : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Verify that the filetype is allowed
+ *
+ * @access public
+ * @return bool
+ */
+ function is_allowed_filetype()
+ {
+ if (count($this->allowed_types) == 0)
+ {
+ $this->set_error('upload_no_file_types');
+ return FALSE;
+ }
+
+ foreach ($this->allowed_types as $val)
+ {
+ $mime = $this->mimes_types(strtolower($val));
+
+ if (is_array($mime))
+ {
+ if (in_array($this->file_type, $mime))
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ($mime == $this->file_type)
+ {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Verify that the file is within the allowed size
+ *
+ * @access public
+ * @return bool
+ */
+ function is_allowed_filesize()
+ {
+ if ($this->max_size != 0 AND $this->file_size > $this->max_size)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Verify that the image is within the allowed width/height
+ *
+ * @access public
+ * @return bool
+ */
+ function is_allowed_dimensions()
+ {
+ if ( ! $this->is_image())
+ {
+ return TRUE;
+ }
+
+ if (function_exists('getimagesize'))
+ {
+ $D = @getimagesize($this->file_temp);
+
+ if ($this->max_width > 0 AND $D['0'] > $this->max_width)
+ {
+ return FALSE;
+ }
+
+ if ($this->max_height > 0 AND $D['1'] > $this->max_height)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * VAlidate Upload Path
+ *
+ * Verifies that it is a valid upload path with proper permissions.
+ *
+ *
+ * @access public
+ * @return bool
+ */
+ function validate_upload_path()
+ {
+ if ($this->file_path == '')
+ {
+ $this->set_error('upload_no_filepath');
+ return FALSE;
+ }
+
+ if (function_exists('realpath') AND @realpath($this->file_path) !== FALSE)
+ {
+ $this->file_path = str_replace("\\", "/", realpath($this->file_path));
+ }
+
+ if ( ! @is_dir($this->file_path))
+ {
+ $this->set_error('upload_no_filepath');
+ return FALSE;
+ }
+
+ if ( ! is_writable($this->file_path))
+ {
+ $this->set_error('upload_not_writable');
+ return FALSE;
+ }
+
+ $this->file_path = preg_replace("/(.+?)\/*$/", "\\1/", $this->file_path);
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Extract the file extension
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function get_extension($filename)
+ {
+ $x = explode('.', $filename);
+ return '.'.end($x);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Clean the file name for security
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function clean_file_name($filename)
+ {
+ $bad = array(
+ "<!--",
+ "-->",
+ "'",
+ "<",
+ ">",
+ '"',
+ '&',
+ '$',
+ '=',
+ ';',
+ '?',
+ '/',
+ "%20",
+ "%22",
+ "%3c", // <
+ "%253c", // <
+ "%3e", // >
+ "%0e", // >
+ "%28", // (
+ "%29", // )
+ "%2528", // (
+ "%26", // &
+ "%24", // $
+ "%3f", // ?
+ "%3b", // ;
+ "%3d" // =
+ );
+
+ foreach ($bad as $val)
+ {
+ $filename = str_replace($val, '', $filename);
+ }
+
+ return $filename;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Runs the file through the XSS clean function
+ *
+ * This prevents people from embedding malicious code in their files.
+ * I'm not sure that it won't negatively affect certain files in unexpected ways,
+ * but so far I haven't found that it causes trouble.
+ *
+ * @access public
+ * @return void
+ */
+ function do_xss_clean()
+ {
+ $file = $this->file_path.$this->file_name;
+
+ if (filesize($file) == 0)
+ {
+ return FALSE;
+ }
+
+ if ( ! $fp = @fopen($file, 'rb'))
+ {
+ return FALSE;
+ }
+
+ flock($fp, LOCK_EX);
+
+ $data = fread($fp, filesize($file));
+
+ $obj =& get_instance();
+ $data = $obj->input->xss_clean($data);
+
+ fwrite($fp, $data);
+ flock($fp, LOCK_UN);
+ fclose($fp);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set an error message
+ *
+ * @access public
+ * @param string
+ * @return void
+ */
+ function set_error($msg)
+ {
+ $obj =& get_instance();
+ $obj->lang->load('upload');
+
+ if (is_array($msg))
+ {
+ foreach ($msg as $val)
+ {
+ $msg = ($obj->lang->line($val) == FALSE) ? $val : $obj->lang->line($val);
+ $this->error_msg[] = $msg;
+ log_message('error', $msg);
+ }
+ }
+ else
+ {
+ $msg = ($obj->lang->line($msg) == FALSE) ? $msg : $obj->lang->line($msg);
+ $this->error_msg[] = $msg;
+ log_message('error', $msg);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Display the error message
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function display_errors($open = '<p>', $close = '</p>')
+ {
+ $str = '';
+ foreach ($this->error_msg as $val)
+ {
+ $str .= $open.$val.$close;
+ }
+
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List of Mime Types
+ *
+ * This is a list of mime types. We use it to validate
+ * the "allowed types" set by the developer
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function mimes_types($mime)
+ {
+ if (count($this->mimes) == 0)
+ {
+ if (@include(APPPATH.'config/mimes'.EXT))
+ {
+ $this->mimes = $mimes;
+ unset($mimes);
+ }
+ }
+
+ return ( ! isset($this->mimes[$mime])) ? FALSE : $this->mimes[$mime];
+ }
+
+}
+// END Upload Class
+?> \ No newline at end of file
diff --git a/system/libraries/Validation.php b/system/libraries/Validation.php
new file mode 100644
index 000000000..df8c70ee8
--- /dev/null
+++ b/system/libraries/Validation.php
@@ -0,0 +1,692 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Validation Class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Validation
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/libraries/validation.html
+ */
+class CI_Validation {
+
+ var $error_string = '';
+ var $_error_array = array();
+ var $_rules = array();
+ var $_fields = array();
+ var $_error_messages = array();
+ var $_current_field = '';
+ var $_safe_form_data = FALSE;
+ var $_error_prefix = '<p>';
+ var $_error_suffix = '</p>';
+ var $obj;
+
+
+ /**
+ * Constructor
+ *
+ */
+ function CI_Validation()
+ {
+ $this->obj =& get_instance();
+ log_message('debug', "Validation Class Initialized");
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Fields
+ *
+ * This function takes an array of field names as input
+ * and generates class variables with the same name, which will
+ * either be blank or contain the $_POST value corresponding to it
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return void
+ */
+ function set_fields($data = '', $field = '')
+ {
+ if ($data == '')
+ return;
+
+ if ( ! is_array($data))
+ {
+ if ($field == '')
+ return;
+
+ $data = array($data => $field);
+ }
+
+ $this->_fields = $data;
+
+ foreach($this->_fields as $key => $val)
+ {
+ $this->$key = ( ! isset($_POST[$key]) OR is_array($_POST[$key])) ? '' : $this->prep_for_form($_POST[$key]);
+
+ $error = $key.'_error';
+ if ( ! isset($this->$error))
+ {
+ $this->$error = '';
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Rules
+ *
+ * This function takes an array of field names and validation
+ * rules as input ad simply stores is for use later.
+ *
+ * @access public
+ * @param mixed
+ * @param string
+ * @return void
+ */
+ function set_rules($data, $rules = '')
+ {
+ if ( ! is_array($data))
+ {
+ if ($rules == '')
+ return;
+
+ $data[$data] = $rules;
+ }
+
+ foreach ($data as $key => $val)
+ {
+ $this->_rules[$key] = $val;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Error Message
+ *
+ * Lets users set their own error messages on the fly. Note: The key
+ * name has to match the function name that it corresponds to.
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function set_message($lang, $val = '')
+ {
+ if ( ! is_array($lang))
+ {
+ $lang = array($lang => $val);
+ }
+
+ $this->_error_messages = array_merge($this->_error_messages, $lang);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set The Error Delimiter
+ *
+ * Permits a prefix/suffix to be added to each error message
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return void
+ */
+ function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
+ {
+ $this->_error_prefix = $prefix;
+ $this->_error_suffix = $suffix;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Run the Validator
+ *
+ * This function does all the work.
+ *
+ * @access public
+ * @return bool
+ */
+ function run()
+ {
+ // Do we even have any data to process? Mm?
+ if (count($_POST) == 0 OR count($this->_rules) == 0)
+ {
+ return FALSE;
+ }
+
+ // Load the language file containing error messages
+ $this->obj->lang->load('validation');
+
+ // Cycle through the rules and test for errors
+ foreach ($this->_rules as $field => $rules)
+ {
+ //Explode out the rules!
+ $ex = explode('|', $rules);
+
+ // Is the field required? If not, if the field is blank we'll move on to the next text
+ if ( ! in_array('required', $ex))
+ {
+ if ( ! isset($_POST[$field]) OR $_POST[$field] == '')
+ {
+ continue;
+ }
+ }
+
+ /*
+ * Are we dealing with an "isset" rule?
+ *
+ * Before going further, we'll see if one of the rules
+ * is to check whether the item is set (typically this
+ * applies only to checkboxes). If so, we'll
+ * test for it here since there's not reason to go
+ * further
+ */
+ if ( ! isset($_POST[$field]))
+ {
+ if (in_array('isset', $ex) OR in_array('required', $ex))
+ {
+ if ( ! isset($this->messages['isset']))
+ {
+ if (FALSE === ($line = $this->obj->lang->line('isset')))
+ {
+ $line = 'The field was not set';
+ }
+ }
+ else
+ {
+ $line = $this->_error_messages['isset'];
+ }
+
+ $field = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
+ $this->_error_array[] = sprintf($line, $field);
+ }
+
+ continue;
+ }
+
+ /*
+ * Set the current field
+ *
+ * The various prepping functions need to know the
+ * current field name so they can do this:
+ *
+ * $_POST[$this->_current_field] == 'bla bla';
+ */
+ $this->_current_field = $field;
+
+ // Cycle through the rules!
+ foreach ($ex As $rule)
+ {
+
+ // Is the rule a callback?
+ $callback = FALSE;
+ if (substr($rule, 0, 9) == 'callback_')
+ {
+ $rule = substr($rule, 9);
+ $callback = TRUE;
+ }
+
+ // Strip the parameter (if exists) from the rule
+ // Rules can contain a parameter: max_length[5]
+ $param = FALSE;
+ if (preg_match("/.*?(\[.*?\]).*/", $rule, $match))
+ {
+ $param = substr(substr($match['1'], 1), 0, -1);
+ $rule = str_replace($match['1'], '', $rule);
+ }
+
+ // Call the function that corresponds to the rule
+ if ($callback === TRUE)
+ {
+ if ( ! method_exists($this->obj, $rule))
+ {
+ continue;
+ }
+
+ $result = $this->obj->$rule($_POST[$field], $param);
+ }
+ else
+ {
+ if ( ! method_exists($this, $rule))
+ {
+ /*
+ * Run the native PHP function if called for
+ *
+ * If our own wrapper function doesn't exist we see
+ * if a native PHP function does. Users can use
+ * any native PHP function call that has one param.
+ */
+ if (function_exists($rule))
+ {
+ $_POST[$field] = $rule($_POST[$field]);
+ $this->$field = $_POST[$field];
+ }
+
+ continue;
+ }
+
+ $result = $this->$rule($_POST[$field], $param);
+ }
+
+ // Did the rule test negatively? If so, grab the error.
+ if ($result === FALSE)
+ {
+ if ( ! isset($this->_error_messages[$rule]))
+ {
+ if (FALSE === ($line = $this->obj->lang->line($rule)))
+ {
+ $line = 'Unable to access an error message corresponding to your field name.';
+ }
+ }
+ else
+ {
+ $line = $this->_error_messages[$rule];;
+ }
+
+ // Build the error message
+ $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
+ $mparam = ( ! isset($this->_fields[$param])) ? $param : $this->_fields[$param];
+ $message = sprintf($line, $mfield, $mparam);
+
+ // Set the error variable. Example: $this->username_error
+ $error = $field.'_error';
+ $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
+
+ // Add the error to the error array
+ $this->_error_array[] = $message;
+ continue 2;
+ }
+ }
+ }
+
+ $total_errors = count($this->_error_array);
+
+ /*
+ * Recompile the class variables
+ *
+ * If any prepping functions were called the $_POST data
+ * might now be different then the corresponding class
+ * variables so we'll set them anew.
+ */
+ if ($total_errors > 0)
+ {
+ $this->_safe_form_data = TRUE;
+ }
+
+ $this->set_fields();
+
+ // Did we end up with any errors?
+ if ($total_errors == 0)
+ {
+ return TRUE;
+ }
+
+ // Generate the error string
+ foreach ($this->_error_array as $val)
+ {
+ $this->error_string .= $this->_error_prefix.$val.$this->_error_suffix."\n";
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Required
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function required($str)
+ {
+ if ( ! is_array($str))
+ {
+ return (trim($str) == '') ? FALSE : TRUE;
+ }
+ else
+ {
+ return ( ! empty($str));
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Match one field to another
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function matches($str, $field)
+ {
+ if ( ! isset($_POST[$field]))
+ {
+ return FALSE;
+ }
+
+ return ($str !== $_POST[$field]) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Minimum Length
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function min_length($str, $val)
+ {
+ if ( ! ctype_digit($val))
+ {
+ return FALSE;
+ }
+
+ return (strlen($str) < $val) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Max Length
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function max_length($str, $val)
+ {
+ if ( ! ctype_digit($val))
+ {
+ return FALSE;
+ }
+
+ return (strlen($str) > $val) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Exact Length
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function exact_length($str, $val)
+ {
+ if ( ! ctype_digit($val))
+ {
+ return FALSE;
+ }
+
+ return (strlen($str) != $val) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Valid Email
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function valid_email($str)
+ {
+ return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Alpha
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function alpha($str)
+ {
+ return ( ! preg_match("/^([-a-z])+$/i", $str)) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Alpha-numeric
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function alpha_numeric($str)
+ {
+ return ( ! preg_match("/^([-a-z0-9])+$/i", $str)) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Alpha-numeric with underscores and dashes
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function alpha_dash($str)
+ {
+ return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Numeric
+ *
+ * @access public
+ * @param string
+ * @return bool
+ */
+ function numeric($str)
+ {
+ return ( ! ctype_digit($str)) ? FALSE : TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Select
+ *
+ * Enables pull-down lists to be set to the value the user
+ * selected in the event of an error
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function set_select($field = '', $value = '')
+ {
+ if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
+ {
+ return '';
+ }
+
+ if ($_POST[$field] == $value)
+ {
+ return ' selected="selected"';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Radio
+ *
+ * Enables radio buttons to be set to the value the user
+ * selected in the event of an error
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function set_radio($field = '', $value = '')
+ {
+ if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
+ {
+ return '';
+ }
+
+ if ($_POST[$field] == $value)
+ {
+ return ' checked="checked"';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set Checkbox
+ *
+ * Enables checkboxes to be set to the value the user
+ * selected in the event of an error
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return string
+ */
+ function set_checkbox($field = '', $value = '')
+ {
+ if ($field == '' OR $value == '' OR ! isset($_POST[$field]))
+ {
+ return '';
+ }
+
+ if ($_POST[$field] == $value)
+ {
+ return ' checked="checked"';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep data for form
+ *
+ * This function allows HTML to be safely shown in a form.
+ * Special characters are converted.
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function prep_for_form($str = '')
+ {
+ if ($this->_safe_form_data == FALSE OR $str == '')
+ {
+ return $str;
+ }
+
+ return str_replace(array("'", '"', '<', '>'), array("&#39;", "&quot;", '&lt;', '&gt;'), stripslashes($str));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep URL
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function prep_url($str = '')
+ {
+ if ($str == 'http://' OR $str == '')
+ {
+ $_POST[$this->_current_field] = '';
+ return;
+ }
+
+ if (substr($str, 0, 7) != 'http://' && substr($str, 0, 8) != 'https://')
+ {
+ $str = 'http://'.$str;
+ }
+
+ $_POST[$this->_current_field] = $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Strip Image Tags
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function strip_image_tags($str)
+ {
+ $_POST[$this->_current_field] = $this->input->strip_image_tags($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * XSS Clean
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function xss_clean($str)
+ {
+ $_POST[$this->_current_field] = $this->obj->input->xss_clean($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Convert PHP tags to entities
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function encode_php_tags($str)
+ {
+ $_POST[$this->_current_field] = str_replace(array('<?php', '<?PHP', '<?', '?>'), array('&lt;?php', '&lt;?PHP', '&lt;?', '?&gt;'), $str);
+ }
+
+}
+// END Validation Class
+?> \ No newline at end of file
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
new file mode 100644
index 000000000..9eeb46a15
--- /dev/null
+++ b/system/libraries/Xmlrpc.php
@@ -0,0 +1,1409 @@
+<?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
+ */
+
+if ( ! function_exists('xml_parser_create'))
+{
+ show_error('Your PHP installation does not support XML');
+}
+
+/**
+ * XML-RPC request handler class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category XML-RPC
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/xmlrpc.html
+ */
+class CI_XML_RPC {
+
+ var $debug = FALSE; // Debugging on or off
+ var $xmlrpcI4 = 'i4';
+ var $xmlrpcInt = 'int';
+ var $xmlrpcBoolean = 'boolean';
+ var $xmlrpcDouble = 'double';
+ var $xmlrpcString = 'string';
+ var $xmlrpcDateTime = 'dateTime.iso8601';
+ var $xmlrpcBase64 = 'base64';
+ var $xmlrpcArray = 'array';
+ var $xmlrpcStruct = 'struct';
+
+ var $xmlrpcTypes = array();
+ var $valid_parents = array();
+ var $xmlrpcerr = array(); // Response numbers
+ var $xmlrpcstr = array(); // Response strings
+
+ var $xmlrpc_defencoding = 'UTF-8';
+ var $xmlrpcName = 'XML-RPC for CodeIgniter';
+ var $xmlrpcVersion = '1.1';
+ var $xmlrpcerruser = 800; // Start of user errors
+ var $xmlrpcerrxml = 100; // Start of XML Parse errors
+ var $xmlrpc_backslash = ''; // formulate backslashes for escaping regexp
+
+ var $client;
+ var $method;
+ var $data;
+ var $message = '';
+ var $error = ''; // Error string for request
+ var $result;
+ var $response = array(); // Response from remote server
+
+
+ //-------------------------------------
+ // VALUES THAT MULTIPLE CLASSES NEED
+ //-------------------------------------
+
+ function CI_XML_RPC ($config = array())
+ {
+
+ $this->xmlrpcName = $this->xmlrpcName;
+ $this->xmlrpc_backslash = chr(92).chr(92);
+
+ // Types for info sent back and forth
+ $this->xmlrpcTypes = array(
+ $this->xmlrpcI4 => '1',
+ $this->xmlrpcInt => '1',
+ $this->xmlrpcBoolean => '1',
+ $this->xmlrpcString => '1',
+ $this->xmlrpcDouble => '1',
+ $this->xmlrpcDateTime => '1',
+ $this->xmlrpcBase64 => '1',
+ $this->xmlrpcArray => '2',
+ $this->xmlrpcStruct => '3'
+ );
+
+ // Array of Valid Parents for Various XML-RPC elements
+ $this->valid_parents = array('BOOLEAN' => array('VALUE'),
+ 'I4' => array('VALUE'),
+ 'INT' => array('VALUE'),
+ 'STRING' => array('VALUE'),
+ 'DOUBLE' => array('VALUE'),
+ 'DATETIME.ISO8601' => array('VALUE'),
+ 'BASE64' => array('VALUE'),
+ 'ARRAY' => array('VALUE'),
+ 'STRUCT' => array('VALUE'),
+ 'PARAM' => array('PARAMS'),
+ 'METHODNAME' => array('METHODCALL'),
+ 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'),
+ 'MEMBER' => array('STRUCT'),
+ 'NAME' => array('MEMBER'),
+ 'DATA' => array('ARRAY'),
+ 'FAULT' => array('METHODRESPONSE'),
+ 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT')
+ );
+
+
+ // XML-RPC Responses
+ $this->xmlrpcerr['unknown_method'] = '1';
+ $this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';
+ $this->xmlrpcerr['invalid_return'] = '2';
+ $this->xmlrpcstr['invalid_return'] = 'The XML data receieved was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';
+ $this->xmlrpcerr['incorrect_params'] = '3';
+ $this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';
+ $this->xmlrpcerr['introspect_unknown'] = '4';
+ $this->xmlrpcstr['introspect_unknown'] = "Cannot inspect signature for request: method unknown";
+ $this->xmlrpcerr['http_error'] = '5';
+ $this->xmlrpcstr['http_error'] = "Did not receive a '200 OK' response from remote server.";
+ $this->xmlrpcerr['no_data'] = '6';
+ $this->xmlrpcstr['no_data'] ='No data received from server.';
+
+ $this->initialize($config);
+
+ log_message('debug', "XML-RPC Class Initialized");
+ }
+
+
+ //-------------------------------------
+ // Initialize Prefs
+ //-------------------------------------
+
+ function initialize($config = array())
+ {
+ if (sizeof($config) > 0)
+ {
+ foreach ($config as $key => $val)
+ {
+ if (isset($this->$key))
+ {
+ $this->$key = $val;
+ }
+ }
+ }
+ }
+ // END
+
+ //-------------------------------------
+ // Take URL and parse it
+ //-------------------------------------
+
+ function server($url, $port=80)
+ {
+ if (substr($url, 0, 4) != "http")
+ {
+ $url = "http://".$url;
+ }
+
+ $parts = parse_url($url);
+
+ $path = (!isset($parts['path'])) ? '/' : $parts['path'];
+
+ if (isset($parts['query']) && $parts['query'] != '')
+ {
+ $path .= '?'.$parts['query'];
+ }
+
+ $this->client = new XML_RPC_Client($path, $parts['host'], $port);
+ }
+ // END
+
+ //-------------------------------------
+ // Set Timeout
+ //-------------------------------------
+
+ function timeout($seconds=5)
+ {
+ if ( ! is_null($this->client) && is_int($seconds))
+ {
+ $this->client->timeout = $seconds;
+ }
+ }
+ // END
+
+ //-------------------------------------
+ // Set Methods
+ //-------------------------------------
+
+ function method($function)
+ {
+ $this->method = $function;
+ }
+ // END
+
+ //-------------------------------------
+ // Take Array of Data and Create Objects
+ //-------------------------------------
+
+ function request($incoming)
+ {
+ if ( ! is_array($incoming))
+ {
+ // Send Error
+ }
+
+ foreach($incoming as $key => $value)
+ {
+ $this->data[$key] = $this->values_parsing($value);
+ }
+ }
+ // END
+
+
+ //-------------------------------------
+ // Set Debug
+ //-------------------------------------
+
+ function set_debug($flag = TRUE)
+ {
+ $this->debug = ($flag == TRUE) ? TRUE : FALSE;
+ }
+
+ //-------------------------------------
+ // Values Parsing
+ //-------------------------------------
+
+ function values_parsing($value, $return = FALSE)
+ {
+ if (is_array($value) && isset($value['0']))
+ {
+ if ( ! isset($value['1']) OR ! isset($this->xmlrpcTypes[strtolower($value['1'])]))
+ {
+ $temp = new XML_RPC_Values($value['0'], 'string');
+ }
+ elseif(is_array($value['0']) && ($value['1'] == 'struct' OR $value['1'] == 'array'))
+ {
+ while (list($k) = each($value['0']))
+ {
+ $value['0'][$k] = $this->values_parsing($value['0'][$k], TRUE);
+ }
+
+ $temp = new XML_RPC_Values($value['0'], $value['1']);
+ }
+ else
+ {
+ $temp = new XML_RPC_Values($value['0'], $value['1']);
+ }
+ }
+ else
+ {
+ $temp = new XML_RPC_Values($value, 'string');
+ }
+
+ return $temp;
+ }
+ // END
+
+
+ //-------------------------------------
+ // Sends XML-RPC Request
+ //-------------------------------------
+
+ function send_request()
+ {
+ $this->message = new XML_RPC_Message($this->method,$this->data);
+ $this->message->debug = $this->debug;
+
+ if ( ! $this->result = $this->client->send($this->message))
+ {
+ $this->error = $this->result->errstr;
+ return FALSE;
+ }
+ elseif( ! is_object($this->result->val))
+ {
+ $this->error = $this->result->errstr;
+ return FALSE;
+ }
+
+ $this->response = $this->result->decode();
+
+ return TRUE;
+ }
+ // END
+
+ //-------------------------------------
+ // Returns Error
+ //-------------------------------------
+
+ function display_error()
+ {
+ return $this->error;
+ }
+ // END
+
+ //-------------------------------------
+ // Returns Remote Server Response
+ //-------------------------------------
+
+ function display_response()
+ {
+ return $this->response;
+ }
+ // END
+
+ //-------------------------------------
+ // Sends an Error Message for Server Request
+ //-------------------------------------
+
+ function send_error_message($number, $message)
+ {
+ return new XML_RPC_Response('0',$number, $message);
+ }
+ // END
+
+
+ //-------------------------------------
+ // Send Response for Server Request
+ //-------------------------------------
+
+ function send_response($response)
+ {
+ // $response should be array of values, which will be parsed
+ // based on their data and type into a valid group of XML-RPC values
+
+ $response = $this->values_parsing($response);
+
+ return new XML_RPC_Response($response);
+ }
+ // END
+
+} // END XML_RPC Class
+
+
+
+/**
+ * XML-RPC Client class
+ *
+ * @category XML-RPC
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/xmlrpc.html
+ */
+class XML_RPC_Client extends CI_XML_RPC
+{
+ var $path = '';
+ var $server = '';
+ var $port = 80;
+ var $errno = '';
+ var $errstring = '';
+ var $timeout = 5;
+ var $no_multicall = false;
+
+ function XML_RPC_Client($path, $server, $port=80)
+ {
+ parent::CI_XML_RPC();
+
+ $this->port = $port;
+ $this->server = $server;
+ $this->path = $path;
+ }
+
+ function send($msg)
+ {
+ if (is_array($msg))
+ {
+ // Multi-call disabled
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'],$this->xmlrpcstr['multicall_recursion']);
+ return $r;
+ }
+
+ return $this->sendPayload($msg);
+ }
+
+ function sendPayload($msg)
+ {
+ $fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstr, $this->timeout);
+
+ if (! is_resource($fp))
+ {
+ error_log($this->xmlrpcstr['http_error']);
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'],$this->xmlrpcstr['http_error']);
+ return $r;
+ }
+
+ if(empty($msg->payload))
+ {
+ // $msg = XML_RPC_Messages
+ $msg->createPayload();
+ }
+
+ $r = "\r\n";
+ $op = "POST {$this->path} HTTP/1.0$r";
+ $op .= "Host: {$this->server}$r";
+ $op .= "Content-Type: text/xml$r";
+ $op .= "User-Agent: {$this->xmlrpcName}$r";
+ $op .= "Content-Length: ".strlen($msg->payload). "$r$r";
+ $op .= $msg->payload;
+
+
+ if (!fputs($fp, $op, strlen($op)))
+ {
+ error_log($this->xmlrpcstr['http_error']);
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
+ return $r;
+ }
+ $resp = $msg->parseResponse($fp);
+ fclose($fp);
+ return $resp;
+ }
+
+} // end class XML_RPC_Client
+
+
+/**
+ * XML-RPC Response class
+ *
+ * @category XML-RPC
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/xmlrpc.html
+ */
+class XML_RPC_Response
+{
+ var $val = 0;
+ var $errno = 0;
+ var $errstr = '';
+ var $headers = array();
+
+ function XML_RPC_Response($val, $code = 0, $fstr = '')
+ {
+ if ($code != 0)
+ {
+ // error
+ $this->errno = $code;
+ $this->errstr = htmlentities($fstr);
+ }
+ else if (!is_object($val))
+ {
+ // programmer error, not an object
+ error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to XML_RPC_Response. Defaulting to empty value.");
+ $this->val = new XML_RPC_Values();
+ }
+ else
+ {
+ $this->val = $val;
+ }
+ }
+
+ function faultCode()
+ {
+ return $this->errno;
+ }
+
+ function faultString()
+ {
+ return $this->errstr;
+ }
+
+ function value()
+ {
+ return $this->val;
+ }
+
+ function prepare_response()
+ {
+ $result = "<methodResponse>\n";
+ if ($this->errno)
+ {
+ $result .= '<fault>
+ <value>
+ <struct>
+ <member>
+ <name>faultCode</name>
+ <value><int>' . $this->errno . '</int></value>
+ </member>
+ <member>
+ <name>faultString</name>
+ <value><string>' . $this->errstr . '</string></value>
+ </member>
+ </struct>
+ </value>
+</fault>';
+ }
+ else
+ {
+ $result .= "<params>\n<param>\n" .
+ $this->val->serialize_class() .
+ "</param>\n</params>";
+ }
+ $result .= "\n</methodResponse>";
+ return $result;
+ }
+
+ function decode($array=FALSE)
+ {
+ $obj =& get_instance();
+
+ if ($array !== FALSE && is_array($array))
+ {
+ while (list($key) = each($array))
+ {
+ if (is_array($array[$key]))
+ {
+ $array[$key] = $this->decode($array[$key]);
+ }
+ else
+ {
+ $array[$key] = $obj->input->xss_clean($array[$key]);
+ }
+ }
+
+ $result = $array;
+ }
+ else
+ {
+ $result = $this->xmlrpc_decoder($this->val);
+
+ if (is_array($result))
+ {
+ $result = $this->decode($result);
+ }
+ else
+ {
+ $result = $obj->input->xss_clean($result);
+ }
+ }
+
+ return $result;
+ }
+
+
+
+ //-------------------------------------
+ // XML-RPC Object to PHP Types
+ //-------------------------------------
+
+ function xmlrpc_decoder($xmlrpc_val)
+ {
+ $kind = $xmlrpc_val->kindOf();
+
+ if($kind == 'scalar')
+ {
+ return $xmlrpc_val->scalarval();
+ }
+ elseif($kind == 'array')
+ {
+ reset($xmlrpc_val->me);
+ list($a,$b) = each($xmlrpc_val->me);
+ $size = sizeof($b);
+
+ $arr = array();
+
+ for($i = 0; $i < $size; $i++)
+ {
+ $arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);
+ }
+ return $arr;
+ }
+ elseif($kind == 'struct')
+ {
+ reset($xmlrpc_val->me['struct']);
+ $arr = array();
+
+ while(list($key,$value) = each($xmlrpc_val->me['struct']))
+ {
+ $arr[$key] = $this->xmlrpc_decoder($value);
+ }
+ return $arr;
+ }
+ }
+
+
+ //-------------------------------------
+ // ISO-8601 time to server or UTC time
+ //-------------------------------------
+
+ function iso8601_decode($time, $utc=0)
+ {
+ // return a timet in the localtime, or UTC
+ $t = 0;
+ if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})", $time, $regs))
+ {
+ if ($utc == 1)
+ $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
+ else
+ $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
+ }
+ return $t;
+ }
+
+} // End Response Class
+
+
+
+/**
+ * XML-RPC Message class
+ *
+ * @category XML-RPC
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/xmlrpc.html
+ */
+class XML_RPC_Message extends CI_XML_RPC
+{
+ var $payload;
+ var $method_name;
+ var $params = array();
+ var $xh = array();
+
+ function XML_RPC_Message($method, $pars=0)
+ {
+ parent::CI_XML_RPC();
+
+ $this->method_name = $method;
+ if (is_array($pars) && sizeof($pars) > 0)
+ {
+ for($i=0; $i<sizeof($pars); $i++)
+ {
+ // $pars[$i] = XML_RPC_Values
+ $this->params[] = $pars[$i];
+ }
+ }
+ }
+
+ //-------------------------------------
+ // Create Payload to Send
+ //-------------------------------------
+
+ function createPayload()
+ {
+ $this->payload = "<?xml version=\"1.0\"?".">\r\n<methodCall>\r\n";
+ $this->payload .= '<methodName>' . $this->method_name . "</methodName>\r\n";
+ $this->payload .= "<params>\r\n";
+
+ for($i=0; $i<sizeof($this->params); $i++)
+ {
+ // $p = XML_RPC_Values
+ $p = $this->params[$i];
+ $this->payload .= "<param>\r\n".$p->serialize_class()."</param>\r\n";
+ }
+
+ $this->payload .= "</params>\r\n</methodCall>\r\n";
+ }
+
+ //-------------------------------------
+ // Parse External XML-RPC Server's Response
+ //-------------------------------------
+
+ function parseResponse($fp)
+ {
+ $data = '';
+
+ while($datum = fread($fp, 4096))
+ {
+ $data .= $datum;
+ }
+
+ //-------------------------------------
+ // DISPLAY HTTP CONTENT for DEBUGGING
+ //-------------------------------------
+
+ if ($this->debug === TRUE)
+ {
+ echo "<pre>";
+ echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
+ echo "</pre>";
+ }
+
+ //-------------------------------------
+ // Check for data
+ //-------------------------------------
+
+ if($data == "")
+ {
+ error_log($this->xmlrpcstr['no_data']);
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);
+ return $r;
+ }
+
+
+ //-------------------------------------
+ // Check for HTTP 200 Response
+ //-------------------------------------
+
+ if(ereg("^HTTP",$data) && !ereg("^HTTP/[0-9\.]+ 200 ", $data))
+ {
+ $errstr= substr($data, 0, strpos($data, "\n")-1);
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']. ' (' . $errstr . ')');
+ return $r;
+ }
+
+ //-------------------------------------
+ // Create and Set Up XML Parser
+ //-------------------------------------
+
+ $parser = xml_parser_create($this->xmlrpc_defencoding);
+
+ $this->xh[$parser] = array();
+ $this->xh[$parser]['isf'] = 0;
+ $this->xh[$parser]['ac'] = '';
+ $this->xh[$parser]['headers'] = array();
+ $this->xh[$parser]['stack'] = array();
+ $this->xh[$parser]['valuestack'] = array();
+ $this->xh[$parser]['isf_reason'] = 0;
+
+ xml_set_object($parser, $this);
+ xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
+ xml_set_element_handler($parser, 'open_tag', 'closing_tag');
+ xml_set_character_data_handler($parser, 'character_data');
+ //xml_set_default_handler($parser, 'default_handler');
+
+
+ //-------------------------------------
+ // GET HEADERS
+ //-------------------------------------
+
+ $lines = explode("\r\n", $data);
+ while (($line = array_shift($lines)))
+ {
+ if (strlen($line) < 1)
+ {
+ break;
+ }
+ $this->xh[$parser]['headers'][] = $line;
+ }
+ $data = implode("\r\n", $lines);
+
+
+ //-------------------------------------
+ // PARSE XML DATA
+ //-------------------------------------
+
+ if (!xml_parse($parser, $data, sizeof($data)))
+ {
+ $errstr = sprintf('XML error: %s at line %d',
+ xml_error_string(xml_get_error_code($parser)),
+ xml_get_current_line_number($parser));
+ //error_log($errstr);
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);
+ xml_parser_free($parser);
+ return $r;
+ }
+ xml_parser_free($parser);
+
+ // ---------------------------------------
+ // Got Ourselves Some Badness, It Seems
+ // ---------------------------------------
+
+ if ($this->xh[$parser]['isf'] > 1)
+ {
+ if ($this->debug === TRUE)
+ {
+ echo "---Invalid Return---\n";
+ echo $this->xh[$parser]['isf_reason'];
+ echo "---Invalid Return---\n\n";
+ }
+
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
+ return $r;
+ }
+ elseif ( ! is_object($this->xh[$parser]['value']))
+ {
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'],$this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
+ return $r;
+ }
+
+ //-------------------------------------
+ // DISPLAY XML CONTENT for DEBUGGING
+ //-------------------------------------
+
+ if ($this->debug === TRUE)
+ {
+ echo "<pre>";
+
+ if (count($this->xh[$parser]['headers'] > 0))
+ {
+ echo "---HEADERS---\n";
+ foreach ($this->xh[$parser]['headers'] as $header)
+ {
+ echo "$header\n";
+ }
+ echo "---END HEADERS---\n\n";
+ }
+
+ echo "---DATA---\n" . htmlspecialchars($data) . "\n---END DATA---\n\n";
+
+ echo "---PARSED---\n" ;
+ var_dump($this->xh[$parser]['value']);
+ echo "\n---END PARSED---</pre>";
+ }
+
+ //-------------------------------------
+ // SEND RESPONSE
+ //-------------------------------------
+
+ $v = $this->xh[$parser]['value'];
+
+ if ($this->xh[$parser]['isf'])
+ {
+ $errno_v = $v->me['struct']['faultCode'];
+ $errstr_v = $v->me['struct']['faultString'];
+ $errno = $errno_v->scalarval();
+
+ if ($errno == 0)
+ {
+ // FAULT returned, errno needs to reflect that
+ $errno = -1;
+ }
+
+ $r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());
+ }
+ else
+ {
+ $r = new XML_RPC_Response($v);
+ }
+
+ $r->headers = $this->xh[$parser]['headers'];
+ return $r;
+ }
+
+ // ------------------------------------
+ // Begin Return Message Parsing section
+ // ------------------------------------
+
+ // quick explanation of components:
+ // ac - used to accumulate values
+ // isf - used to indicate a fault
+ // lv - used to indicate "looking for a value": implements
+ // the logic to allow values with no types to be strings
+ // params - used to store parameters in method calls
+ // method - used to store method name
+ // stack - array with parent tree of the xml element,
+ // used to validate the nesting of elements
+
+ //-------------------------------------
+ // Start Element Handler
+ //-------------------------------------
+
+ function open_tag($the_parser, $name, $attrs)
+ {
+ // If invalid nesting, then return
+ if ($this->xh[$the_parser]['isf'] > 1) return;
+
+ // Evaluate and check for correct nesting of XML elements
+
+ if (count($this->xh[$the_parser]['stack']) == 0)
+ {
+ if ($name != 'METHODRESPONSE' && $name != 'METHODCALL')
+ {
+ $this->xh[$the_parser]['isf'] = 2;
+ $this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';
+ return;
+ }
+ }
+ else
+ {
+ // not top level element: see if parent is OK
+ if (!in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name]))
+ {
+ $this->xh[$the_parser]['isf'] = 2;
+ $this->xh[$the_parser]['isf_reason'] = "XML-RPC element $name cannot be child of ".$this->xh[$the_parser]['stack'][0];
+ return;
+ }
+ }
+
+ switch($name)
+ {
+ case 'STRUCT':
+ case 'ARRAY':
+ // Creates array for child elements
+
+ $cur_val = array('value' => array(),
+ 'type' => $name);
+
+ array_unshift($this->xh[$the_parser]['valuestack'], $cur_val);
+ break;
+ case 'METHODNAME':
+ case 'NAME':
+ $this->xh[$the_parser]['ac'] = '';
+ break;
+ case 'FAULT':
+ $this->xh[$the_parser]['isf'] = 1;
+ break;
+ case 'PARAM':
+ $this->xh[$the_parser]['value'] = null;
+ break;
+ case 'VALUE':
+ $this->xh[$the_parser]['vt'] = 'value';
+ $this->xh[$the_parser]['ac'] = '';
+ $this->xh[$the_parser]['lv'] = 1;
+ break;
+ case 'I4':
+ case 'INT':
+ case 'STRING':
+ case 'BOOLEAN':
+ case 'DOUBLE':
+ case 'DATETIME.ISO8601':
+ case 'BASE64':
+ if ($this->xh[$the_parser]['vt'] != 'value')
+ {
+ //two data elements inside a value: an error occurred!
+ $this->xh[$the_parser]['isf'] = 2;
+ $this->xh[$the_parser]['isf_reason'] = "'Twas a $name element following a ".$this->xh[$the_parser]['vt']." element inside a single value";
+ return;
+ }
+
+ $this->xh[$the_parser]['ac'] = '';
+ break;
+ case 'MEMBER':
+ // Set name of <member> to nothing to prevent errors later if no <name> is found
+ $this->xh[$the_parser]['valuestack'][0]['name'] = '';
+
+ // Set NULL value to check to see if value passed for this param/member
+ $this->xh[$the_parser]['value'] = null;
+ break;
+ case 'DATA':
+ case 'METHODCALL':
+ case 'METHODRESPONSE':
+ case 'PARAMS':
+ // valid elements that add little to processing
+ break;
+ default:
+ /// An Invalid Element is Found, so we have trouble
+ $this->xh[$the_parser]['isf'] = 2;
+ $this->xh[$the_parser]['isf_reason'] = "Invalid XML-RPC element found: $name";
+ break;
+ }
+
+ // Add current element name to stack, to allow validation of nesting
+ array_unshift($this->xh[$the_parser]['stack'], $name);
+
+ if ($name != 'VALUE') $this->xh[$the_parser]['lv'] = 0;
+ }
+ // END
+
+
+ //-------------------------------------
+ // End Element Handler
+ //-------------------------------------
+
+ function closing_tag($the_parser, $name)
+ {
+ if ($this->xh[$the_parser]['isf'] > 1) return;
+
+ // Remove current element from stack and set variable
+ // NOTE: If the XML validates, then we do not have to worry about
+ // the opening and closing of elements. Nesting is checked on the opening
+ // tag so we be safe there as well.
+
+ $curr_elem = array_shift($this->xh[$the_parser]['stack']);
+
+ switch($name)
+ {
+ case 'STRUCT':
+ case 'ARRAY':
+ $cur_val = array_shift($this->xh[$the_parser]['valuestack']);
+ $this->xh[$the_parser]['value'] = ( ! isset($cur_val['values'])) ? array() : $cur_val['values'];
+ $this->xh[$the_parser]['vt'] = strtolower($name);
+ break;
+ case 'NAME':
+ $this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];
+ break;
+ case 'BOOLEAN':
+ case 'I4':
+ case 'INT':
+ case 'STRING':
+ case 'DOUBLE':
+ case 'DATETIME.ISO8601':
+ case 'BASE64':
+ $this->xh[$the_parser]['vt'] = strtolower($name);
+
+ if ($name == 'STRING')
+ {
+ $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
+ }
+ elseif ($name=='DATETIME.ISO8601')
+ {
+ $this->xh[$the_parser]['vt'] = $this->xmlrpcDateTime;
+ $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
+ }
+ elseif ($name=='BASE64')
+ {
+ $this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);
+ }
+ elseif ($name=='BOOLEAN')
+ {
+ // Translated BOOLEAN values to TRUE AND FALSE
+ if ($this->xh[$the_parser]['ac'] == '1')
+ {
+ $this->xh[$the_parser]['value'] = TRUE;
+ }
+ else
+ {
+ $this->xh[$the_parser]['value'] = FALSE;
+ }
+ }
+ elseif ($name=='DOUBLE')
+ {
+ // we have a DOUBLE
+ // we must check that only 0123456789-.<space> are characters here
+ if (!ereg("^[+-]?[eE0123456789 \\t\\.]+$", $this->xh[$the_parser]['ac']))
+ {
+ $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
+ }
+ else
+ {
+ $this->xh[$the_parser]['value'] = (double)$this->xh[$the_parser]['ac'];
+ }
+ }
+ else
+ {
+ // we have an I4/INT
+ // we must check that only 0123456789-<space> are characters here
+ if (!ereg("^[+-]?[0123456789 \\t]+$", $this->xh[$the_parser]['ac']))
+ {
+ $this->xh[$the_parser]['value'] = 'ERROR_NON_NUMERIC_FOUND';
+ }
+ else
+ {
+ $this->xh[$the_parser]['value'] = (int)$this->xh[$the_parser]['ac'];
+ }
+ }
+ $this->xh[$the_parser]['ac'] = '';
+ $this->xh[$the_parser]['lv'] = 3; // indicate we've found a value
+ break;
+ case 'VALUE':
+ // This if() detects if no scalar was inside <VALUE></VALUE>
+ if ($this->xh[$the_parser]['vt']=='value')
+ {
+ $this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];
+ $this->xh[$the_parser]['vt'] = $this->xmlrpcString;
+ }
+
+ // build the XML-RPC value out of the data received, and substitute it
+ $temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);
+
+ if (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] == 'ARRAY')
+ {
+ // Array
+ $this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;
+ }
+ else
+ {
+ // Struct
+ $this->xh[$the_parser]['value'] = $temp;
+ }
+ break;
+ case 'MEMBER':
+ $this->xh[$the_parser]['ac']='';
+
+ // If value add to array in the stack for the last element built
+ if ($this->xh[$the_parser]['value'])
+ {
+ $this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];
+ }
+ break;
+ case 'DATA':
+ $this->xh[$the_parser]['ac']='';
+ break;
+ case 'PARAM':
+ if ($this->xh[$the_parser]['value'])
+ {
+ $this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];
+ }
+ break;
+ case 'METHODNAME':
+ $this->xh[$the_parser]['method'] = ereg_replace("^[\n\r\t ]+", '', $this->xh[$the_parser]['ac']);
+ break;
+ case 'PARAMS':
+ case 'FAULT':
+ case 'METHODCALL':
+ case 'METHORESPONSE':
+ // We're all good kids with nuthin' to do
+ break;
+ default:
+ // End of an Invalid Element. Taken care of during the opening tag though
+ break;
+ }
+ }
+
+ //-------------------------------------
+ // Parses Character Data
+ //-------------------------------------
+
+ function character_data($the_parser, $data)
+ {
+ if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
+
+ // If a value has not been found
+ if ($this->xh[$the_parser]['lv'] != 3)
+ {
+ if ($this->xh[$the_parser]['lv'] == 1)
+ {
+ $this->xh[$the_parser]['lv'] = 2; // Found a value
+ }
+
+ if( ! @isset($this->xh[$the_parser]['ac']))
+ {
+ $this->xh[$the_parser]['ac'] = '';
+ }
+
+ $this->xh[$the_parser]['ac'] .= $data;
+ }
+ }
+
+
+ function addParam($par) { $this->params[]=$par; }
+
+ function output_parameters($array=FALSE)
+ {
+ $obj =& get_instance();
+
+ if ($array !== FALSE && is_array($array))
+ {
+ while (list($key) = each($array))
+ {
+ if (is_array($array[$key]))
+ {
+ $array[$key] = $this->output_parameters($array[$key]);
+ }
+ else
+ {
+ $array[$key] = $obj->input->xss_clean($array[$key]);
+ }
+ }
+
+ $parameters = $array;
+ }
+ else
+ {
+ $parameters = array();
+
+ for ($i = 0; $i < sizeof($this->params); $i++)
+ {
+ $a_param = $this->decode_message($this->params[$i]);
+
+ if (is_array($a_param))
+ {
+ $parameters[] = $this->output_parameters($a_param);
+ }
+ else
+ {
+ $parameters[] = $obj->input->xss_clean($a_param);
+ }
+ }
+ }
+
+ return $parameters;
+ }
+
+
+ function decode_message($param)
+ {
+ $kind = $param->kindOf();
+
+ if($kind == 'scalar')
+ {
+ return $param->scalarval();
+ }
+ elseif($kind == 'array')
+ {
+ reset($param->me);
+ list($a,$b) = each($param->me);
+
+ $arr = array();
+
+ for($i = 0; $i < sizeof($b); $i++)
+ {
+ $arr[] = $this->decode_message($param->me['array'][$i]);
+ }
+
+ return $arr;
+ }
+ elseif($kind == 'struct')
+ {
+ reset($param->me['struct']);
+
+ $arr = array();
+
+ while(list($key,$value) = each($param->me['struct']))
+ {
+ $arr[$key] = $this->decode_message($value);
+ }
+
+ return $arr;
+ }
+ }
+
+} // End XML_RPC_Messages class
+
+
+
+/**
+ * XML-RPC Values class
+ *
+ * @category XML-RPC
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/xmlrpc.html
+ */
+class XML_RPC_Values extends CI_XML_RPC
+{
+ var $me = array();
+ var $mytype = 0;
+
+ function XML_RPC_Values($val=-1, $type='')
+ {
+ parent::CI_XML_RPC();
+
+ if ($val != -1 || $type != '')
+ {
+ $type = $type == '' ? 'string' : $type;
+
+ if ($this->xmlrpcTypes[$type] == 1)
+ {
+ $this->addScalar($val,$type);
+ }
+ elseif ($this->xmlrpcTypes[$type] == 2)
+ {
+ $this->addArray($val);
+ }
+ elseif ($this->xmlrpcTypes[$type] == 3)
+ {
+ $this->addStruct($val);
+ }
+ }
+ }
+
+ function addScalar($val, $type='string')
+ {
+ $typeof = $this->xmlrpcTypes[$type];
+
+ if ($this->mytype==1)
+ {
+ echo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';
+ return 0;
+ }
+
+ if ($typeof != 1)
+ {
+ echo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';
+ return 0;
+ }
+
+ if ($type == $this->xmlrpcBoolean)
+ {
+ if (strcasecmp($val,'true')==0 || $val==1 || ($val==true && strcasecmp($val,'false')))
+ {
+ $val = 1;
+ }
+ else
+ {
+ $val=0;
+ }
+ }
+
+ if ($this->mytype == 2)
+ {
+ // adding to an array here
+ $ar = $this->me['array'];
+ $ar[] = new XML_RPC_Values($val, $type);
+ $this->me['array'] = $ar;
+ }
+ else
+ {
+ // a scalar, so set the value and remember we're scalar
+ $this->me[$type] = $val;
+ $this->mytype = $typeof;
+ }
+ return 1;
+ }
+
+ function addArray($vals)
+ {
+ if ($this->mytype != 0)
+ {
+ echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
+ return 0;
+ }
+
+ $this->mytype = $this->xmlrpcTypes['array'];
+ $this->me['array'] = $vals;
+ return 1;
+ }
+
+ function addStruct($vals)
+ {
+ if ($this->mytype != 0)
+ {
+ echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
+ return 0;
+ }
+ $this->mytype = $this->xmlrpcTypes['struct'];
+ $this->me['struct'] = $vals;
+ return 1;
+ }
+
+ function kindOf()
+ {
+ switch($this->mytype)
+ {
+ case 3:
+ return 'struct';
+ break;
+ case 2:
+ return 'array';
+ break;
+ case 1:
+ return 'scalar';
+ break;
+ default:
+ return 'undef';
+ }
+ }
+
+ function serializedata($typ, $val)
+ {
+ $rs = '';
+
+ switch($this->xmlrpcTypes[$typ])
+ {
+ case 3:
+ // struct
+ $rs .= "<struct>\n";
+ reset($val);
+ while(list($key2, $val2) = each($val))
+ {
+ $rs .= "<member>\n<name>{$key2}</name>\n";
+ $rs .= $this->serializeval($val2);
+ $rs .= "</member>\n";
+ }
+ $rs .= '</struct>';
+ break;
+ case 2:
+ // array
+ $rs .= "<array>\n<data>\n";
+ for($i=0; $i < sizeof($val); $i++)
+ {
+ $rs .= $this->serializeval($val[$i]);
+ }
+ $rs.="</data>\n</array>\n";
+ break;
+ case 1:
+ // others
+ switch ($typ)
+ {
+ case $this->xmlrpcBase64:
+ $rs .= "<{$typ}>" . base64_encode($val) . "</{$typ}>\n";
+ break;
+ case $this->xmlrpcBoolean:
+ $rs .= "<{$typ}>" . ($val ? '1' : '0') . "</{$typ}>\n";
+ break;
+ case $this->xmlrpcString:
+ $rs .= "<{$typ}>" . htmlspecialchars($val). "</{$typ}>\n";
+ break;
+ default:
+ $rs .= "<{$typ}>{$val}</{$typ}>\n";
+ break;
+ }
+ default:
+ break;
+ }
+ return $rs;
+ }
+
+ function serialize_class()
+ {
+ return $this->serializeval($this);
+ }
+
+ function serializeval($o)
+ {
+
+ $ar = $o->me;
+ reset($ar);
+
+ list($typ, $val) = each($ar);
+ $rs = "<value>\n".$this->serializedata($typ, $val)."</value>\n";
+ return $rs;
+ }
+
+ function scalarval()
+ {
+ reset($this->me);
+ list($a,$b) = each($this->me);
+ return $b;
+ }
+
+
+ //-------------------------------------
+ // Encode time in ISO-8601 form.
+ //-------------------------------------
+
+ // Useful for sending time in XML-RPC
+
+ function iso8601_encode($time, $utc=0)
+ {
+ if ($utc == 1)
+ {
+ $t = strftime("%Y%m%dT%H:%M:%S", $time);
+ }
+ else
+ {
+ if (function_exists('gmstrftime'))
+ $t = gmstrftime("%Y%m%dT%H:%M:%S", $time);
+ else
+ $t = strftime("%Y%m%dT%H:%M:%S", $time - date('Z'));
+ }
+ return $t;
+ }
+
+}
+// END XML_RPC_Values Class
+?> \ No newline at end of file
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
new file mode 100644
index 000000000..eaec87a6d
--- /dev/null
+++ b/system/libraries/Xmlrpcs.php
@@ -0,0 +1,492 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * XML-RPC server class
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category XML-RPC
+ * @author Paul Burdick
+ * @link http://www.codeigniter.com/user_guide/libraries/xmlrpc.html
+ */
+class CI_XML_RPC_Server extends CI_XML_RPC
+{
+ var $methods = array(); //array of methods mapped to function names and signatures
+ var $debug_msg = ''; // Debug Message
+ var $system_methods = array(); // XML RPC Server methods
+ var $controller_obj;
+
+
+ //-------------------------------------
+ // Constructor, more or less
+ //-------------------------------------
+
+ function CI_XML_RPC_Server($config=array())
+ {
+ parent::CI_XML_RPC();
+ $this->set_system_methods();
+
+ if (isset($config['functions']) && is_array($config['functions']))
+ {
+ $this->methods = $config['functions'];
+ }
+
+ log_message('debug', "XML-RPC Server Class Initialized");
+ }
+
+ //-------------------------------------
+ // Initialize Prefs and Serve
+ //-------------------------------------
+
+ function initialize($config=array())
+ {
+ if (isset($config['functions']) && is_array($config['functions']))
+ {
+ $this->methods = $config['functions'];
+ }
+
+ if (isset($config['debug']))
+ {
+ $this->debug = $config['debug'];
+ }
+ }
+
+ //-------------------------------------
+ // Setting of System Methods
+ //-------------------------------------
+
+ function set_system_methods ()
+ {
+ $system_methods = array(
+ 'system.listMethods' => array(
+ 'function' => 'this.listMethods',
+ 'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString), array($this->xmlrpcArray)),
+ 'docstring' => 'Returns an array of available methods on this server'),
+ 'system.methodHelp' => array(
+ 'function' => 'this.methodHelp',
+ 'signature' => array(array($this->xmlrpcString, $this->xmlrpcString)),
+ 'docstring' => 'Returns a documentation string for the specified method'),
+ 'system.methodSignature' => array(
+ 'function' => 'this.methodSignature',
+ 'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString)),
+ 'docstring' => 'Returns an array describing the return type and required parameters of a method'),
+ 'system.multicall' => array(
+ 'function' => 'this.multicall',
+ 'signature' => array(array($this->xmlrpcArray, $this->xmlrpcArray)),
+ 'docstring' => 'Combine multiple RPC calls in one request. See http://www.xmlrpc.com/discuss/msgReader$1208 for details')
+ );
+ }
+
+
+ //-------------------------------------
+ // Main Server Function
+ //-------------------------------------
+
+ function serve()
+ {
+ $r = $this->parseRequest();
+ $payload = '<?xml version="1.0" encoding="'.$this->xmlrpc_defencoding.'"?'.'>'."\n";
+ $payload .= $this->debug_msg;
+ $payload .= $r->prepare_response();
+
+ header("Content-Type: text/xml");
+ header("Content-Length: ".strlen($payload));
+ echo $payload;
+ }
+
+ //-------------------------------------
+ // Add Method to Class
+ //-------------------------------------
+
+ function add_to_map($methodname,$function,$sig,$doc)
+ {
+ $this->methods[$methodname] = array(
+ 'function' => $function,
+ 'signature' => $sig,
+ 'docstring' => $doc
+ );
+ }
+
+
+ //-------------------------------------
+ // Parse Server Request
+ //-------------------------------------
+
+ function parseRequest($data='')
+ {
+ global $HTTP_RAW_POST_DATA;
+
+ //-------------------------------------
+ // Get Data
+ //-------------------------------------
+
+ if ($data == '')
+ {
+ $data = $HTTP_RAW_POST_DATA;
+ }
+
+
+ //-------------------------------------
+ // Set up XML Parser
+ //-------------------------------------
+
+ $parser = xml_parser_create($this->xmlrpc_defencoding);
+ $parser_object = new XML_RPC_Message("filler");
+
+ $parser_object->xh[$parser] = array();
+ $parser_object->xh[$parser]['isf'] = 0;
+ $parser_object->xh[$parser]['isf_reason'] = '';
+ $parser_object->xh[$parser]['params'] = array();
+ $parser_object->xh[$parser]['stack'] = array();
+ $parser_object->xh[$parser]['valuestack'] = array();
+ $parser_object->xh[$parser]['method'] = '';
+
+ xml_set_object($parser, $parser_object);
+ xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
+ xml_set_element_handler($parser, 'open_tag', 'closing_tag');
+ xml_set_character_data_handler($parser, 'character_data');
+ //xml_set_default_handler($parser, 'default_handler');
+
+
+ //-------------------------------------
+ // PARSE + PROCESS XML DATA
+ //-------------------------------------
+
+ if ( ! xml_parse($parser, $data, 1))
+ {
+ // return XML error as a faultCode
+ $r = new XML_RPC_Response(0,
+ $this->xmlrpcerrxml + xml_get_error_code($parser),
+ sprintf('XML error: %s at line %d',
+ xml_error_string(xml_get_error_code($parser)),
+ xml_get_current_line_number($parser)));
+ xml_parser_free($parser);
+ }
+ elseif($parser_object->xh[$parser]['isf'])
+ {
+ return new XML_RPC_Response(0,
+ $this->xmlrpcerr['invalid_return'],
+ $this->xmlrpcstr['invalid_retrun']);
+ }
+ else
+ {
+ xml_parser_free($parser);
+
+ $m = new XML_RPC_Message($parser_object->xh[$parser]['method']);
+ $plist='';
+
+ for($i=0; $i < sizeof($parser_object->xh[$parser]['params']); $i++)
+ {
+ $plist .= "$i - " . print_r(get_object_vars($parser_object->xh[$parser]['params'][$i]), TRUE). ";\n";
+
+ $m->addParam($parser_object->xh[$parser]['params'][$i]);
+ }
+
+ if ($this->debug === TRUE)
+ {
+ echo "<pre>";
+ echo "---PLIST---\n" . $plist . "\n---PLIST END---\n\n";
+ echo "</pre>";
+ }
+
+ $r = $this->execute($m);
+ }
+
+ //-------------------------------------
+ // SET DEBUGGING MESSAGE
+ //-------------------------------------
+
+ if ($this->debug === TRUE)
+ {
+ $this->debug_msg = "<!-- DEBUG INFO:\n\n".$plist."\n END DEBUG-->\n";
+ }
+
+ return $r;
+ }
+
+ //-------------------------------------
+ // Executes the Method
+ //-------------------------------------
+
+ function execute($m)
+ {
+ $methName = $m->method_name;
+
+ // Check to see if it is a system call
+ // If so, load the system_methods
+ $sysCall = ereg("^system\.", $methName);
+ $methods = $sysCall ? $this->system_methods : $this->methods;
+
+ //-------------------------------------
+ // Check for Function
+ //-------------------------------------
+
+ if (!isset($methods[$methName]['function']))
+ {
+ return new XML_RPC_Response(0,
+ $this->xmlrpcerr['unknown_method'],
+ $this->xmlrpcstr['unknown_method']);
+ }
+ else
+ {
+ // See if we are calling function in an object
+
+ $method_parts = explode(".",$methods[$methName]['function']);
+ $objectCall = (isset($method_parts['1']) && $method_parts['1'] != "") ? true : false;
+
+ if ($objectCall && !is_callable(array($method_parts['0'],$method_parts['1'])))
+ {
+ return new XML_RPC_Response(0,
+ $this->xmlrpcerr['unknown_method'],
+ $this->xmlrpcstr['unknown_method']);
+ }
+ elseif (!$objectCall && !is_callable($methods[$methName]['function']))
+ {
+ return new XML_RPC_Response(0,
+ $this->xmlrpcerr['unknown_method'],
+ $this->xmlrpcstr['unknown_method']);
+ }
+ }
+
+ //-------------------------------------
+ // Checking Methods Signature
+ //-------------------------------------
+
+ if (isset($methods[$methName]['signature']))
+ {
+ $sig = $methods[$methName]['signature'];
+ for($i=0; $i<sizeof($sig); $i++)
+ {
+ $current_sig = $sig[$i];
+
+ if (sizeof($current_sig) == sizeof($m->params)+1)
+ {
+ for($n=0; $n < sizeof($m->params); $n++)
+ {
+ $p = $m->params[$n];
+ $pt = ($p->kindOf() == 'scalar') ? $p->scalartyp() : $p->kindOf();
+
+ if ($pt != $current_sig[$n+1])
+ {
+ $pno = $n+1;
+ $wanted = $current_sig[$n+1];
+
+ return new XML_RPC_Response(0,
+ $this->xmlrpcerr['incorrect_params'],
+ $this->xmlrpcstr['incorrect_params'] .
+ ": Wanted {$wanted}, got {$pt} at param {$pno})");
+ }
+ }
+ }
+ }
+ }
+
+ //-------------------------------------
+ // Calls the Function
+ //-------------------------------------
+
+ if ($objectCall)
+ {
+ if ($method_parts['1'] == "this")
+ {
+ return call_user_func(array($this, $method_parts['0']), $m);
+ }
+ else
+ {
+ $obj =& get_instance();
+ return $obj->$method_parts['1']($m);
+ //$class = new $method_parts['0'];
+ //return $class->$method_parts['1']($m);
+ //return call_user_func(array(&$method_parts['0'],$method_parts['1']), $m);
+ }
+ }
+ else
+ {
+ return call_user_func($methods[$methName]['function'], $m);
+ }
+ }
+
+
+ //-------------------------------------
+ // Server Function: List Methods
+ //-------------------------------------
+
+ function listMethods($m)
+ {
+ $v = new XML_RPC_Values();
+ $output = array();
+ foreach($this->$methods as $key => $value)
+ {
+ $output[] = new XML_RPC_Values($key, 'string');
+ }
+
+ foreach($this->system_methods as $key => $value)
+ {
+ $output[]= new XML_RPC_Values($key, 'string');
+ }
+
+ $v->addArray($output);
+ return new XML_RPC_Response($v);
+ }
+
+ //-------------------------------------
+ // Server Function: Return Signature for Method
+ //-------------------------------------
+
+ function methodSignature($m)
+ {
+ $methName = $m->getParam(0);
+ $method_name = $methName->scalarval();
+
+ $methods = ereg("^system\.", $method_name) ? $this->system_methods : $this->methods;
+
+ if (isset($methods[$method_name]))
+ {
+ if ($methods[$method_name]['signature'])
+ {
+ $sigs = array();
+ $signature = $methods[$method_name]['signature'];
+
+ for($i=0; $i < sizeof($signature); $i++)
+ {
+ $cursig = array();
+ $inSig = $signature[$i];
+ for($j=0; $j<sizeof($inSig); $j++)
+ {
+ $cursig[]= new XML_RPC_Values($inSig[$j], 'string');
+ }
+ $sigs[]= new XML_RPC_Values($cursig, 'array');
+ }
+ $r = new XML_RPC_Response(new XML_RPC_Values($sigs, 'array'));
+ }
+ else
+ {
+ $r = new XML_RPC_Response(new XML_RPC_Values('undef', 'string'));
+ }
+ }
+ else
+ {
+ $r = new XML_RPC_Response(0,$this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
+ }
+ return $r;
+ }
+
+ //-------------------------------------
+ // Server Function: Doc String for Method
+ //-------------------------------------
+
+ function methodHelp($m)
+ {
+ $methName = $m->getParam(0);
+ $method_name = $methName->scalarval();
+
+ $methods = ereg("^system\.", $method_name) ? $this->system_methods : $this->methods;
+
+ if (isset($methods[$methName]))
+ {
+ $docstring = isset($methods[$method_name]['docstring']) ? $methods[$method_name]['docstring'] : '';
+ $r = new XML_RPC_Response(new XML_RPC_Values($docstring, 'string'));
+ }
+ else
+ {
+ $r = new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
+ }
+ return $r;
+ }
+
+ //-------------------------------------
+ // Server Function: Multi-call
+ //-------------------------------------
+
+ function multicall($m)
+ {
+ $calls = $m->getParam(0);
+ list($a,$b)=each($calls->me);
+ $result = array();
+
+ for ($i = 0; $i < sizeof($b); $i++)
+ {
+ $call = $calls->me['array'][$i];
+ $result[$i] = $this->do_multicall($call);
+ }
+
+ return new XML_RPC_Response(new XML_RPC_Values($result, 'array'));
+ }
+
+
+ //-------------------------------------
+ // Multi-call Function: Error Handling
+ //-------------------------------------
+
+ function multicall_error($err)
+ {
+ $str = is_string($err) ? $this->xmlrpcstr["multicall_${err}"] : $err->faultString();
+ $code = is_string($err) ? $this->xmlrpcerr["multicall_${err}"] : $err->faultCode();
+
+ $struct['faultCode'] = new XML_RPC_Values($code, 'int');
+ $struct['faultString'] = new XML_RPC_Values($str, 'string');
+
+ return new XML_RPC_Values($struct, 'struct');
+ }
+
+
+ //-------------------------------------
+ // Multi-call Function: Processes method
+ //-------------------------------------
+
+ function do_multicall($call)
+ {
+ if ($call->kindOf() != 'struct')
+ return $this->multicall_error('notstruct');
+ elseif (!$methName = $call->me['struct']['methodName'])
+ return $this->multicall_error('nomethod');
+
+ list($scalar_type,$scalar_value)=each($methName->me);
+ $scalar_type = $scalar_type == $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;
+
+ if ($methName->kindOf() != 'scalar' || $scalar_type != 'string')
+ return $this->multicall_error('notstring');
+ elseif ($scalar_value == 'system.multicall')
+ return $this->multicall_error('recursion');
+ elseif (!$params = $call->me['struct']['params'])
+ return $this->multicall_error('noparams');
+ elseif ($params->kindOf() != 'array')
+ return $this->multicall_error('notarray');
+
+ list($a,$b)=each($params->me);
+ $numParams = sizeof($b);
+
+ $msg = new XML_RPC_Message($scalar_value);
+ for ($i = 0; $i < $numParams; $i++)
+ {
+ $msg->params[] = $params->me['array'][$i];
+ }
+
+ $result = $this->execute($msg);
+
+ if ($result->faultCode() != 0)
+ {
+ return $this->multicall_error($result);
+ }
+
+ return new XML_RPC_Values(array($result->value()), 'array');
+ }
+
+}
+// END XML_RPC_Server class
+?> \ No newline at end of file
diff --git a/system/libraries/index.html b/system/libraries/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/libraries/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/logs/index.html b/system/logs/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/logs/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/plugins/captcha_pi.php b/system/plugins/captcha_pi.php
new file mode 100644
index 000000000..54944b823
--- /dev/null
+++ b/system/plugins/captcha_pi.php
@@ -0,0 +1,346 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/*
+Instructions:
+
+Load the plugin using:
+
+ $this->load->plugin('captcha');
+
+Once loaded you can generate a captcha like this:
+
+ $vals = array(
+ 'word' => 'Random word',
+ 'img_path' => './captcha/',
+ 'img_url' => 'http://www.your-site.com/captcha/',
+ 'font_path' => './system/texb.ttf',
+ 'img_width' => '150',
+ 'img_height' => 30,
+ 'expiration' => 7200
+ );
+
+ $cap = create_captcha($vals);
+ echo $cap['image'];
+
+
+NOTES:
+
+ The captcha function requires the GD image library.
+
+ Only the img_path and img_url are required.
+
+ If a "word" is not supplied, the function will generate a random
+ ASCII string. You might put together your own word library that
+ you can draw randomly from.
+
+ If you do not specify a path to a TRUE TYPE font, the native ugly GD
+ font will be used.
+
+ The "captcha" folder must be writable (666, or 777)
+
+ The "expiration" (in seconds) signifies how long an image will
+ remain in the captcha folder before it will be deleted. The default
+ is two hours.
+
+RETURNED DATA
+
+The create_captcha() function returns an associative array with this data:
+
+ [array]
+ (
+ 'image' => IMAGE TAG
+ 'time' => TIMESTAMP (in microtime)
+ 'word' => CAPTCHA WORD
+ )
+
+The "image" is the actual image tag:
+<img src="http://your-site.com/captcha/12345.jpg" width="140" height="50" />
+
+The "time" is the micro timestamp used as the image name without the file
+extension. It will be a number like this: 1139612155.3422
+
+The "word" is the word that appears in the captcha image, which if not
+supplied to the function, will be a random string.
+
+
+ADDING A DATABASE
+
+In order for the captcha function to prevent someone from posting, you will need
+to add the information returned from create_captcha() function to your database.
+Then, when the data from the form is submitted by the user you will need to verify
+that the data exists in the database and has not expired.
+
+Here is a table prototype:
+
+ CREATE TABLE captcha (
+ captcha_id bigint(13) unsigned NOT NULL auto_increment,
+ captcha_time int(10) unsigned NOT NULL,
+ ip_address varchar(16) default '0' NOT NULL,
+ word varchar(20) NOT NULL,
+ PRIMARY KEY (captcha_id),
+ KEY (word)
+ )
+
+
+Here is an example of usage with a DB.
+
+On the page where the captcha will be shown you'll have something like this:
+
+ $this->load->plugin('captcha');
+ $vals = array(
+ 'img_path' => './captcha/',
+ 'img_url' => 'http://www.your-site.com/captcha/'
+ );
+
+ $cap = create_captcha($vals);
+
+ $data = array(
+ 'captcha_id' => '',
+ 'captcha_time' => $cap['time'],
+ 'ip_address' => $this->input->ip_address(),
+ 'word' => $cap['word']
+ );
+
+ $query = $this->db->insert_string('captcha', $data);
+ $this->db->query($query);
+
+ echo 'Submit the word you see below:';
+ echo $cap['image'];
+ echo '<input type="text" name="captcha" value="" />';
+
+
+Then, on the page that accepts the submission you'll have something like this:
+
+ // First, delete old captchas
+ $expiration = time()-7200; // Two hour limit
+ $DB->query("DELETE FROM captcha WHERE captcha_time < ".$expiration);
+
+ // Then see if a captcha exists:
+ $sql = "SELECT COUNT(*) AS count FROM captcha WHERE word = ? AND ip_address = ? AND date > ?";
+ $binds = array($_POST['captcha'], $this->input->ip_address(), $expiration);
+ $query = $this->db->query($sql, $binds);
+ $row = $query->row();
+
+ if ($row->count == 0)
+ {
+ echo "You must submit the word that appears in the image";
+ }
+
+*/
+
+
+
+/**
+|==========================================================
+| Create Captcha
+|==========================================================
+|
+*/
+function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = '')
+{
+ $defaults = array('word' => '', 'img_path' => '', 'img_url' => '', 'img_width' => '150', 'img_height' => '30', 'font_path' => '', 'expiration' => 7200);
+
+ foreach ($defaults as $key => $val)
+ {
+ if ( ! is_array($data))
+ {
+ if ( ! isset($$key) OR $$key == '')
+ {
+ $$key = $val;
+ }
+ }
+ else
+ {
+ $$key = ( ! isset($data[$key])) ? $val : $data[$key];
+ }
+ }
+
+ if ($img_path == '' OR $img_url == '')
+ {
+ return FALSE;
+ }
+
+ if ( ! @is_dir($img_path))
+ {
+ return FALSE;
+ }
+
+ if ( ! is_writable($img_path))
+ {
+ return FALSE;
+ }
+
+ if ( ! extension_loaded('gd'))
+ {
+ return FALSE;
+ }
+
+ // -----------------------------------
+ // Remove old images
+ // -----------------------------------
+
+ list($usec, $sec) = explode(" ", microtime());
+ $now = ((float)$usec + (float)$sec);
+
+ $current_dir = @opendir($img_path);
+
+ while($filename = @readdir($current_dir))
+ {
+ if ($filename != "." and $filename != ".." and $filename != "index.html")
+ {
+ $name = str_replace(".jpg", "", $filename);
+
+ if (($name + $expiration) < $now)
+ {
+ @unlink($img_path.$filename);
+ }
+ }
+ }
+
+ @closedir($current_dir);
+
+ // -----------------------------------
+ // Do we have a "word" yet?
+ // -----------------------------------
+
+ if ($word == '')
+ {
+ $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ $str = '';
+ for ($i = 0; $i < 8; $i++)
+ {
+ $str .= substr($pool, mt_rand(0, strlen($pool) -1), 1);
+ }
+
+ $word = $str;
+ }
+
+ // -----------------------------------
+ // Determine angle and position
+ // -----------------------------------
+
+ $length = strlen($word);
+ $angle = ($length >= 6) ? rand(-($length-6), ($length-6)) : 0;
+ $x_axis = rand(6, (360/$length)-16);
+ $y_axis = ($angle >= 0 ) ? rand($img_height, $img_width) : rand(6, $img_height);
+
+ // -----------------------------------
+ // Create image
+ // -----------------------------------
+
+ $im = ImageCreate($img_width, $img_height);
+
+ // -----------------------------------
+ // Assign colors
+ // -----------------------------------
+
+ $bg_color = ImageColorAllocate($im, 255, 255, 255);
+ $border_color = ImageColorAllocate($im, 153, 102, 102);
+ $text_color = ImageColorAllocate($im, 204, 153, 153);
+ $grid_color = imagecolorallocate($im, 255, 182, 182);
+ $shadow_color = imagecolorallocate($im, 255, 240, 240);
+
+ // -----------------------------------
+ // Create the rectangle
+ // -----------------------------------
+
+ ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $bg_color);
+
+ // -----------------------------------
+ // Create the spiral pattern
+ // -----------------------------------
+
+ $theta = 1;
+ $thetac = 7;
+ $radius = 16;
+ $circles = 20;
+ $points = 32;
+
+ for ($i = 0; $i < ($circles * $points) - 1; $i++)
+ {
+ $theta = $theta + $thetac;
+ $rad = $radius * ($i / $points );
+ $x = ($rad * cos($theta)) + $x_axis;
+ $y = ($rad * sin($theta)) + $y_axis;
+ $theta = $theta + $thetac;
+ $rad1 = $radius * (($i + 1) / $points);
+ $x1 = ($rad1 * cos($theta)) + $x_axis;
+ $y1 = ($rad1 * sin($theta )) + $y_axis;
+ imageline($im, $x, $y, $x1, $y1, $grid_color);
+ $theta = $theta - $thetac;
+ }
+
+ // -----------------------------------
+ // Write the text
+ // -----------------------------------
+
+ $use_font = ($font_path != '' AND file_exists($font_path) AND function_exists('imagettftext')) ? TRUE : FALSE;
+
+ if ($use_font == FALSE)
+ {
+ $font_size = 5;
+ $x = rand(0, $img_width/($length/3));
+ $y = 0;
+ }
+ else
+ {
+ $font_size = 16;
+ $x = rand(0, $img_width/($length/1.5));
+ $y = $font_size+2;
+ }
+
+ for ($i = 0; $i < strlen($word); $i++)
+ {
+ if ($use_font == FALSE)
+ {
+ $y = rand(0 , $img_height/2);
+ imagestring($im, $font_size, $x, $y, substr($word, $i, 1), $text_color);
+ $x += ($font_size*2);
+ }
+ else
+ {
+ $y = rand($img_height/2, $img_height-3);
+ imagettftext($im, $font_size, $angle, $x, $y, $text_color, $font_path, substr($word, $i, 1));
+ $x += $font_size;
+ }
+ }
+
+
+ // -----------------------------------
+ // Create the border
+ // -----------------------------------
+
+ imagerectangle($im, 0, 0, $img_width-1, $img_height-1, $border_color);
+
+ // -----------------------------------
+ // Generate the image
+ // -----------------------------------
+
+ $img_name = $now.'.jpg';
+
+ ImageJPEG($im, $img_path.$img_name);
+
+ $img = "<img src=\"$img_url$img_name\" width=\"$img_width\" height=\"$img_height\" style=\"border:0;\" alt=\" \" />";
+
+ ImageDestroy($im);
+
+ return array('word' => $word, 'time' => $now, 'image' => $img);
+}
+
+?> \ No newline at end of file
diff --git a/system/plugins/index.html b/system/plugins/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/plugins/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/plugins/js_calendar_pi.php b/system/plugins/js_calendar_pi.php
new file mode 100644
index 000000000..16c3f4136
--- /dev/null
+++ b/system/plugins/js_calendar_pi.php
@@ -0,0 +1,604 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/*
+Instructions:
+
+Load the plugin using:
+
+ $this->load->plugin('js_calendar');
+
+Once loaded you'll add the calendar script to the <head> of your page like this:
+
+<?php echo js_calendar_script('my_form'); ?>
+
+The above function will be passed the name of your form.
+
+Then to show the actual calendar you'll do this:
+
+<?php echo js_calendar_write('entry_date', time(), true); ?>
+<form name="my_form">
+<input type="text" name="entry_date" value="" onblur="update_calendar(this.name, this.value);" />
+<p><a href="javascript:void(0);" onClick="set_to_time('entry_date', '<?php echo time(); ?>')" >Today</a></p>
+</form>
+
+
+Note: The first parameter is the name of the field containing your date, the second parameter contains the "now" time,
+and the third tells the calendar whether to highlight the current day or not.
+
+Lastly, you'll need some CSS for your calendar:
+
+.calendar {
+ border: 1px #6975A3 solid;
+ background-color: transparent;
+}
+.calheading {
+ background-color: #7C8BC0;
+ color: #fff;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 11px;
+ font-weight: bold;
+ text-align: center;
+}
+.calnavleft {
+ background-color: #7C8BC0;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 10px;
+ font-weight: bold;
+ color: #fff;
+ padding: 4px;
+ cursor: pointer;
+}
+.calnavright {
+ background-color: #7C8BC0;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 10px;
+ font-weight: bold;
+ color: #fff;
+ text-align: right;
+ padding: 4px;
+ cursor: pointer;
+}
+.caldayheading {
+ background-color: #000;
+ color: #fff;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 10px;
+ text-align: center;
+ padding: 6px 2px 6px 2px;
+}
+.caldaycells{
+ color: #000;
+ background-color: #D1D7E6;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 11px;
+ text-align: center;
+ padding: 4px;
+ border: 1px #E0E5F1 solid;
+ cursor: pointer;
+}
+.caldaycellhover{
+ color: #fff;
+ background-color: #B3BCD4;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 11px;
+ text-align: center;
+ padding: 4px;
+ border: 1px #B3BCD4 solid;
+ cursor: pointer;
+}
+.caldayselected{
+ background-color: #737FAC;
+ color: #fff;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 11px;
+ font-weight: bold;
+ text-align: center;
+ border: 1px #566188 solid;
+ padding: 3px;
+ cursor: pointer;
+}
+.calblanktop {
+ background-color: #fff;
+ padding: 4px;
+}
+.calblankbot {
+ background-color: #fff;
+ padding: 4px;
+}
+
+
+*/
+
+function js_calendar_script($form_name = 'entryform')
+{
+
+ob_start();
+?>
+<script type="text/javascript">
+<!--
+var form_name = "<?php echo $form_name; ?>";
+var format = 'us'; // eu or us
+var days = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
+var months = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
+var last_click = new Array();
+var current_month = '';
+var current_year = '';
+var last_date = '';
+
+function calendar(id, d, highlight, adjusted)
+{
+ if (adjusted == undefined)
+ {
+ var d = new Date(d * 1000);
+ }
+
+ this.id = id;
+ this.highlight = highlight;
+ this.date_obj = d;
+ this.write = build_calendar;
+ this.total_days = total_days;
+ this.month = d.getMonth();
+ this.date = d.getDate();
+ this.day = d.getDay();
+ this.year = d.getFullYear();
+ this.hours = d.getHours();
+ this.minutes = d.getMinutes();
+ this.seconds = d.getSeconds();
+ this.date_str = date_str;
+
+ if (highlight == false)
+ {
+ this.selected_date = '';
+ }
+ else
+ {
+ this.selected_date = this.year + '' + this.month + '' + this.date;
+ }
+
+ // Set the "selected date"
+ d.setDate(1);
+ this.firstDay = d.getDay();
+
+ //then reset the date object to the correct date
+ d.setDate(this.date);
+}
+
+// Build the body of the calendar
+function build_calendar()
+{
+ var str = '';
+
+ // Calendar Heading
+
+ str += '<div id="cal' + this.id + '">';
+ str += '<table class="calendar" cellspacing="0" cellpadding="0" border="0" >';
+ str += '<tr>';
+ str += '<td class="calnavleft" onClick="change_month(-1, \'' + this.id + '\')">&lt;&lt;<\/td>';
+ str += '<td colspan="5" class="calheading">' + months[this.month] + ' ' + this.year + '<\/td>';
+ str += '<td class="calnavright" onClick="change_month(1, \'' + this.id + '\')">&gt;&gt;<\/td>';
+ str += '<\/tr>';
+
+ // Day Names
+
+ str += '<tr>';
+
+ for (i = 0; i < 7; i++)
+ {
+ str += '<td class="caldayheading">' + days[i] + '<\/td>';
+ }
+
+ str += '<\/tr>';
+
+ // Day Cells
+
+ str += '<tr>';
+
+ selDate = (last_date != '') ? last_date : this.date;
+
+ for (j = 0; j < 42; j++)
+ {
+ var displayNum = (j - this.firstDay + 1);
+
+ if (j < this.firstDay) // leading empty cells
+ {
+ str += '<td class="calblanktop">&nbsp;<\/td>';
+ }
+ else if (displayNum == selDate && this.highlight == true) // Selected date
+ {
+ str += '<td id="' + this.id +'selected" class="caldayselected" onClick="set_date(this,\'' + this.id + '\')">' + displayNum + '<\/td>';
+ }
+ else if (displayNum > this.total_days())
+ {
+ str += '<td class="calblankbot">&nbsp;<\/td>'; // trailing empty cells
+ }
+ else // Unselected days
+ {
+ str += '<td id="" class="caldaycells" onClick="set_date(this,\'' + this.id + '\'); return false;" onMouseOver="javascript:cell_highlight(this,\'' + displayNum + '\',\'' + this.id + '\');" onMouseOut="javascript:cell_reset(this,\'' + displayNum + '\',\'' + this.id + '\');" >' + displayNum + '<\/td>';
+ }
+
+ if (j % 7 == 6)
+ {
+ str += '<\/tr><tr>';
+ }
+ }
+
+ str += '<\/tr>';
+ str += '<\/table>';
+ str += '<\/div>';
+
+ return str;
+}
+
+// Total number of days in a month
+function total_days()
+{
+ switch(this.month)
+ {
+ case 1: // Check for leap year
+ if (( this.date_obj.getFullYear() % 4 == 0
+ && this.date_obj.getFullYear() % 100 != 0)
+ || this.date_obj.getFullYear() % 400 == 0)
+ return 29;
+ else
+ return 28;
+ case 3:
+ return 30;
+ case 5:
+ return 30;
+ case 8:
+ return 30;
+ case 10:
+ return 30
+ default:
+ return 31;
+ }
+}
+
+// Highlight Cell on Mouseover
+function cell_highlight(td, num, cal)
+{
+ cal = eval(cal);
+
+ if (last_click[cal.id] != num)
+ {
+ td.className = "caldaycellhover";
+ }
+}
+
+// Reset Cell on MouseOut
+function cell_reset(td, num, cal)
+{
+ cal = eval(cal);
+
+ if (last_click[cal.id] == num)
+ {
+ td.className = "caldayselected";
+ }
+ else
+ {
+ td.className = "caldaycells";
+ }
+}
+
+// Clear Field
+function clear_field(id)
+{
+ eval("document." + form_name + "." + id + ".value = ''");
+
+ document.getElementById(id + "selected").className = "caldaycells";
+ document.getElementById(id + "selected").id = "";
+
+ cal = eval(id);
+ cal.selected_date = '';
+}
+
+
+// Set date to specified time
+function set_to_time(id, raw)
+{
+ if (document.getElementById(id + "selected"))
+ {
+ document.getElementById(id + "selected").className = "caldaycells";
+ document.getElementById(id + "selected").id = "";
+ }
+
+ document.getElementById('cal' + id).innerHTML = '<div id="tempcal'+id+'">&nbsp;<'+'/div>';
+
+ var nowDate = new Date();
+ nowDate.setTime = raw * 1000;
+
+ current_month = nowDate.getMonth();
+ current_year = nowDate.getFullYear();
+ current_date = nowDate.getDate();
+
+ oldcal = eval(id);
+ oldcal.selected_date = current_year + '' + current_month + '' + current_date;
+
+ cal = new calendar(id, nowDate, true, true);
+ cal.selected_date = current_year + '' + current_month + '' + current_date;
+
+ last_date = cal.date;
+
+ document.getElementById('tempcal'+id).innerHTML = cal.write();
+
+ insert_date(cal);
+}
+
+// Set date to what is in the field
+var lastDates = new Array();
+
+function update_calendar(id, dateValue)
+{
+ if (lastDates[id] == dateValue) return;
+
+ lastDates[id] = dateValue;
+
+ var fieldString = dateValue.replace(/\s+/g, ' ');
+
+ while (fieldString.substring(0,1) == ' ')
+ {
+ fieldString = fieldString.substring(1, fieldString.length);
+ }
+
+ var dateString = fieldString.split(' ');
+ var dateParts = dateString[0].split('-')
+
+ if (dateParts.length < 3) return;
+ var newYear = dateParts[0];
+ var newMonth = dateParts[1];
+ var newDay = dateParts[2];
+
+ if (isNaN(newDay) || newDay < 1 || (newDay.length != 1 && newDay.length != 2)) return;
+ if (isNaN(newYear) || newYear < 1 || newYear.length != 4) return;
+ if (isNaN(newMonth) || newMonth < 1 || (newMonth.length != 1 && newMonth.length != 2)) return;
+
+ if (newMonth > 12) newMonth = 12;
+
+ if (newDay > 28)
+ {
+ switch(newMonth - 1)
+ {
+ case 1: // Check for leap year
+ if ((newYear % 4 == 0 && newYear % 100 != 0) || newYear % 400 == 0)
+ {
+ if (newDay > 29) newDay = 29;
+ }
+ else
+ {
+ if (newDay > 28) newDay = 28;
+ }
+ case 3:
+ if (newDay > 30) newDay = 30;
+ case 5:
+ if (newDay > 30) newDay = 30;
+ case 8:
+ if (newDay > 30) newDay = 30;
+ case 10:
+ if (newDay > 30) newDay = 30;
+ default:
+ if (newDay > 31) newDay = 31;
+ }
+ }
+
+ if (document.getElementById(id + "selected"))
+ {
+ document.getElementById(id + "selected").className = "caldaycells";
+ document.getElementById(id + "selected").id = "";
+ }
+
+ document.getElementById('cal' + id).innerHTML = '<div id="tempcal'+id+'">&nbsp;<'+'/div>';
+
+ var nowDate = new Date();
+ nowDate.setDate(newDay);
+ nowDate.setMonth(newMonth - 1);
+ nowDate.setYear(newYear);
+ nowDate.setHours(12);
+
+ current_month = nowDate.getMonth();
+ current_year = nowDate.getFullYear();
+
+ cal = new calendar(id, nowDate, true, true);
+ document.getElementById('tempcal'+id).innerHTML = cal.write();
+}
+
+// Set the date
+function set_date(td, cal)
+{
+ cal = eval(cal);
+
+ // If the user is clicking a cell that is already
+ // selected we'll de-select it and clear the form field
+
+ if (last_click[cal.id] == td.firstChild.nodeValue)
+ {
+ td.className = "caldaycells";
+ last_click[cal.id] = '';
+ remove_date(cal);
+ cal.selected_date = '';
+ return;
+ }
+
+ // Onward!
+ if (document.getElementById(cal.id + "selected"))
+ {
+ document.getElementById(cal.id + "selected").className = "caldaycells";
+ document.getElementById(cal.id + "selected").id = "";
+ }
+
+ td.className = "caldayselected";
+ td.id = cal.id + "selected";
+
+ cal.selected_date = cal.date_obj.getFullYear() + '' + cal.date_obj.getMonth() + '' + cal.date;
+ cal.date_obj.setDate(td.firstChild.nodeValue);
+ cal = new calendar(cal.id, cal.date_obj, true, true);
+ cal.selected_date = cal.date_obj.getFullYear() + '' + cal.date_obj.getMonth() + '' + cal.date;
+
+ last_date = cal.date;
+
+ //cal.date
+ last_click[cal.id] = cal.date;
+
+ // Insert the date into the form
+ insert_date(cal);
+}
+
+// Insert the date into the form field
+function insert_date(cal)
+{
+ cal = eval(cal);
+ fval = eval("document." + form_name + "." + cal.id);
+
+ if (fval.value == '')
+ {
+ fval.value = cal.date_str('y');
+ }
+ else
+ {
+ time = fval.value.substring(10);
+ new_date = cal.date_str('n') + time;
+ fval.value = new_date;
+ }
+}
+
+// Remove the date from the form field
+function remove_date(cal)
+{
+ cal = eval(cal);
+ fval = eval("document." + form_name + "." + cal.id);
+ fval.value = '';
+}
+
+// Change to a new month
+function change_month(mo, cal)
+{
+ cal = eval(cal);
+
+ if (current_month != '')
+ {
+ cal.date_obj.setMonth(current_month);
+ cal.date_obj.setYear(current_year);
+
+ current_month = '';
+ current_year = '';
+ }
+
+ var newMonth = cal.date_obj.getMonth() + mo;
+ var newDate = cal.date_obj.getDate();
+
+ if (newMonth == 12)
+ {
+ cal.date_obj.setYear(cal.date_obj.getFullYear() + 1)
+ newMonth = 0;
+ }
+ else if (newMonth == -1)
+ {
+ cal.date_obj.setYear(cal.date_obj.getFullYear() - 1)
+ newMonth = 11;
+ }
+
+ if (newDate > 28)
+ {
+ var newYear = cal.date_obj.getFullYear();
+
+ switch(newMonth)
+ {
+ case 1: // Check for leap year
+ if ((newYear % 4 == 0 && newYear % 100 != 0) || newYear % 400 == 0)
+ {
+ if (newDate > 29) newDate = 29;
+ }
+ else
+ {
+ if (newDate > 28) newDate = 28;
+ }
+ case 3:
+ if (newDate > 30) newDate = 30;
+ case 5:
+ if (newDate > 30) newDate = 30;
+ case 8:
+ if (newDate > 30) newDate = 30;
+ case 10:
+ if (newDate > 30) newDate = 30;
+ default:
+ if (newDate > 31) newDate = 31;
+ }
+ }
+
+ cal.date_obj.setDate(newDate);
+ cal.date_obj.setMonth(newMonth);
+ new_mdy = cal.date_obj.getFullYear() + '' + cal.date_obj.getMonth() + '' + cal.date;
+
+ highlight = (cal.selected_date == new_mdy) ? true : false;
+ cal = new calendar(cal.id, cal.date_obj, highlight, true);
+ document.getElementById('cal' + cal.id).innerHTML = cal.write();
+}
+
+// Finalize the date string
+function date_str(time)
+{
+ var month = this.month + 1;
+ if (month < 10)
+ month = '0' + month;
+
+ var day = (this.date < 10) ? '0' + this.date : this.date;
+ var minutes = (this.minutes < 10) ? '0' + this.minutes : this.minutes;
+
+ if (format == 'us')
+ {
+ var hours = (this.hours > 12) ? this.hours - 12 : this.hours;
+ var ampm = (this.hours > 11) ? 'PM' : 'AM'
+ }
+ else
+ {
+ var hours = this.hours;
+ var ampm = '';
+ }
+
+ if (time == 'y')
+ {
+ return this.year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ' ' + ampm;
+ }
+ else
+ {
+ return this.year + '-' + month + '-' + day;
+ }
+}
+
+//-->
+</script>
+<?php
+
+$r = ob_get_contents();
+ob_end_clean();
+return $r;
+}
+
+
+function js_calendar_write($field_id, $time = '', $highlight = TRUE)
+{
+ if ($time == '')
+ $time = time();
+
+ return
+ '<script type="text/javascript">
+ var '.$field_id.' = new calendar("'.$field_id.'", '.$time.', '.(($highlight == TRUE) ? 'true' : 'false').');
+ document.write('.$field_id.'.write());
+ </script>';
+}
+
+?> \ No newline at end of file
diff --git a/system/scaffolding/Scaffolding.php b/system/scaffolding/Scaffolding.php
new file mode 100644
index 000000000..4b6ebeed5
--- /dev/null
+++ b/system/scaffolding/Scaffolding.php
@@ -0,0 +1,285 @@
+<?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
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Scaffolding Class
+ *
+ * Provides the Scaffolding framework
+ *
+ * @package CodeIgniter
+ * @subpackage Scaffolding
+ * @author Rick Ellis
+ * @link http://www.codeigniter.com/user_guide/general/scaffolding.html
+ */
+class Scaffolding {
+
+ var $current_table;
+ var $base_url = '';
+ var $lang = array();
+
+ function Scaffolding($db_table)
+ {
+ $obj =& get_instance();
+ foreach ($obj->ci_is_loaded as $val)
+ {
+ $this->$val =& $obj->$val;
+ }
+
+ /**
+ * Set the current table name
+ * This is done when initializing scaffolding:
+ * $this->_ci_init_scaffolding('table_name')
+ *
+ */
+ $this->current_table = $db_table;
+
+ /**
+ * Set the path to the "view" files
+ * We'll manually override the "view" path so that
+ * the load->view function knows where to look.
+ */
+ $this->load->_ci_set_view_path(BASEPATH.'scaffolding/views/');
+
+ // Set the base URL
+ $this->base_url = $this->config->site_url().'/'.$this->uri->segment(1).$this->uri->slash_segment(2, 'both');
+ $this->base_uri = $this->uri->segment(1).$this->uri->slash_segment(2, 'leading');
+
+ // Set a few globals
+ $data = array(
+ 'image_url' => $this->config->system_url().'scaffolding/images/',
+ 'base_uri' => $this->base_uri,
+ 'base_url' => $this->base_url,
+ 'title' => $this->current_table
+ );
+
+ $this->load->vars($data);
+
+ // Load the language file and create variables
+ $this->lang = $this->load->language('scaffolding', '', TRUE);
+ $this->load->vars($this->lang);
+
+ // Load the helper files we plan to use
+ $this->load->helper(array('url', 'form'));
+
+
+ log_message('debug', 'Scaffolding Class Initialized');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Add" Page
+ *
+ * Shows a form representing the currently selected DB
+ * so that data can be inserted
+ *
+ * @access public
+ * @return string the HTML "add" page
+ */
+ function add()
+ {
+ $data = array(
+ 'title' => ( ! isset($this->lang['scaff_add'])) ? 'Add Data' : $this->lang['scaff_add'],
+ 'fields' => $this->db->field_data($this->current_table),
+ 'action' => $this->base_uri.'/insert'
+ );
+
+ $this->load->view('add', $data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert the data
+ *
+ * @access public
+ * @return void redirects to the view page
+ */
+ function insert()
+ {
+ if ($this->db->insert($this->current_table, $_POST) === FALSE)
+ {
+ $this->add();
+ }
+ else
+ {
+ redirect($this->base_uri.'/view/');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "View" Page
+ *
+ * Shows a table containing the data in the currently
+ * selected DB
+ *
+ * @access public
+ * @return string the HTML "view" page
+ */
+ function view()
+ {
+ // Fetch the total number of DB rows
+ $total_rows = $this->db->count_all($this->current_table);
+
+ if ($total_rows < 1)
+ {
+ return $this->load->view('no_data');
+ }
+
+ // Set the query limit/offset
+ $per_page = 20;
+ $offset = $this->uri->segment(4, 0);
+
+ // Run the query
+ $query = $this->db->get($this->current_table, $per_page, $offset);
+
+ // Now let's get the field names
+ $fields = $this->db->field_names($this->current_table);
+
+ // We assume that the column in the first position is the primary field.
+ $primary = current($fields);
+
+ // Pagination!
+ $this->pagination->initialize(
+ array(
+ 'base_url' => $this->base_url.'/view',
+ 'total_rows' => $total_rows,
+ 'per_page' => $per_page,
+ 'uri_segment' => 4,
+ 'full_tag_open' => '<p>',
+ 'full_tag_close' => '</p>'
+ )
+ );
+
+ $data = array(
+ 'title' => ( ! isset($this->lang['scaff_view'])) ? 'View Data' : $this->lang['scaff_view'],
+ 'query' => $query,
+ 'fields' => $fields,
+ 'primary' => $primary,
+ 'paginate' => $this->pagination->create_links()
+ );
+
+ $this->load->view('view', $data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Edit" Page
+ *
+ * Shows a form representing the currently selected DB
+ * so that data can be edited
+ *
+ * @access public
+ * @return string the HTML "edit" page
+ */
+ function edit()
+ {
+ if (FALSE === ($id = $this->uri->segment(4)))
+ {
+ return $this->view();
+ }
+
+ // Fetch the primary field name
+ $primary = $this->db->primary($this->current_table);
+
+ // Run the query
+ $query = $this->db->getwhere($this->current_table, array($primary => $id));
+
+ $data = array(
+ 'title' => ( ! isset($this->lang['scaff_edit'])) ? 'Edit Data' : $this->lang['scaff_edit'],
+ 'fields' => $query->field_data(),
+ 'query' => $query->row(),
+ 'action' => $this->base_uri.'/update/'.$this->uri->segment(4)
+ );
+
+ $this->load->view('edit', $data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update
+ *
+ * @access public
+ * @return void redirects to the view page
+ */
+ function update()
+ {
+ // Fetch the primary key
+ $primary = $this->db->primary($this->current_table);
+
+ // Now do the query
+ $this->db->update($this->current_table, $_POST, array($primary => $this->uri->segment(4)));
+
+ redirect($this->base_uri.'/view/');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete Confirmation
+ *
+ * @access public
+ * @return string the HTML "delete confirm" page
+ */
+ function delete()
+ {
+ if ( ! isset($this->lang['scaff_del_confirm']))
+ {
+ $message = 'Are you sure you want to delete the following row: '.$this->uri->segment(4);
+ }
+ else
+ {
+ $message = $this->lang['scaff_del_confirm'].' '.$this->uri->segment(4);
+ }
+
+ $data = array(
+ 'title' => ( ! isset($this->lang['scaff_delete'])) ? 'Delete Data' : $this->lang['scaff_delete'],
+ 'message' => $message,
+ 'no' => anchor(array($this->base_uri, 'view'), ( ! isset($this->lang['scaff_no'])) ? 'No' : $this->lang['scaff_no']),
+ 'yes' => anchor(array($this->base_uri, 'do_delete', $this->uri->segment(4)), ( ! isset($this->lang['scaff_yes'])) ? 'Yes' : $this->lang['scaff_yes'])
+ );
+
+ $this->load->view('delete', $data);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete
+ *
+ * @access public
+ * @return void redirects to the view page
+ */
+ function do_delete()
+ {
+ // Fetch the primary key
+ $primary = $this->db->primary($this->current_table);
+
+ // Now do the query
+ $this->db->where($primary, $this->uri->segment(4));
+ $this->db->delete($this->current_table);
+
+ header("Refresh:0;url=".site_url(array($this->base_uri, 'view')));
+ exit;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/system/scaffolding/images/background.jpg b/system/scaffolding/images/background.jpg
new file mode 100644
index 000000000..9d5bdcea1
--- /dev/null
+++ b/system/scaffolding/images/background.jpg
Binary files differ
diff --git a/system/scaffolding/images/index.html b/system/scaffolding/images/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/scaffolding/images/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/scaffolding/images/logo.jpg b/system/scaffolding/images/logo.jpg
new file mode 100644
index 000000000..d6cc9a76d
--- /dev/null
+++ b/system/scaffolding/images/logo.jpg
Binary files differ
diff --git a/system/scaffolding/index.html b/system/scaffolding/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/scaffolding/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/scaffolding/views/add.php b/system/scaffolding/views/add.php
new file mode 100644
index 000000000..a65e3d745
--- /dev/null
+++ b/system/scaffolding/views/add.php
@@ -0,0 +1,30 @@
+<?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'); ?>
diff --git a/system/scaffolding/views/delete.php b/system/scaffolding/views/delete.php
new file mode 100644
index 000000000..75a5c21b8
--- /dev/null
+++ b/system/scaffolding/views/delete.php
@@ -0,0 +1,7 @@
+<?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'); ?>
diff --git a/system/scaffolding/views/edit.php b/system/scaffolding/views/edit.php
new file mode 100644
index 000000000..a7d65c619
--- /dev/null
+++ b/system/scaffolding/views/edit.php
@@ -0,0 +1,31 @@
+<?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'); ?> \ No newline at end of file
diff --git a/system/scaffolding/views/footer.php b/system/scaffolding/views/footer.php
new file mode 100644
index 000000000..36b29d1cd
--- /dev/null
+++ b/system/scaffolding/views/footer.php
@@ -0,0 +1,10 @@
+
+</div>
+
+<div id="footer">
+<p><a href="http://www.codeigniter.com/">Code Igniter</a>, by <a href="http://www.pmachine.com">pMachine</a> - Version <?php echo APPVER ?></p>
+<p>Page rendered in {elapsed_time}</p>
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/scaffolding/views/header.php b/system/scaffolding/views/header.php
new file mode 100644
index 000000000..7ab60fd81
--- /dev/null
+++ b/system/scaffolding/views/header.php
@@ -0,0 +1,31 @@
+<!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>
+
+<script src="../../nav.js" type="text/javascript"></script>
+
+<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/index.html b/system/scaffolding/views/index.html
new file mode 100644
index 000000000..5a1f5d6ae
--- /dev/null
+++ b/system/scaffolding/views/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/scaffolding/views/no_data.php b/system/scaffolding/views/no_data.php
new file mode 100644
index 000000000..dca477e2d
--- /dev/null
+++ b/system/scaffolding/views/no_data.php
@@ -0,0 +1,6 @@
+<?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'); ?> \ No newline at end of file
diff --git a/system/scaffolding/views/stylesheet.css b/system/scaffolding/views/stylesheet.css
new file mode 100644
index 000000000..55c8d9e59
--- /dev/null
+++ b/system/scaffolding/views/stylesheet.css
@@ -0,0 +1,143 @@
+body {
+ margin: 0;
+ padding: 0;
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 11px;
+ color: #4F5155;
+ background: #fff url(<?php echo $image_url; ?>background.jpg) repeat-x left top;
+}
+
+a {
+ color: #8B0D00;
+ background-color: transparent;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+a:visited {
+ color: #8B0D00;
+ background-color: transparent;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #000;
+ text-decoration: none;
+ background-color: transparent;
+}
+
+
+#header {
+ margin: 0;
+ padding: 0;
+}
+
+#header_left {
+ background-color: transparent;
+ float: left;
+ padding: 21px 0 0 32px;
+ margin: 0
+}
+
+#header_right {
+ background-color: transparent;
+ float: right;
+ text-align: right;
+ padding: 35px 50px 20px 0;
+ margin: 0
+}
+
+#footer {
+ margin: 20px 0 15px 0;
+ padding: 0;
+}
+
+#footer p {
+ font-size: 10px;
+ color: #999;
+ text-align: center;
+}
+
+#outer {
+ margin: 30px 40px 0 40px;
+}
+
+img {
+ padding:0;
+ border: 0;
+ margin: 0;
+}
+
+.nopad {
+ padding:0;
+ border: 0;
+ margin: 0;
+}
+
+table {
+ background-color: #efefef;
+}
+
+th {
+ background-color: #eee;
+ font-weight: bold;
+ padding: 6px;
+ text-align: left;
+}
+
+td {
+ background-color: #fff;
+ padding: 6px;
+}
+
+
+form {
+ margin: 0;
+ padding: 0;
+}
+
+.input {
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 11px;
+ width: 600px;
+ color: #333;
+ border: 1px solid #B3B4BD;
+ font-size: 11px;
+ height: 2em;
+ padding: 0;
+ margin: 0;
+}
+
+.textarea {
+ font-family: Lucida Grande, Verdana, Geneva, Sans-serif;
+ font-size: 12px;
+ width: 600px;
+ color: #333;
+ border: 1px solid #B3B4BD;
+ padding: 0;
+ margin: 0;
+}
+
+.select {
+ background-color: #fff;
+ font-size: 11px;
+ font-weight: normal;
+ color: #333;
+ padding: 0;
+ margin: 0 0 3px 0;
+}
+
+.checkbox {
+ background-color: transparent;
+ padding: 0;
+ border: 0;
+}
+
+.submit {
+ background-color: #8B0D00;
+ color: transparent;
+ font-weight: normal;
+ border: 1px solid #000;
+ margin: 6px 0 0 0;
+ padding: 1px 5px 1px 5px;
+}
diff --git a/system/scaffolding/views/view.php b/system/scaffolding/views/view.php
new file mode 100644
index 000000000..fd20a174d
--- /dev/null
+++ b/system/scaffolding/views/view.php
@@ -0,0 +1,25 @@
+<?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><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'); ?> \ No newline at end of file