diff --git a/.gitattributes b/.gitattributes index a4296d591b8..eba1110b579 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,25 +1,2 @@ -# This file tells which files and directories should be ignored and -# NOT downloaded when using composer to pull down a project with -# the --prefer-dist option selected. Used to remove development -# specific files so user has a clean download. - -# git files -.gitattributes export-ignore -# .gitignore - -# helper config files -.travis.yml export-ignore -phpdoc.dist.xml export-ignore - -# Misc other files -readme.rst - -# They don't want all of our tests... -tests/codeigniter/ export-ignore -tests/travis/ export-ignore - -# User Guide Source Files -user_guide_src - -# User Guide Compiled Files -user_guide export-ignore +# Auto detect text files and perform LF normalization +* text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore index 269044ea9ea..496ee2ca6a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1 @@ -.DS_Store - -application/cache/* -!application/cache/index.html - -application/logs/* -!application/logs/index.html - -!application/*/.htaccess - -composer.lock - -user_guide_src/build/* -user_guide_src/cilexer/build/* -user_guide_src/cilexer/dist/* -user_guide_src/cilexer/pycilexer.egg-info/* -/vendor/ - -# IDE Files -#------------------------- -/nbproject/ -.idea/* - -## Sublime Text cache files -*.tmlanguage.cache -*.tmPreferences.cache -*.stTheme.cache -*.sublime-workspace -*.sublime-project -/tests/tests/ -/tests/results/ +.DS_Store \ No newline at end of file diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000000..59bcbe22f89 --- /dev/null +++ b/.htaccess @@ -0,0 +1,6 @@ + +RewriteEngine On +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^(.*)$ index.php/$1 [L] + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8525d5f6cef..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,63 +0,0 @@ -language: php -dist: trusty - -php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4snapshot - - nightly - - hhvm-3.30 - -env: - - DB=mysql - - DB=mysqli - - DB=pgsql - - DB=sqlite - - DB=pdo/mysql - - DB=pdo/pgsql - - DB=pdo/sqlite - -sudo: false - -before_script: - - sh -c "composer install --dev --no-progress" - - sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS ci_test;' -U postgres; fi" - - sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'create database ci_test;' -U postgres; fi" - - sh -c "if [ '$DB' = 'mysql' ] || [ '$DB' = 'mysqli' ] || [ '$DB' = 'pdo/mysql' ]; then mysql -e 'create database IF NOT EXISTS ci_test;'; fi" - -script: php -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --coverage-text --configuration tests/travis/$DB.phpunit.xml - -matrix: - allow_failures: - - php: 7.4snapshot - - php: nightly - - php: hhvm-3.30 - exclude: - - php: hhvm-3.30 - env: DB=pgsql - - php: hhvm-3.30 - env: DB=pdo/pgsql - - php: 7.0 - env: DB=mysql - - php: 7.1 - env: DB=mysql - - php: 7.2 - env: DB=mysql - - php: 7.3 - env: DB=mysql - - php: 7.4snapshot - env: DB=mysql - - php: nightly - env: DB=mysql - -branches: - only: - - develop - - 3.0-stable - - 3.1-stable - - /^feature\/.+$/ diff --git a/README.md b/README.md new file mode 100644 index 00000000000..01d6d13dce8 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# vietgram + +On this repository I'll clone Instagram front end and back end \ No newline at end of file diff --git a/application/cache/index.html b/application/cache/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/cache/index.html +++ b/application/cache/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/config/autoload.php b/application/config/autoload.php index 7cdc9013c11..6a67fddc3d2 100644 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -58,7 +58,7 @@ | | $autoload['libraries'] = array('user_agent' => 'ua'); */ -$autoload['libraries'] = array(); +$autoload['libraries'] = array('upload','session','form_validation','database'); /* | ------------------------------------------------------------------- @@ -89,7 +89,7 @@ | | $autoload['helper'] = array('url', 'file'); */ -$autoload['helper'] = array(); +$autoload['helper'] = array('url'); /* | ------------------------------------------------------------------- diff --git a/application/config/config.php b/application/config/config.php index 782b19c74b6..f498f4c1ff0 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -23,7 +23,7 @@ | a PHP script and you can easily do that on your own. | */ -$config['base_url'] = ''; +$config['base_url'] = 'http://localhost/CI/'; /* |-------------------------------------------------------------------------- @@ -35,7 +35,7 @@ | variable so that it is blank. | */ -$config['index_page'] = 'index.php'; +$config['index_page'] = ''; /* |-------------------------------------------------------------------------- @@ -63,8 +63,6 @@ | For more information please see the user guide: | | https://codeigniter.com/user_guide/general/urls.html -| -| Note: This option is ignored for CLI requests. */ $config['url_suffix'] = ''; @@ -88,7 +86,7 @@ | This determines which character set is used by default in various methods | that require a character set to be provided. | -| See https://secure.php.net/htmlspecialchars for a list of supported charsets. +| See http://php.net/htmlspecialchars for a list of supported charsets. | */ $config['charset'] = 'UTF-8'; @@ -133,7 +131,7 @@ | | $config['composer_autoload'] = '/path/to/vendor/autoload.php'; | -| For more information about Composer, please visit https://getcomposer.org/ +| For more information about Composer, please visit http://getcomposer.org/ | | Note: This will NOT disable or override the CodeIgniter-specific | autoloading (application/config/autoload.php) @@ -159,8 +157,6 @@ | | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! | -| Note: This option is ignored for CLI requests. -| */ $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; @@ -191,6 +187,20 @@ $config['function_trigger'] = 'm'; $config['directory_trigger'] = 'd'; +/* +|-------------------------------------------------------------------------- +| Allow $_GET array +|-------------------------------------------------------------------------- +| +| By default CodeIgniter enables access to the $_GET array. If for some +| reason you would like to disable it, set 'allow_get_array' to FALSE. +| +| WARNING: This feature is DEPRECATED and currently available only +| for backwards compatibility purposes! +| +*/ +$config['allow_get_array'] = TRUE; + /* |-------------------------------------------------------------------------- | Error Logging Threshold @@ -221,7 +231,7 @@ |-------------------------------------------------------------------------- | | Leave this BLANK unless you would like to set something other than the default -| application/logs/ directory. Use a full server path. +| application/logs/ directory. Use a full server path with trailing slash. | */ $config['log_path'] = ''; @@ -269,7 +279,7 @@ |-------------------------------------------------------------------------- | | Leave this BLANK unless you would like to set something other than the default -| application/views/errors/ directory. Use a full server path. +| application/views/errors/ directory. Use a full server path with trailing slash. | */ $config['error_views_path'] = ''; @@ -280,7 +290,7 @@ |-------------------------------------------------------------------------- | | Leave this BLANK unless you would like to set something other than the default -| application/cache/ directory. Use a full server path. +| application/cache/ directory. Use a full server path with trailing slash. | */ $config['cache_path'] = ''; @@ -396,6 +406,34 @@ $config['cookie_secure'] = FALSE; $config['cookie_httponly'] = FALSE; +/* +|-------------------------------------------------------------------------- +| Standardize newlines +|-------------------------------------------------------------------------- +| +| Determines whether to standardize newline characters in input data, +| meaning to replace \r\n, \r, \n occurrences with the PHP_EOL value. +| +| WARNING: This feature is DEPRECATED and currently available only +| for backwards compatibility purposes! +| +*/ +$config['standardize_newlines'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Global XSS Filtering +|-------------------------------------------------------------------------- +| +| Determines whether the XSS filter is always active when GET, POST or +| COOKIE data is encountered +| +| WARNING: This feature is DEPRECATED and currently available only +| for backwards compatibility purposes! +| +*/ +$config['global_xss_filtering'] = FALSE; + /* |-------------------------------------------------------------------------- | Cross Site Request Forgery @@ -452,6 +490,20 @@ */ $config['time_reference'] = 'local'; +/* +|-------------------------------------------------------------------------- +| Rewrite PHP Short Tags +|-------------------------------------------------------------------------- +| +| If your PHP installation does not have short tag support enabled CI +| can rewrite the tags on-the-fly, enabling you to utilize that syntax +| in your view files. Options are TRUE or FALSE (boolean) +| +| Note: You need to have eval() enabled for this to work. +| +*/ +$config['rewrite_short_tags'] = FALSE; + /* |-------------------------------------------------------------------------- | Reverse Proxy IPs diff --git a/application/config/constants.php b/application/config/constants.php index fb58784477c..18d3b4b76ff 100644 --- a/application/config/constants.php +++ b/application/config/constants.php @@ -65,10 +65,10 @@ | are as follows: | | Standard C/C++ Library (stdlibc): -| https://www.gnu.org/software/libc/manual/html_node/Exit-Status.html +| http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html | (This link also contains other GNU-specific conventions) | BSD sysexits.h: -| https://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits +| http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits | Bash scripting: | http://tldp.org/LDP/abs/html/exitcodes.html | diff --git a/application/config/database.php b/application/config/database.php index 77748959f9f..3d45a25cb13 100644 --- a/application/config/database.php +++ b/application/config/database.php @@ -22,7 +22,7 @@ | ['dbdriver'] The database driver. e.g.: mysqli. | Currently supported: | cubrid, ibase, mssql, mysql, mysqli, oci8, -| odbc, pdo, postgre, sqlite3, sqlsrv +| odbc, pdo, postgre, sqlite, sqlite3, sqlsrv | ['dbprefix'] You can add an optional prefix, which will be added | to the table name when using the Query Builder class | ['pconnect'] TRUE/FALSE - Whether to use a persistent connection @@ -76,9 +76,9 @@ $db['default'] = array( 'dsn' => '', 'hostname' => 'localhost', - 'username' => '', + 'username' => 'root', 'password' => '', - 'database' => '', + 'database' => 'instagram', 'dbdriver' => 'mysqli', 'dbprefix' => '', 'pconnect' => FALSE, diff --git a/application/config/index.html b/application/config/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/config/index.html +++ b/application/config/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/config/routes.php b/application/config/routes.php index 8ebf62bfa43..68827ae3f79 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -43,12 +43,12 @@ | This is not exactly a route, but allows you to automatically route | controller and method names that contain dashes. '-' isn't a valid | class or method name character, so it requires translation. -| When you set this option to TRUE, it will replace ALL dashes with -| underscores in the controller and method URI segments. +| When you set this option to TRUE, it will replace ALL dashes in the +| controller and method URI segments. | | Examples: my-controller/index -> my_controller/index | my-controller/my-method -> my_controller/my_method */ -$route['default_controller'] = 'welcome'; +$route['default_controller'] = 'C_Login'; $route['404_override'] = ''; $route['translate_uri_dashes'] = FALSE; diff --git a/application/config/smileys.php b/application/config/smileys.php new file mode 100644 index 00000000000..abf9a898dde --- /dev/null +++ b/application/config/smileys.php @@ -0,0 +1,64 @@ + array('grin.gif', '19', '19', 'grin'), + ':lol:' => array('lol.gif', '19', '19', 'LOL'), + ':cheese:' => array('cheese.gif', '19', '19', 'cheese'), + ':)' => array('smile.gif', '19', '19', 'smile'), + ';-)' => array('wink.gif', '19', '19', 'wink'), + ';)' => array('wink.gif', '19', '19', 'wink'), + ':smirk:' => array('smirk.gif', '19', '19', 'smirk'), + ':roll:' => array('rolleyes.gif', '19', '19', 'rolleyes'), + ':-S' => array('confused.gif', '19', '19', 'confused'), + ':wow:' => array('surprise.gif', '19', '19', 'surprised'), + ':bug:' => array('bigsurprise.gif', '19', '19', 'big surprise'), + ':-P' => array('tongue_laugh.gif', '19', '19', 'tongue laugh'), + '%-P' => array('tongue_rolleye.gif', '19', '19', 'tongue rolleye'), + ';-P' => array('tongue_wink.gif', '19', '19', 'tongue wink'), + ':P' => array('raspberry.gif', '19', '19', 'raspberry'), + ':blank:' => array('blank.gif', '19', '19', 'blank stare'), + ':long:' => array('longface.gif', '19', '19', 'long face'), + ':ohh:' => array('ohh.gif', '19', '19', 'ohh'), + ':grrr:' => array('grrr.gif', '19', '19', 'grrr'), + ':gulp:' => array('gulp.gif', '19', '19', 'gulp'), + '8-/' => array('ohoh.gif', '19', '19', 'oh oh'), + ':down:' => array('downer.gif', '19', '19', 'downer'), + ':red:' => array('embarrassed.gif', '19', '19', 'red face'), + ':sick:' => array('sick.gif', '19', '19', 'sick'), + ':shut:' => array('shuteye.gif', '19', '19', 'shut eye'), + ':-/' => array('hmm.gif', '19', '19', 'hmmm'), + '>:(' => array('mad.gif', '19', '19', 'mad'), + ':mad:' => array('mad.gif', '19', '19', 'mad'), + '>:-(' => array('angry.gif', '19', '19', 'angry'), + ':angry:' => array('angry.gif', '19', '19', 'angry'), + ':zip:' => array('zip.gif', '19', '19', 'zipper'), + ':kiss:' => array('kiss.gif', '19', '19', 'kiss'), + ':ahhh:' => array('shock.gif', '19', '19', 'shock'), + ':coolsmile:' => array('shade_smile.gif', '19', '19', 'cool smile'), + ':coolsmirk:' => array('shade_smirk.gif', '19', '19', 'cool smirk'), + ':coolgrin:' => array('shade_grin.gif', '19', '19', 'cool grin'), + ':coolhmm:' => array('shade_hmm.gif', '19', '19', 'cool hmm'), + ':coolmad:' => array('shade_mad.gif', '19', '19', 'cool mad'), + ':coolcheese:' => array('shade_cheese.gif', '19', '19', 'cool cheese'), + ':vampire:' => array('vampire.gif', '19', '19', 'vampire'), + ':snake:' => array('snake.gif', '19', '19', 'snake'), + ':exclaim:' => array('exclaim.gif', '19', '19', 'exclaim'), + ':question:' => array('question.gif', '19', '19', 'question') + +); diff --git a/application/config/user_agents.php b/application/config/user_agents.php index c866903f6da..c4429aac55f 100644 --- a/application/config/user_agents.php +++ b/application/config/user_agents.php @@ -87,8 +87,7 @@ 'amaya' => 'Amaya', 'IBrowse' => 'IBrowse', 'Maxthon' => 'Maxthon', - 'Ubuntu' => 'Ubuntu Web Browser', - 'Vivaldi' => 'Vivaldi' + 'Ubuntu' => 'Ubuntu Web Browser' ); $mobiles = array( diff --git a/application/controllers/C_Feed.php b/application/controllers/C_Feed.php new file mode 100644 index 00000000000..6149b37e688 --- /dev/null +++ b/application/controllers/C_Feed.php @@ -0,0 +1,17 @@ +load->view('feed'); + + } + +} diff --git a/application/controllers/C_Login.php b/application/controllers/C_Login.php new file mode 100644 index 00000000000..2cf01a07eb9 --- /dev/null +++ b/application/controllers/C_Login.php @@ -0,0 +1,37 @@ +load->model('M_Login'); + } + + public function index() + { + $this->load->view('index'); + } + + public function login() + { + $this->form_validation->set_rules('username', 'username', 'required'); + $this->form_validation->set_rules('password', 'password', 'required'); + + if ($this->form_validation->run() == false) { + redirect('C_Login'); + } else { + $username = $this->input->post('username',true); + $pass = $this->input->post('password',true); + $data = $this->M_Login->login($username,$pass); + if (count($data) == 1) { + $this->session->set_userdata('user', $data[0]); + redirect('C_Feed'); + } else { + redirect('C_Login'); + } + } + } + + +} diff --git a/application/controllers/C_profile.php b/application/controllers/C_profile.php new file mode 100644 index 00000000000..60eb12a6774 --- /dev/null +++ b/application/controllers/C_profile.php @@ -0,0 +1,44 @@ +load->model('M_profile'); + + } + + public function index() + { + $user = $this->session->userdata('user'); + $data['profile'] = $this->M_profile->getProfile($user['username']); + $this->load->view('profile',$data); + } + public function edit() + { + $user = $this->session->userdata('user'); + $data['profile'] = $this->M_profile->getProfile($user['username']); + $username = $data['profile']['username']; + $this->form_validation->set_rules('username', 'username','required'); + + if ($this->form_validation->run() == false) { + $this->load->view('edit-profile',$data); + + } else { + $update = array( + 'name' => $this->input->post('name'), + 'username' => $this->input->post('username'), + 'website' => $this->input->post('website'), + 'bio' => $this->input->post('bio'), + 'email' => $this->input->post('email'), + 'phone' => $this->input->post('phone'), + 'gender' => $this->input->post('gender'), + + ); + + $this->M_profile->editProfile($username,$update); + redirect('C_profile'); + } + } +} \ No newline at end of file diff --git a/application/controllers/index.html b/application/controllers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/controllers/index.html +++ b/application/controllers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/core/index.html b/application/core/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/core/index.html +++ b/application/core/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/helpers/index.html b/application/helpers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/helpers/index.html +++ b/application/helpers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/hooks/index.html b/application/hooks/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/hooks/index.html +++ b/application/hooks/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/index.html b/application/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/index.html +++ b/application/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/language/english/index.html b/application/language/english/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/language/english/index.html +++ b/application/language/english/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/language/index.html b/application/language/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/language/index.html +++ b/application/language/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/libraries/index.html b/application/libraries/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/libraries/index.html +++ b/application/libraries/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/logs/index.html b/application/logs/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/logs/index.html +++ b/application/logs/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/models/M_Login.php b/application/models/M_Login.php new file mode 100644 index 00000000000..a2c3e5c3422 --- /dev/null +++ b/application/models/M_Login.php @@ -0,0 +1,12 @@ +db->query("SELECT * FROM user WHERE username = '".$username."' AND password = '".$pass."'"); + return $query->result_array(); + } + +} diff --git a/application/models/M_Profile.php b/application/models/M_Profile.php new file mode 100644 index 00000000000..22386b5f857 --- /dev/null +++ b/application/models/M_Profile.php @@ -0,0 +1,20 @@ +db->query("SELECT * FROM profile WHERE username = '".$username."'"); + return $query->row_array(); + } + + public function editProfile($username,$data) + { + $query = $this->db->where('username',$username); + $this->db->update('profile',$data); + } +} + + diff --git a/application/models/index.html b/application/models/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/models/index.html +++ b/application/models/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/third_party/index.html b/application/third_party/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/third_party/index.html +++ b/application/third_party/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/views/box-model.php b/application/views/box-model.php new file mode 100644 index 00000000000..a52be8be767 --- /dev/null +++ b/application/views/box-model.php @@ -0,0 +1,42 @@ + + + + + + + Box Model + + + +
+
+
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/application/views/edit-profile.php b/application/views/edit-profile.php new file mode 100644 index 00000000000..2c41da3759f --- /dev/null +++ b/application/views/edit-profile.php @@ -0,0 +1,114 @@ + + + + + + + + Edit Profile | Vietgram + + + + + +
+
+
+
+ +
+

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + + + \ No newline at end of file diff --git a/application/views/errors/cli/index.html b/application/views/errors/cli/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/views/errors/cli/index.html +++ b/application/views/errors/cli/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/views/errors/html/error_404.php b/application/views/errors/html/error_404.php index d2f888c3f81..756ea9d6209 100644 --- a/application/views/errors/html/error_404.php +++ b/application/views/errors/html/error_404.php @@ -3,85 +3,62 @@ ?> - - 404 Page Not Found - +p { + margin: 12px 15px 12px 15px; +} +

-
- -
+
- + \ No newline at end of file diff --git a/application/views/errors/html/error_db.php b/application/views/errors/html/error_db.php index 23b0655fedc..f5a43f6382d 100644 --- a/application/views/errors/html/error_db.php +++ b/application/views/errors/html/error_db.php @@ -3,85 +3,62 @@ ?> - - Database Error - +p { + margin: 12px 15px 12px 15px; +} +

-
- -
+
- + \ No newline at end of file diff --git a/application/views/errors/html/error_exception.php b/application/views/errors/html/error_exception.php index befa12955e9..87848866af3 100644 --- a/application/views/errors/html/error_exception.php +++ b/application/views/errors/html/error_exception.php @@ -2,31 +2,31 @@ defined('BASEPATH') OR exit('No direct script access allowed'); ?> -
+
-

An uncaught Exception was encountered

+

An uncaught Exception was encountered

-

Type:

-

Message:

-

Filename: getFile(); ?>

-

Line Number: getLine(); ?>

+

Type:

+

Message:

+

Filename: getFile(); ?>

+

Line Number: getLine(); ?>

- + -

Backtrace:

- getTrace() as $error): ?> +

Backtrace:

+ getTrace() as $error): ?> - + -

- File:
- Line:
- Function: -

- +

+ File:
+ Line:
+ Function: +

+ - + - + -
+
\ No newline at end of file diff --git a/application/views/errors/html/error_general.php b/application/views/errors/html/error_general.php index ad106640970..fc3b2ebadba 100644 --- a/application/views/errors/html/error_general.php +++ b/application/views/errors/html/error_general.php @@ -3,85 +3,62 @@ ?> - - Error - +p { + margin: 12px 15px 12px 15px; +} +

-
- -
+
- + \ No newline at end of file diff --git a/application/views/errors/html/error_php.php b/application/views/errors/html/error_php.php index 8b445ef3960..b146f9c5bd3 100644 --- a/application/views/errors/html/error_php.php +++ b/application/views/errors/html/error_php.php @@ -2,32 +2,32 @@ defined('BASEPATH') OR exit('No direct script access allowed'); ?> -
+
-

A PHP Error was encountered

+

A PHP Error was encountered

-

Severity:

-

Message:

-

Filename:

-

Line Number:

+

Severity:

+

Message:

+

Filename:

+

Line Number:

- + -

Backtrace:

- +

Backtrace:

+ - + -

- File:
- Line:
- Function: -

+

+ File:
+ Line:
+ Function: +

- + - + - + -
+
\ No newline at end of file diff --git a/application/views/errors/html/index.html b/application/views/errors/html/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/views/errors/html/index.html +++ b/application/views/errors/html/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/views/errors/index.html b/application/views/errors/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/views/errors/index.html +++ b/application/views/errors/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/application/views/feed.php b/application/views/feed.php new file mode 100644 index 00000000000..c5062fab7f8 --- /dev/null +++ b/application/views/feed.php @@ -0,0 +1,117 @@ + + + + + + + + Feed | Vietgram + + + + + + +
+
+
+ Gilang Brilians + +
+ +
+
+ + + + + + +
+ +
    +
  • + +
  • +
  • + serranoarevalo love this! +
  • +
  • + serranoarevalo love this! +
  • +
  • + serranoarevalo love this! +
  • +
  • + serranoarevalo love this! +
  • +
+ 2 hours ago +
+ + +
+
+
+ +
+ + + + \ No newline at end of file diff --git a/application/views/index.php b/application/views/index.php new file mode 100644 index 00000000000..b8941e4bfee --- /dev/null +++ b/application/views/index.php @@ -0,0 +1,66 @@ + + + + Vietgram | Login + + + + + + + + +
+
+ +
+
+ + + +
+
+ + + \ No newline at end of file diff --git a/application/views/profile.php b/application/views/profile.php new file mode 100644 index 00000000000..8ff05de2fd2 --- /dev/null +++ b/application/views/profile.php @@ -0,0 +1,114 @@ + + + + + + + Profile | Vietgram + + + + + +
+
+
+ +
+
+
+

+ Edit profile + +
+
    +
  • + 1 posts +
  • +
  • + 872 followers +
  • +
  • + 201 following +
  • +
+

+ + +
+
+ +

+
+
+
+
+ +
+ + + + + + 344 + +
+
+
+
+ + + + \ No newline at end of file diff --git a/application/views/welcome_message.php b/application/views/welcome_message.php index dae768bc899..d79c049bfdf 100644 --- a/application/views/welcome_message.php +++ b/application/views/welcome_message.php @@ -8,19 +8,18 @@ -
-

- CodeIgniter -

-
-

The page you are looking at is being generated dynamically by CodeIgniter.

+
+

Welcome to CodeIgniter!

-

If you would like to edit this page you'll find it located at:

- application/views/welcome_message.php +
+

The page you are looking at is being generated dynamically by CodeIgniter.

-

The corresponding controller for this page is found at:

- application/controllers/Welcome.php +

If you would like to edit this page you'll find it located at:

+ application/views/welcome_message.php -

If you are exploring CodeIgniter for the very first time, you should start by reading the User Guide.

-
+

The corresponding controller for this page is found at:

+ application/controllers/Welcome.php - +

If you are exploring CodeIgniter for the very first time, you should start by reading the User Guide.

+ + +
+ diff --git a/assets/css/edit-profile.css b/assets/css/edit-profile.css new file mode 100644 index 00000000000..75465431998 --- /dev/null +++ b/assets/css/edit-profile.css @@ -0,0 +1,100 @@ +#edit-profile { + display: flex; + justify-content: center; +} + +#edit-profile .edit-profile__container { + background-color: white; + border: 1px solid #e6e6e6; + width: 100%; + max-width: 800px; +} + +#edit-profile .edit-profile__container { + padding: 40px 0; +} + +#edit-profile .edit-profile__header { + display: flex; + align-items: center; + margin-bottom: 50px; +} + +.edit-profile__header .edit-profile__avatar-container { + width: 200px; +} + +.edit-profile__avatar-container { + display: flex; + justify-content: flex-end; + margin-right: 35px; +} + +.edit-profile__avatar-container img { + width: 38px; + height: 38px; + border-radius: 50%; +} +.edit-profile__header h4 { + font-size: 18px; + font-weight: 600; +} + +.edit-profile__form .form__row { + display: flex; +} + +.form__row { + margin-bottom: 20px; + display: flex; + align-items: center; +} + +.form__row .form__label { + width: 200px; + display: block; + text-align: right; + margin-right: 35px; + font-weight: 600; + font-size: 16px; +} + +.form__row label { + font-size: 15px; + width: 80%; +} + +.form__row .form__input, +.form__row textarea { + padding: 8px; + width: 255px; + resize: vertical; + border: 0; + border: 1px solid #e6e6e6; + border-radius: 3px; +} + +.form__row input[type="checkbox"] { + margin-right: 15px; +} + +#edit-profile select { + background: 0 0; + border: 1px solid #efefef; + border-radius: 3px; + color: #262626; + font-size: 16px; + height: 32px; + padding: 0 30px 0 10px; +} + +#edit-profile input[type="submit"] { + margin-left: 235px; + border: 0; + color: white; + font-weight: 600; + border-radius: 3px; + background-color: var(--fd-blue); + font-size: 14px; + padding: 7px 25px; +} diff --git a/assets/css/explore.css b/assets/css/explore.css new file mode 100644 index 00000000000..d4a8f6ba2af --- /dev/null +++ b/assets/css/explore.css @@ -0,0 +1,70 @@ +#explore { + display: flex; + justify-content: center; + align-items: flex-start; + min-height: 500px; +} + +#explore .explore__users { + background-color: white; + border: 1px solid #e6e6e6; + border-radius: 3px; + width: 100%; + max-width: 600px; +} + +.explore__users .explore__user { + padding: 10px 15px; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid #e6e6e6; +} + +.explore__users .explore__user:last-child { + border: 0; +} + +.explore__user .explore__avatar { + width: 55px; + border-radius: 50%; +} + +.explore__user .explore__user-column { + display: flex; + align-items: center; +} + +.explore__user .explore__info { + margin-left: 15px; +} + +.explore__info .explore__username { + display: block; + font-weight: 600; + margin-bottom: 5px; +} + +.explore__info .explore__full-name { + color: #999; +} + +.explore__user-column button { + background-color: var(--fd-blue); + color: white; + border: 0; + font-weight: 600; + padding: 5px 10px; + font-size: 14px; + border-radius: 3px; + cursor: pointer; +} + +.explore__user-column button:active, +.explore__user-column button:focus { + outline: none; +} + +.explore__user-column:active { + opacity: 0.9; +} diff --git a/assets/css/feed.css b/assets/css/feed.css new file mode 100644 index 00000000000..cc88c16ef17 --- /dev/null +++ b/assets/css/feed.css @@ -0,0 +1,101 @@ +#feed { + display: flex; + align-items: center; + flex-direction: column; +} + +#feed .photo { + background-color: white; + border: 1px solid #e6e6e6; + border-radius: 3px; + width: 100%; + max-width: 600px; + margin-bottom: 65px; +} + +.photo .photo__header { + padding: 15px; + display: flex; + align-items: center; +} + +.photo__header .photo__avatar { + width: 32px; + border-radius: 50%; + margin-right: 10px; +} + +.photo .photo__user-info .photo__author { + display: block; + font-weight: 600; + margin-bottom: 5px; +} + +.photo > img { + max-width: 100%; +} + +.photo .photo__info { + padding: 15px 20px; +} + +.photo__actions { + margin-bottom: 15px; + font-size: 115%; +} + +.photo__actions .photo__action:first-child { + margin-right: 15px; +} + +.photo__actions .photo__action { + cursor: pointer; +} + +.photo .photo__likes { + font-weight: 600; + margin-bottom: 10px; + display: block; +} + +.photo .photo__add-comment-container { + margin-top: 15px; + border-top: 1px solid #e6e6e6; + padding-top: 10px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.photo__add-comment-container textarea { + width: 90%; + border: 0; + font-size: 14px; + resize: none; + height: 20px; +} + +.photo__add-comment-container textarea:focus, +.photo__add-comment-container textarea:active { + outline: none; +} + +.photo__add-comment-container i { + cursor: pointer; +} + +.photo .photo__time-ago { + font-size: 10px; + text-transform: uppercase; + color: #999; + margin-top: 10px; + display: block; +} + +.photo__comment { + margin-bottom: 10px; +} + +.photo__comments .photo__comment-author { + font-weight: 600; +} diff --git a/assets/css/footer.css b/assets/css/footer.css new file mode 100644 index 00000000000..0d5b8cbae0e --- /dev/null +++ b/assets/css/footer.css @@ -0,0 +1,30 @@ +.footer { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + max-width: 900px; + margin: 30px auto; + text-transform: uppercase; + font-size: 12px; + font-weight: 600; +} + +.footer .footer__list { + padding: 0; + list-style-type: none; + display: flex; +} + +.footer .footer__copyright { + color: hsl(0, 0%, 60%); +} + +.footer__list .footer__list-item { + margin-right: 10px; +} + +.footer .footer__link { + text-decoration: none; + color: var(--link-color); +} diff --git a/assets/css/globals.css b/assets/css/globals.css new file mode 100644 index 00000000000..cea96117b23 --- /dev/null +++ b/assets/css/globals.css @@ -0,0 +1,21 @@ +body { + background-color: white; + background-color: var(--background-color); + font-size: 14px; + font-family: "Open Sans", sans-serif; +} + +main { + animation: fadeInMain 0.5s linear; +} + +@keyframes fadeInMain { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0px); + } +} diff --git a/assets/css/login.css b/assets/css/login.css new file mode 100644 index 00000000000..f5657f0c13a --- /dev/null +++ b/assets/css/login.css @@ -0,0 +1,128 @@ +#login { + width: 100%; + max-width: 800px; + margin: 45px auto; + display: flex; + justify-content: space-around; +} + +#login .login__column { + width: 45%; +} + +.login__column .login__phone { + max-width: 100%; +} + +.login__column .login__box { + background-color: white; + border: 1px solid #e6e6e6; +} + +.login__column .login__box--transparent { + background: none; + border: 0; + display: flex; + flex-direction: column; + align-items: center; + margin-top: 35px; +} + +.login__column .login__appstores { + margin-top: 20px; +} + +.login__appstores .login__appstore { + height: 40px; +} + +#login .login__box { + padding: 30px 0; + text-align: center; +} + +#login .login__box:first-child { + margin-bottom: 10px; + padding-left: 40px; + padding-right: 40px; +} + +.login__column .login__logo { + height: 50px; +} + +.login__form input { + display: block; + width: 100%; + box-sizing: border-box; + padding: 7px; + font-size: 14px; + border: 0; + border: 1px solid #e6e6e6; + border-radius: 5px; + background: #fafafa; +} + +.login__form input:focus { + outline: none; + border: 1px solid #a9a9a9; +} + +.login__form input:first-child { + margin-bottom: 5px; +} + +.login__form input[type="submit"] { + background-color: #3f99ed; + border: 0; + padding: 5px; + margin-top: 15px; + margin-bottom: 20px; + color: white; + font-weight: 600; +} + +#login .login__divider { + display: block; + text-transform: uppercase; + font-weight: 600; + color: #999; + margin-bottom: 20px; + position: relative; + width: 100%; +} + +#login .login__link { + display: block; + text-decoration: none; + color: #003569; +} + +#login .login__link--small { + margin-top: 30px; +} + +.login__box a { + text-decoration: none; + color: var(--fd-blue); +} + +#login .login__divider:before { + content: ""; + height: 1px; + background-color: rgba(153, 153, 153, 0.5); + width: 40%; + position: absolute; + left: 0; + top: 10px; +} + +#login .login__divider:after { + content: ""; + height: 1px; + background-color: rgba(153, 153, 153, 0.5); + width: 40%; + position: absolute; + right: 0; + top: 10px; +} diff --git a/assets/css/mobile.css b/assets/css/mobile.css new file mode 100644 index 00000000000..fc236e0553c --- /dev/null +++ b/assets/css/mobile.css @@ -0,0 +1,110 @@ +@media screen and (min-width: 375px) and (max-width: 667px) { + .navigation { + padding: 0 20px; + margin-bottom: 0; + } + .navigation input, + .navigation .fa-search { + display: none; + } + #feed .photo { + background-color: transparent; + border: 0; + margin-bottom: 20px; + } + #feed .photo .photo__add-comment-container { + display: none; + } + .footer { + width: 80%; + } + .footer, + .footer .footer__list { + flex-wrap: wrap; + justify-content: center; + } + .footer__list .footer__list-item { + margin-bottom: 10px; + } + #login .login__column { + width: 100%; + } + #login .login__column:first-child { + display: none; + } + #login .login__box { + background-color: transparent; + border: 0; + } + #profile { + margin-top: 50px; + } + #profile .profile__header { + flex-direction: column; + align-items: center; + } + #profile .profile__title { + flex-wrap: wrap; + justify-content: center; + width: 100%; + } + .profile__title h3 { + margin: 20px 0; + } + .profile__title a { + margin-right: auto; + } + .profile__stats { + justify-content: space-between; + } + .profile__stats .profile__stat { + text-align: center; + margin-right: 0; + } + .profile__stat span { + display: block; + } + .profile__photos .profile__photo { + width: 33%; + margin-bottom: 0; + } + .profile__photos { + margin-bottom: 50px; + } + #explore .explore__users { + background-color: transparent; + border: 0; + } + .explore__users .explore__user { + border: 0; + } + #edit-profile > .edit-profile__container { + border: 0; + } + #edit-profile .form__row { + flex-direction: column; + } + .form__row .form__label { + margin: 0; + text-align: center; + margin-bottom: 10px; + } + #edit-profile input[type="submit"] { + width: 120px; + margin: 0; + margin-top: 20px; + } + #edit-profile .edit-profile__container { + display: flex; + flex-direction: column; + align-items: center; + } + #edit-profile .edit-profile__form { + display: flex; + flex-direction: column; + align-items: center; + } + .edit-profile__header .edit-profile__avatar-container { + width: 0; + } +} diff --git a/assets/css/navigation.css b/assets/css/navigation.css new file mode 100644 index 00000000000..cb729669732 --- /dev/null +++ b/assets/css/navigation.css @@ -0,0 +1,77 @@ +.navigation { + height: 75px; + background-color: white; + border-bottom: 1px solid #e6e6e6; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 100px; + margin-bottom: 60px; +} + +.navigation .navigation__column:first-child img { + height: 45px; +} + +.navigation .navigations__links { + display: flex; + padding: 0; + list-style-type: none; +} + +.navigation .navigation__list-item { + margin-left: 30px; + padding: 0 2px; + opacity: 0; + animation: slideNavLink 0.5s ease-out forwards; +} + +@keyframes slideNavLink { + from { + transform: translateY(-10px); + } + to { + opacity: 1; + transform: none; + } +} + +.navigation .navigation__list-item:nth-child(2) { + animation-delay: 0.2s; +} + +.navigation .navigation__list-item:last-child { + animation-delay: 0.3s; +} + +.navigation__link { + color: rgba(0, 0, 0, 0.8); + font-size: 18px; +} + +.navigation__column input { + padding: 5px 0; + padding-left: 60px; + border: 0; + border: 1px solid #e6e6e6; + border-radius: 3px; + background: #fafafa; + font-size: 16px; +} + +.navigation__column input:focus { + outline: none; + border: 1px solid #a9a9a9; +} + +.navigation__column { + position: relative; +} + +.navigation__column .fa-search { + position: absolute; + top: 10px; + left: 10px; + color: rgba(0, 0, 0, 0.5); + font-size: 12px; +} diff --git a/assets/css/profile.css b/assets/css/profile.css new file mode 100644 index 00000000000..5d115215978 --- /dev/null +++ b/assets/css/profile.css @@ -0,0 +1,161 @@ +#profile { + display: flex; + flex-direction: column; + align-items: center; +} + +#profile .profile__header { + max-width: 935px; + width: 100%; + display: flex; + margin-bottom: 50px; + font-size: 110%; +} + +.profile__header .profile__column { + width: 70%; +} + +.profile__header .profile__column:first-child { + width: 30%; + display: flex; + align-items: center; + justify-content: center; +} + +.profile__column:first-child img { + border-radius: 50%; + transform-style: preserve-3d; + transition: transform 0.5s linear; + animation: rotateLynn 1s linear infinite; +} + +@keyframes rotateLynn { + from { + transform: rotateY(0turn); + } + to { + transform: rotateY(1turn); + } +} + +.profile__column .profile__title, +.profile__column .profile__stats { + display: flex; + align-items: center; +} + +.profile__column .profile__title { + margin-bottom: 30px; +} + +.profile__title .profile__username { + margin-right: 25px; + font-size: 32px; + font-weight: 300; +} + +.profile__title a { + margin-right: 10px; + text-decoration: none; + color: inherit; + font-weight: 600; + padding: 5px 25px; + border: 1px solid #e6e6e6; + border-radius: 3px; + transition: all 0.3s ease-in-out; +} + +.profile__title a:hover { + background-color: #3f99ed; + color: white; + border-color: #3f99ed; +} + +.profile__title i { + cursor: pointer; + transition: transform 1s ease-in; +} + +.profile__title i:hover { + transform: rotate(2turn); +} + +.profile__column .profile__stats { + margin-bottom: 30px; +} + +.profile__stats .profile__stat { + margin-right: 40px; +} + +.profile__stat .stat__number { + font-weight: 600; +} + +.profile__bio .profile__full-name { + font-weight: 600; +} + +.profile__bio a { + color: var(--link-color); + font-weight: 600; + text-decoration: none; + display: block; +} + +.profile__column .profile__bio { + line-height: 125%; +} + +#profile .profile__photos { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + max-width: 936px; + width: 100%; +} + +.profile__photos .profile__photo { + width: 31%; + margin-bottom: 35px; + position: relative; +} + +.profile__photo img { + max-width: 100%; +} + +.profile__photo .profile__photo-overlay { + position: absolute; + top: 0; + background-color: rgba(0, 0, 0, 0.5); + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + color: white; + font-weight: 600; + opacity: 0; + transition: opacity 0.2s linear; +} + +.profile__photo:hover .profile__photo-overlay { + opacity: 1; +} + +.profile__photo-overlay .overlay__item { + font-size: 130%; + display: flex; + align-items: center; +} +.profile__photo-overlay .overlay__item:last-child { + margin-left: 10px; + /**/ +} + +.profile__photo-overlay .overlay__item i { + font-size: 130%; + margin-right: 5px; +} diff --git a/assets/css/reset.css b/assets/css/reset.css new file mode 100644 index 00000000000..82935aeceff --- /dev/null +++ b/assets/css/reset.css @@ -0,0 +1,124 @@ +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ""; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/assets/css/styles.css b/assets/css/styles.css new file mode 100644 index 00000000000..09dd98497fc --- /dev/null +++ b/assets/css/styles.css @@ -0,0 +1,12 @@ +@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600"); +@import "reset.css"; +@import "variables.css"; +@import "globals.css"; +@import "login.css"; +@import "footer.css"; +@import "navigation.css"; +@import "explore.css"; +@import "feed.css"; +@import "profile.css"; +@import "edit-profile.css"; +@import "mobile.css"; diff --git a/assets/css/variables.css b/assets/css/variables.css new file mode 100644 index 00000000000..0620c7ea3f3 --- /dev/null +++ b/assets/css/variables.css @@ -0,0 +1,5 @@ +:root { + --background-color: #fafafa; + --fd-blue: #3897f0; + --link-color: #003569; +} diff --git a/assets/images/android.png b/assets/images/android.png new file mode 100644 index 00000000000..306aa45f29e Binary files /dev/null and b/assets/images/android.png differ diff --git a/assets/images/avatar.jpg b/assets/images/avatar.jpg new file mode 100644 index 00000000000..5ef783b9abf Binary files /dev/null and b/assets/images/avatar.jpg differ diff --git a/assets/images/feedPhoto.jpg b/assets/images/feedPhoto.jpg new file mode 100644 index 00000000000..f1da1a8cf0d Binary files /dev/null and b/assets/images/feedPhoto.jpg differ diff --git a/assets/images/ios.png b/assets/images/ios.png new file mode 100644 index 00000000000..460f81ab32d Binary files /dev/null and b/assets/images/ios.png differ diff --git a/assets/images/loginLogo.png b/assets/images/loginLogo.png new file mode 100644 index 00000000000..332881b2ad3 Binary files /dev/null and b/assets/images/loginLogo.png differ diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 00000000000..e2ab02a7522 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/images/phoneImage.png b/assets/images/phoneImage.png new file mode 100644 index 00000000000..949173e7366 Binary files /dev/null and b/assets/images/phoneImage.png differ diff --git a/composer.json b/composer.json index 39c7e77c4d9..4a1b33313c4 100644 --- a/composer.json +++ b/composer.json @@ -5,13 +5,13 @@ "homepage": "https://codeigniter.com", "license": "MIT", "support": { - "forum": "https://forum.codeigniter.com/", + "forum": "http://forum.codeigniter.com/", "wiki": "https://github.com/bcit-ci/CodeIgniter/wiki", "slack": "https://codeigniterchat.slack.com", "source": "https://github.com/bcit-ci/CodeIgniter" }, "require": { - "php": ">=5.4.8" + "php": ">=5.3.7" }, "suggest": { "paragonie/random_compat": "Provides better randomness in PHP 5.x" diff --git a/contributing.md b/contributing.md index 8f43c45a652..703fe8f44a2 100644 --- a/contributing.md +++ b/contributing.md @@ -28,14 +28,14 @@ If you change anything that requires a change to documentation then you will nee ### Compatibility -CodeIgniter recommends PHP 5.5 or newer to be used, but it should be +CodeIgniter recommends PHP 5.4 or newer to be used, but it should be compatible with PHP 5.2.4 so all code supplied must stick to this requirement. If PHP 5.3 (and above) functions or features are used then there must be a fallback for PHP 5.2.4. ### Branching -CodeIgniter uses the [Git-Flow](https://nvie.com/posts/a-successful-git-branching-model/) branching model which requires all pull requests to be sent to the "develop" branch. This is +CodeIgniter uses the [Git-Flow](http://nvie.com/posts/a-successful-git-branching-model/) branching model which requires all pull requests to be sent to the "develop" branch. This is where the next planned version will be developed. The "master" branch will always contain the latest stable version and is kept clean so a "hotfix" (e.g: an emergency security patch) can be applied to master to create a new version, without worrying about other features holding it up. For this reason all commits need to be made to "develop" and any sent to "master" will be closed automatically. If you have multiple changes to submit, please place all changes into their own branch on your fork. One thing at a time: A pull request should only contain one change. That does not mean only one commit, but one change - however many commits it took. The reason for this is that if you change X and Y but send a pull request for both at the same time, we might really want X but disagree with Y, meaning we cannot merge the request. Using the Git-Flow branching model you can create new branches for both of these features and send two requests. @@ -54,7 +54,7 @@ This will sign your commits with the information setup in your git config, e.g. `Signed-off-by: John Q Public ` -If you are using [Tower](https://www.git-tower.com/) there is a "Sign-Off" checkbox in the commit window. You could even alias git commit to use the `-s` flag so you don’t have to think about it. +If you are using [Tower](http://www.git-tower.com/) there is a "Sign-Off" checkbox in the commit window. You could even alias git commit to use the `-s` flag so you don’t have to think about it. By signing your work in this manner, you certify to a "Developer's Certificate of Origin". The current version of this certificate is in the `DCO.txt` file in the root of this repository. diff --git a/index.php b/index.php index e7aab3b0381..e50550472ae 100755 --- a/index.php +++ b/index.php @@ -73,7 +73,14 @@ case 'testing': case 'production': ini_set('display_errors', 0); - error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); + if (version_compare(PHP_VERSION, '5.3', '>=')) + { + error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); + } + else + { + error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_USER_NOTICE); + } break; default: diff --git a/instagram.sql b/instagram.sql new file mode 100644 index 00000000000..06ce2b7b2c8 --- /dev/null +++ b/instagram.sql @@ -0,0 +1,92 @@ +-- phpMyAdmin SQL Dump +-- version 4.9.1 +-- https://www.phpmyadmin.net/ +-- +-- Host: 127.0.0.1 +-- Generation Time: Mar 10, 2020 at 04:17 PM +-- Server version: 10.4.8-MariaDB +-- PHP Version: 7.3.11 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET AUTOCOMMIT = 0; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `instagram` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `photo` +-- + +CREATE TABLE `photo` ( + `url` varchar(50) NOT NULL, + `caption` varchar(500) NOT NULL, + `like` int(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- +-- Dumping data for table `photo` +-- + +INSERT INTO `photo` (`url`, `caption`, `like`) VALUES +('feed.php', 'hola', 578), +('feed.php', 'hello world', 500), +('feed.html', 'good day', 400), +('feed.html', 'look what i found', 756); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `profile` +-- + +CREATE TABLE `profile` ( + `name` varchar(50) NOT NULL, + `username` varchar(50) NOT NULL, + `website` varchar(100) NOT NULL, + `bio` varchar(500) NOT NULL, + `email` varchar(50) NOT NULL, + `phone` varchar(13) NOT NULL, + `gender` enum('Male','Female','Can''t Remember','') NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- +-- Dumping data for table `profile` +-- + +INSERT INTO `profile` (`name`, `username`, `website`, `bio`, `email`, `phone`, `gender`) VALUES +('Gilang Brilians', 'brilians', 'https://www.youtube.com/', 'my name is gilang ', 'hai@gmail.com', '082359517482', 'Male'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user` +-- + +CREATE TABLE `user` ( + `username` varchar(50) NOT NULL, + `password` varchar(15) NOT NULL, + `email` varchar(50) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- +-- Dumping data for table `user` +-- + +INSERT INTO `user` (`username`, `password`, `email`) VALUES +('brilians', '12345678', 'hai@gmail.com'); +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml deleted file mode 100644 index 6dc58c25986..00000000000 --- a/phpdoc.dist.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - CodeIgniter v3.0.0 API - - ./api/ - - - ./api/ - - - ./system - - - - warn - - ./api/log/{DATE}.log - ./api/{DATE}.errors.log - - - \ No newline at end of file diff --git a/readme.rst b/readme.rst index 3e1382fbd8a..b6520080e91 100644 --- a/readme.rst +++ b/readme.rst @@ -31,7 +31,7 @@ Server Requirements PHP version 5.6 or newer is recommended. -It should work on 5.4.8 as well, but we strongly advise you NOT to run +It should work on 5.3.7 as well, but we strongly advise you NOT to run such old versions of PHP, because of potential security and performance issues, as well as missing features. @@ -55,7 +55,7 @@ Resources - `User Guide `_ - `Language File Translations `_ -- `Community Forums `_ +- `Community Forums `_ - `Community Wiki `_ - `Community Slack Channel `_ diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 9bf60a4ac6e..bd0c4c5d81b 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -55,7 +55,7 @@ * @var string * */ - const CI_VERSION = '3.2.0-dev'; + const CI_VERSION = '3.1.12-dev'; /* * ------------------------------------------------------ @@ -79,6 +79,57 @@ */ require_once(BASEPATH.'core/Common.php'); + +/* + * ------------------------------------------------------ + * Security procedures + * ------------------------------------------------------ + */ + +if ( ! is_php('5.4')) +{ + ini_set('magic_quotes_runtime', 0); + + if ((bool) ini_get('register_globals')) + { + $_protected = array( + '_SERVER', + '_GET', + '_POST', + '_FILES', + '_REQUEST', + '_SESSION', + '_ENV', + '_COOKIE', + 'GLOBALS', + 'HTTP_RAW_POST_DATA', + 'system_path', + 'application_folder', + 'view_folder', + '_protected', + '_registered' + ); + + $_registered = ini_get('variables_order'); + foreach (array('E' => '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal) + { + if (strpos($_registered, $key) === FALSE) + { + continue; + } + + foreach (array_keys($$superglobal) as $var) + { + if (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE)) + { + $GLOBALS[$var] = NULL; + } + } + } + } +} + + /* * ------------------------------------------------------ * Define a custom error handler so we can log PHP errors @@ -141,6 +192,20 @@ $BM->mark('total_execution_time_start'); $BM->mark('loading_time:_base_classes_start'); +/* + * ------------------------------------------------------ + * Instantiate the hooks class + * ------------------------------------------------------ + */ + $EXT =& load_class('Hooks', 'core'); + +/* + * ------------------------------------------------------ + * Is there a "pre_system" hook? + * ------------------------------------------------------ + */ + $EXT->call_hook('pre_system'); + /* * ------------------------------------------------------ * Instantiate the config class @@ -162,20 +227,6 @@ } } -/* - * ------------------------------------------------------ - * Instantiate the hooks class - * ------------------------------------------------------ - */ - $EXT =& load_class('Hooks', 'core', $CFG); - -/* - * ------------------------------------------------------ - * Is there a "pre_system" hook? - * ------------------------------------------------------ - */ - $EXT->call_hook('pre_system'); - /* * ------------------------------------------------------ * Important charset-related stuff @@ -243,14 +294,14 @@ * Instantiate the UTF-8 class * ------------------------------------------------------ */ - $UNI =& load_class('Utf8', 'core', $charset); + $UNI =& load_class('Utf8', 'core'); /* * ------------------------------------------------------ * Instantiate the URI class * ------------------------------------------------------ */ - $URI =& load_class('URI', 'core', $CFG); + $URI =& load_class('URI', 'core'); /* * ------------------------------------------------------ @@ -281,14 +332,14 @@ * Load the security class for xss and csrf support * ----------------------------------------------------- */ - $SEC =& load_class('Security', 'core', $charset); + $SEC =& load_class('Security', 'core'); /* * ------------------------------------------------------ * Load the Input class and sanitize globals * ------------------------------------------------------ */ - $IN =& load_class('Input', 'core', $SEC); + $IN =& load_class('Input', 'core'); /* * ------------------------------------------------------ diff --git a/system/core/Common.php b/system/core/Common.php index fadc0a0b182..624b5a9f776 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -81,7 +81,8 @@ function is_php($version) * Tests for file writability * * is_writable() returns TRUE on Windows servers when you really can't write to - * the file, based on the read-only attribute. + * the file, based on the read-only attribute. is_writable() is also unreliable + * on Unix servers if safe_mode is on. * * @link https://bugs.php.net/bug.php?id=54709 * @param string @@ -89,8 +90,8 @@ function is_php($version) */ function is_really_writable($file) { - // If we're on a UNIX-like server, just is_writable() - if (DIRECTORY_SEPARATOR === '/') + // If we're on a Unix server with safe_mode off we call is_writable + if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode'))) { return is_writable($file); } @@ -498,7 +499,6 @@ function set_status_header($code = 200, $text = '') $stati = array( 100 => 'Continue', 101 => 'Switching Protocols', - 103 => 'Early Hints', 200 => 'OK', 201 => 'Created', @@ -507,7 +507,6 @@ function set_status_header($code = 200, $text = '') 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', - 207 => 'Multi-Status', 300 => 'Multiple Choices', 301 => 'Moved Permanently', @@ -516,7 +515,6 @@ function set_status_header($code = 200, $text = '') 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', - 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', @@ -536,13 +534,11 @@ function set_status_header($code = 200, $text = '') 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', - 421 => 'Misdirected Request', 422 => 'Unprocessable Entity', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', - 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', @@ -629,7 +625,7 @@ function _error_handler($severity, $message, $filepath, $line) // If the error is fatal, the execution of the script should be stopped because // errors can't be recovered from. Halting the script conforms with PHP's - // default error handling. See https://secure.php.net/manual/en/errorfunc.constants.php + // default error handling. See http://www.php.net/manual/en/errorfunc.constants.php if ($is_error) { exit(1); // EXIT_ERROR diff --git a/system/core/Config.php b/system/core/Config.php index 13cc087d020..fc6c30f866f 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -169,7 +169,7 @@ public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE $this->is_loaded[] = $file_path; $config = NULL; $loaded = TRUE; - log_message('info', 'Config file loaded: '.$file_path); + log_message('debug', 'Config file loaded: '.$file_path); } } @@ -350,6 +350,20 @@ protected function _uri_string($uri) // -------------------------------------------------------------------- + /** + * System URL + * + * @deprecated 3.0.0 Encourages insecure practices + * @return string + */ + public function system_url() + { + $x = explode('/', preg_replace('|/*(.+?)/*$|', '\\1', BASEPATH)); + return $this->slash_item('base_url').end($x).'/'; + } + + // -------------------------------------------------------------------- + /** * Set a config file item * diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index e8e7f6c2939..90ff1abf4bb 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -161,10 +161,6 @@ public function show_error($heading, $message, $template = 'error_general', $sta { $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; } - else - { - $templates_path = rtrim($templates_path, '/\\').DIRECTORY_SEPARATOR; - } if (is_cli()) { @@ -198,10 +194,6 @@ public function show_exception($exception) { $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; } - else - { - $templates_path = rtrim($templates_path, '/\\').DIRECTORY_SEPARATOR; - } $message = $exception->getMessage(); if (empty($message)) @@ -248,10 +240,6 @@ public function show_php_error($severity, $message, $filepath, $line) { $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; } - else - { - $templates_path = rtrim($templates_path, '/\\').DIRECTORY_SEPARATOR; - } $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity; diff --git a/system/core/Hooks.php b/system/core/Hooks.php index 353e22e214f..6236dd498c1 100644 --- a/system/core/Hooks.php +++ b/system/core/Hooks.php @@ -83,16 +83,16 @@ class CI_Hooks { /** * Class constructor * - * @param CI_Config $config * @return void */ - public function __construct(CI_Config $config) + public function __construct() { + $CFG =& load_class('Config', 'core'); log_message('info', 'Hooks Class Initialized'); // If hooks are not enabled in the config file // there is nothing else to do - if ($config->item('enable_hooks') === FALSE) + if ($CFG->item('enable_hooks') === FALSE) { return; } diff --git a/system/core/Input.php b/system/core/Input.php index 053970b01a3..30b31d0d725 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -57,6 +57,45 @@ class CI_Input { */ protected $ip_address = FALSE; + /** + * Allow GET array flag + * + * If set to FALSE, then $_GET will be set to an empty array. + * + * @var bool + */ + protected $_allow_get_array = TRUE; + + /** + * Standardize new lines flag + * + * If set to TRUE, then newlines are standardized. + * + * @var bool + */ + protected $_standardize_newlines; + + /** + * Enable XSS flag + * + * Determines whether the XSS filter is always active when + * GET, POST or COOKIE data is encountered. + * Set automatically based on config setting. + * + * @var bool + */ + protected $_enable_xss = FALSE; + + /** + * Enable CSRF flag + * + * Enables a CSRF cookie token to be set. + * Set automatically based on config setting. + * + * @var bool + */ + protected $_enable_csrf = FALSE; + /** * List of all HTTP request headers * @@ -83,15 +122,8 @@ class CI_Input { */ protected $_input_stream; - /** - * CI_Security instance - * - * Used for the optional $xss_filter parameter that most - * getter methods have here. - * - * @var CI_Security - */ protected $security; + protected $uni; // -------------------------------------------------------------------- @@ -103,9 +135,30 @@ class CI_Input { * * @return void */ - public function __construct(CI_Security &$security) + public function __construct() { - $this->security = $security; + $this->_allow_get_array = (config_item('allow_get_array') !== FALSE); + $this->_enable_xss = (config_item('global_xss_filtering') === TRUE); + $this->_enable_csrf = (config_item('csrf_protection') === TRUE); + $this->_standardize_newlines = (bool) config_item('standardize_newlines'); + + $this->security =& load_class('Security', 'core'); + + // Do we need the UTF-8 class? + if (UTF8_ENABLED === TRUE) + { + $this->uni =& load_class('Utf8', 'core'); + } + + // Sanitize global arrays + $this->_sanitize_globals(); + + // CSRF Protection check + if ($this->_enable_csrf === TRUE && ! is_cli()) + { + $this->security->csrf_verify(); + } + log_message('info', 'Input Class Initialized'); } @@ -121,8 +174,10 @@ public function __construct(CI_Security &$security) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = FALSE) + protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL) { + is_bool($xss_clean) OR $xss_clean = $this->_enable_xss; + // If $index is NULL, it means that the whole $array is requested isset($index) OR $index = array_keys($array); @@ -182,7 +237,7 @@ protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function get($index = NULL, $xss_clean = FALSE) + public function get($index = NULL, $xss_clean = NULL) { return $this->_fetch_from_array($_GET, $index, $xss_clean); } @@ -196,7 +251,7 @@ public function get($index = NULL, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function post($index = NULL, $xss_clean = FALSE) + public function post($index = NULL, $xss_clean = NULL) { return $this->_fetch_from_array($_POST, $index, $xss_clean); } @@ -210,10 +265,11 @@ public function post($index = NULL, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function post_get($index, $xss_clean = FALSE) + public function post_get($index, $xss_clean = NULL) { - $output = $this->post($index, $xss_clean); - return isset($output) ? $output : $this->get($index, $xss_clean); + return isset($_POST[$index]) + ? $this->post($index, $xss_clean) + : $this->get($index, $xss_clean); } // -------------------------------------------------------------------- @@ -225,10 +281,11 @@ public function post_get($index, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function get_post($index, $xss_clean = FALSE) + public function get_post($index, $xss_clean = NULL) { - $output = $this->get($index, $xss_clean); - return isset($output) ? $output : $this->post($index, $xss_clean); + return isset($_GET[$index]) + ? $this->get($index, $xss_clean) + : $this->post($index, $xss_clean); } // -------------------------------------------------------------------- @@ -240,7 +297,7 @@ public function get_post($index, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function cookie($index = NULL, $xss_clean = FALSE) + public function cookie($index = NULL, $xss_clean = NULL) { return $this->_fetch_from_array($_COOKIE, $index, $xss_clean); } @@ -254,7 +311,7 @@ public function cookie($index = NULL, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function server($index, $xss_clean = FALSE) + public function server($index, $xss_clean = NULL) { return $this->_fetch_from_array($_SERVER, $index, $xss_clean); } @@ -270,7 +327,7 @@ public function server($index, $xss_clean = FALSE) * @param bool $xss_clean Whether to apply XSS filtering * @return mixed */ - public function input_stream($index = NULL, $xss_clean = FALSE) + public function input_stream($index = NULL, $xss_clean = NULL) { // Prior to PHP 5.6, the input stream can only be read once, // so we'll need to check if we have already done that first. @@ -302,7 +359,7 @@ public function input_stream($index = NULL, $xss_clean = FALSE) * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript) * @return void */ - public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) + public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) { if (is_array($name)) { @@ -339,9 +396,9 @@ public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path ? (bool) config_item('cookie_httponly') : (bool) $httponly; - if ( ! is_numeric($expire) OR $expire < 0) + if ( ! is_numeric($expire)) { - $expire = 1; + $expire = time() - 86500; } else { @@ -522,13 +579,174 @@ public function valid_ip($ip, $which = '') * * @return string|null User Agent string or NULL if it doesn't exist */ - public function user_agent($xss_clean = FALSE) + public function user_agent($xss_clean = NULL) { return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean); } // -------------------------------------------------------------------- + /** + * Sanitize Globals + * + * Internal method serving for the following purposes: + * + * - Unsets $_GET data, if query strings are not enabled + * - Cleans POST, COOKIE and SERVER data + * - Standardizes newline characters to PHP_EOL + * + * @return void + */ + protected function _sanitize_globals() + { + // Is $_GET data allowed? If not we'll set the $_GET to an empty array + if ($this->_allow_get_array === FALSE) + { + $_GET = array(); + } + elseif (is_array($_GET)) + { + foreach ($_GET as $key => $val) + { + $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + } + } + + // Clean $_POST Data + if (is_array($_POST)) + { + foreach ($_POST as $key => $val) + { + $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); + } + } + + // Clean $_COOKIE Data + if (is_array($_COOKIE)) + { + // Also get rid of specially treated cookies that might be set by a server + // or silly application, that are of no use to a CI application anyway + // but that when present will trip our 'Disallowed Key Characters' alarm + // http://www.ietf.org/rfc/rfc2109.txt + // note that the key names below are single quoted strings, and are not PHP variables + unset( + $_COOKIE['$Version'], + $_COOKIE['$Path'], + $_COOKIE['$Domain'] + ); + + foreach ($_COOKIE as $key => $val) + { + if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE) + { + $_COOKIE[$cookie_key] = $this->_clean_input_data($val); + } + else + { + unset($_COOKIE[$key]); + } + } + } + + // Sanitize PHP_SELF + $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']); + + log_message('debug', 'Global POST, GET and COOKIE data sanitized'); + } + + // -------------------------------------------------------------------- + + /** + * Clean Input Data + * + * Internal method that aids in escaping data and + * standardizing newline characters to PHP_EOL. + * + * @param string|string[] $str Input string(s) + * @return string + */ + protected function _clean_input_data($str) + { + if (is_array($str)) + { + $new_array = array(); + foreach (array_keys($str) as $key) + { + $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]); + } + return $new_array; + } + + /* We strip slashes if magic quotes is on to keep things consistent + + NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and + it will probably not exist in future versions at all. + */ + if ( ! is_php('5.4') && get_magic_quotes_gpc()) + { + $str = stripslashes($str); + } + + // Clean UTF-8 if supported + if (UTF8_ENABLED === TRUE) + { + $str = $this->uni->clean_string($str); + } + + // Remove control characters + $str = remove_invisible_characters($str, FALSE); + + // Standardize newlines if needed + if ($this->_standardize_newlines === TRUE) + { + return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str); + } + + return $str; + } + + // -------------------------------------------------------------------- + + /** + * Clean Keys + * + * Internal method that helps 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. + * + * @param string $str Input string + * @param bool $fatal Whether to terminate script exection + * or to return FALSE if an invalid + * key is encountered + * @return string|bool + */ + protected function _clean_input_keys($str, $fatal = TRUE) + { + if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str)) + { + if ($fatal === TRUE) + { + return FALSE; + } + else + { + set_status_header(503); + echo 'Disallowed Key Characters.'; + exit(7); // EXIT_USER_INPUT + } + } + + // Clean UTF-8 if supported + if (UTF8_ENABLED === TRUE) + { + return $this->uni->clean_string($str); + } + + return $str; + } + + // -------------------------------------------------------------------- + /** * Request Headers * @@ -620,6 +838,21 @@ public function is_ajax_request() // -------------------------------------------------------------------- + /** + * Is CLI request? + * + * Test to see if a request was made from the command line. + * + * @deprecated 3.0.0 Use is_cli() instead + * @return bool + */ + public function is_cli_request() + { + return is_cli(); + } + + // -------------------------------------------------------------------- + /** * Get Request Method * diff --git a/system/core/Loader.php b/system/core/Loader.php index 0710b1611a3..14888e49a5d 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -348,10 +348,9 @@ public function model($model, $name = '', $db_conn = FALSE) throw new RuntimeException('Unable to locate the model you have specified: '.$model); } } - - if ( ! is_subclass_of($model, 'CI_Model')) + elseif ( ! is_subclass_of($model, 'CI_Model')) { - throw new RuntimeException("Class ".$model." doesn't extend CI_Model"); + throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model"); } $this->_ci_models[] = $name; @@ -944,7 +943,7 @@ protected function _ci_load($_ci_data) empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars); extract($this->_ci_cached_vars); - /** + /* * Buffer the output * * We buffer the output for two reasons: @@ -957,7 +956,18 @@ protected function _ci_load($_ci_data) */ ob_start(); - include($_ci_path); // include() vs include_once() allows for multiple views with the same name + // If the PHP installation does not support short tags we'll + // do a little string replacement, changing the short tags + // to standard PHP echo statements. + if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE) + { + echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('_log_path = ($config['log_path'] !== '') - ? rtrim($config['log_path'], '/\\').DIRECTORY_SEPARATOR : APPPATH.'logs'.DIRECTORY_SEPARATOR; - + $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/'; $this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '') ? ltrim($config['log_file_extension'], '.') : 'php'; @@ -285,6 +283,9 @@ protected static function substr($str, $start, $length = NULL) { if (self::$func_overload) { + // mb_substr($str, $start, null, '8bit') returns an empty + // string on PHP 5.3 + isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); return mb_substr($str, $start, $length, '8bit'); } diff --git a/system/core/Model.php b/system/core/Model.php index 4c497d21e9e..0aadbcdc830 100644 --- a/system/core/Model.php +++ b/system/core/Model.php @@ -48,6 +48,14 @@ */ class CI_Model { + /** + * Class constructor + * + * @link https://github.com/bcit-ci/CodeIgniter/issues/5332 + * @return void + */ + public function __construct() {} + /** * __get magic * diff --git a/system/core/Output.php b/system/core/Output.php index f386d3ad455..64e7ee1f91a 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -412,7 +412,7 @@ public function cache($time) * @param string $output Output data override * @return void */ - public function _display($output = NULL) + public function _display($output = '') { // Note: We use load_class() because we can't use $CI =& get_instance() // since this function is sometimes called by the caching mechanism, @@ -429,7 +429,7 @@ public function _display($output = NULL) // -------------------------------------------------------------------- // Set the output data - if ($output === NULL) + if ($output === '') { $output =& $this->final_output; } @@ -502,7 +502,7 @@ public function _display($output = NULL) echo $output; log_message('info', 'Final output sent to browser'); - log_message('info', 'Total execution time: '.$elapsed); + log_message('debug', 'Total execution time: '.$elapsed); return; } @@ -539,7 +539,7 @@ public function _display($output = NULL) } log_message('info', 'Final output sent to browser'); - log_message('info', 'Total execution time: '.$elapsed); + log_message('debug', 'Total execution time: '.$elapsed); } // -------------------------------------------------------------------- @@ -554,7 +554,7 @@ public function _write_cache($output) { $CI =& get_instance(); $path = $CI->config->item('cache_path'); - $cache_path = ($path === '') ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR; + $cache_path = ($path === '') ? APPPATH.'cache/' : $path; if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path)) { @@ -563,7 +563,7 @@ public function _write_cache($output) } $uri = $CI->config->item('base_url') - .$CI->config->slash_item('index_page') + .$CI->config->item('index_page') .$CI->uri->uri_string(); if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING'])) @@ -658,7 +658,7 @@ public function _display_cache(&$CFG, &$URI) $cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path'); // Build the file path. The file name is an MD5 hash of the full URI - $uri = $CFG->item('base_url').$CFG->slash_item('index_page').$URI->uri_string; + $uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string; if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING'])) { @@ -761,7 +761,7 @@ public function delete_cache($uri = '') } } - $cache_path .= md5($CI->config->item('base_url').$CI->config->slash_item('index_page').ltrim($uri, '/')); + $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/')); if ( ! @unlink($cache_path)) { @@ -829,6 +829,9 @@ protected static function substr($str, $start, $length = NULL) { if (self::$func_overload) { + // mb_substr($str, $start, null, '8bit') returns an empty + // string on PHP 5.3 + isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); return mb_substr($str, $start, $length, '8bit'); } diff --git a/system/core/Router.php b/system/core/Router.php index dcdd1ed1fea..90b69d07a68 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -438,6 +438,19 @@ public function set_class($class) // -------------------------------------------------------------------- + /** + * Fetch the current class + * + * @deprecated 3.0.0 Read the 'class' property instead + * @return string + */ + public function fetch_class() + { + return $this->class; + } + + // -------------------------------------------------------------------- + /** * Set method name * @@ -451,6 +464,19 @@ public function set_method($method) // -------------------------------------------------------------------- + /** + * Fetch the current method + * + * @deprecated 3.0.0 Read the 'method' property instead + * @return string + */ + public function fetch_method() + { + return $this->method; + } + + // -------------------------------------------------------------------- + /** * Set directory name * @@ -469,4 +495,21 @@ public function set_directory($dir, $append = FALSE) $this->directory .= str_replace('.', '', trim($dir, '/')).'/'; } } + + // -------------------------------------------------------------------- + + /** + * Fetch directory + * + * Feches the sub-directory (if any) that contains the requested + * controller class. + * + * @deprecated 3.0.0 Read the 'directory' property instead + * @return string + */ + public function fetch_directory() + { + return $this->directory; + } + } diff --git a/system/core/Security.php b/system/core/Security.php index 5edb67f4eec..6a81faff145 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -169,12 +169,10 @@ class CI_Security { * * @return void */ - public function __construct($charset) + public function __construct() { - $this->charset = $charset; - // Is CSRF protection enabled? - if (config_item('csrf_protection') && ! is_cli()) + if (config_item('csrf_protection')) { // CSRF config foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key) @@ -193,9 +191,10 @@ public function __construct($charset) // Set the CSRF hash $this->_csrf_set_hash(); - $this->csrf_verify(); } + $this->charset = strtoupper(config_item('charset')); + log_message('info', 'Security Class Initialized'); } @@ -640,7 +639,7 @@ public function get_random_bytes($length) if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE) { // Try not to waste entropy ... - stream_set_chunk_size($fp, $length); + is_php('5.4') && stream_set_chunk_size($fp, $length); $output = fread($fp, $length); fclose($fp); if ($output !== FALSE) @@ -670,7 +669,7 @@ public function get_random_bytes($length) * correctly. html_entity_decode() does not convert entities without * semicolons, so we are left with our own little solution here. Bummer. * - * @link https://secure.php.net/html-entity-decode + * @link http://php.net/html-entity-decode * * @param string $str Input * @param string $charset Character set @@ -685,8 +684,26 @@ public function entity_decode($str, $charset = NULL) static $_entities; - isset($charset) OR $charset = $this->charset; - isset($_entities) OR $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML5, $charset)); + isset($charset) OR $charset = $this->charset; + $flag = is_php('5.4') + ? ENT_COMPAT | ENT_HTML5 + : ENT_COMPAT; + + if ( ! isset($_entities)) + { + $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, $flag, $charset)); + + // If we're not on PHP 5.4+, add the possibly dangerous HTML 5 + // entities to the array manually + if ($flag === ENT_COMPAT) + { + $_entities[':'] = ':'; + $_entities['('] = '('; + $_entities[')'] = ')'; + $_entities["\n"] = ' '; + $_entities["\t"] = ' '; + } + } do { @@ -711,9 +728,14 @@ public function entity_decode($str, $charset = NULL) // Decode numeric & UTF16 two byte entities $str = html_entity_decode( preg_replace('/(&#(?:x0*[0-9a-f]{2,5}(?![0-9a-f;])|(?:0*\d{2,4}(?![0-9;]))))/iS', '$1;', $str), - ENT_COMPAT | ENT_HTML5, + $flag, $charset ); + + if ($flag === ENT_COMPAT) + { + $str = str_replace(array_values($_entities), array_keys($_entities), $str); + } } while ($str_compare !== $str); return $str; @@ -1065,4 +1087,5 @@ protected function _csrf_set_hash() return $this->_csrf_hash; } + } diff --git a/system/core/URI.php b/system/core/URI.php index 3670ef29d4a..a8b98ae9323 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -96,40 +96,45 @@ class CI_URI { * * @return void */ - public function __construct(CI_Config $config) + public function __construct() { - $this->config = $config; + $this->config =& load_class('Config', 'core'); - // If it's a CLI request, ignore the configuration - if (is_cli()) - { - $this->_set_uri_string($this->_parse_argv(), TRUE); - } // If query strings are enabled, we don't need to parse any segments. - elseif ($this->config->item('enable_query_strings') !== TRUE) + // However, they don't make sense under CLI. + if (is_cli() OR $this->config->item('enable_query_strings') !== TRUE) { $this->_permitted_uri_chars = $this->config->item('permitted_uri_chars'); - $protocol = $this->config->item('uri_protocol'); - empty($protocol) && $protocol = 'REQUEST_URI'; - switch ($protocol) + // If it's a CLI request, ignore the configuration + if (is_cli()) { - case 'AUTO': // For BC purposes only - case 'REQUEST_URI': - $uri = $this->_parse_request_uri(); - break; - case 'QUERY_STRING': - $uri = $this->_parse_query_string(); - break; - case 'PATH_INFO': - default: - $uri = isset($_SERVER[$protocol]) - ? $_SERVER[$protocol] - : $this->_parse_request_uri(); - break; + $uri = $this->_parse_argv(); } + else + { + $protocol = $this->config->item('uri_protocol'); + empty($protocol) && $protocol = 'REQUEST_URI'; - $this->_set_uri_string($uri, FALSE); + switch ($protocol) + { + case 'AUTO': // For BC purposes only + case 'REQUEST_URI': + $uri = $this->_parse_request_uri(); + break; + case 'QUERY_STRING': + $uri = $this->_parse_query_string(); + break; + case 'PATH_INFO': + default: + $uri = isset($_SERVER[$protocol]) + ? $_SERVER[$protocol] + : $this->_parse_request_uri(); + break; + } + } + + $this->_set_uri_string($uri); } log_message('info', 'URI Class Initialized'); @@ -140,66 +145,43 @@ public function __construct(CI_Config $config) /** * Set URI String * - * @param string $str Input URI string - * @param bool $is_cli Whether the input comes from CLI + * @param string $str * @return void */ - protected function _set_uri_string($str, $is_cli = FALSE) + protected function _set_uri_string($str) { - // CLI requests have a bit simpler logic - if ($is_cli) + // Filter out control characters and trim slashes + $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/'); + + if ($this->uri_string !== '') { - if (($this->uri_string = trim($str, '/')) === '') + // Remove the URL suffix, if present + if (($suffix = (string) $this->config->item('url_suffix')) !== '') { - return; + $slen = strlen($suffix); + + if (substr($this->uri_string, -$slen) === $suffix) + { + $this->uri_string = substr($this->uri_string, 0, -$slen); + } } $this->segments[0] = NULL; - foreach (explode('/', $this->uri_string) as $segment) + // Populate the segments array + foreach (explode('/', trim($this->uri_string, '/')) as $val) { - if (($segment = trim($segment)) !== '') + $val = trim($val); + // Filter segments for security + $this->filter_uri($val); + + if ($val !== '') { - $this->segments[] = $segment; + $this->segments[] = $val; } } unset($this->segments[0]); - return; - } - - // Filter out control characters and trim slashes - $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/'); - - if ($this->uri_string === '') - { - return; } - - // Remove the URL suffix, if present - if (($suffix = (string) $this->config->item('url_suffix')) !== '') - { - $slen = strlen($suffix); - - if (substr($this->uri_string, -$slen) === $suffix) - { - $this->uri_string = substr($this->uri_string, 0, -$slen); - } - } - - $this->segments[0] = NULL; - foreach (explode('/', trim($this->uri_string, '/')) as $segment) - { - $segment = trim($segment); - // Filter segments for security - $this->filter_uri($segment); - - if ($segment !== '') - { - $this->segments[] = $segment; - } - } - - unset($this->segments[0]); } // -------------------------------------------------------------------- diff --git a/system/core/Utf8.php b/system/core/Utf8.php index 39954c42850..9ee63e92913 100644 --- a/system/core/Utf8.php +++ b/system/core/Utf8.php @@ -57,21 +57,21 @@ class CI_Utf8 { * * @return void */ - public function __construct($charset) + public function __construct() { if ( - defined('PREG_BAD_UTF8_ERROR') // PCRE must support UTF-8 - && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) // iconv or mbstring must be installed - && $charset === 'UTF-8' // Application charset must be UTF-8 - ) + defined('PREG_BAD_UTF8_ERROR') // PCRE must support UTF-8 + && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) // iconv or mbstring must be installed + && strtoupper(config_item('charset')) === 'UTF-8' // Application charset must be UTF-8 + ) { define('UTF8_ENABLED', TRUE); - log_message('info', 'UTF-8 Support Enabled'); + log_message('debug', 'UTF-8 Support Enabled'); } else { define('UTF8_ENABLED', FALSE); - log_message('info', 'UTF-8 Support Disabled'); + log_message('debug', 'UTF-8 Support Disabled'); } log_message('info', 'Utf8 Class Initialized'); diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php index 8d905ad6841..8f5510c3f48 100644 --- a/system/core/compat/hash.php +++ b/system/core/compat/hash.php @@ -45,7 +45,7 @@ * @category Compatibility * @author Andrey Andreev * @link https://codeigniter.com/user_guide/ - * @link https://secure.php.net/hash + * @link http://php.net/hash */ // ------------------------------------------------------------------------ @@ -62,7 +62,7 @@ /** * hash_equals() * - * @link https://secure.php.net/hash_equals + * @link http://php.net/hash_equals * @param string $known_string * @param string $user_string * @return bool @@ -108,7 +108,7 @@ function hash_equals($known_string, $user_string) /** * hash_pbkdf2() * - * @link https://secure.php.net/hash_pbkdf2 + * @link http://php.net/hash_pbkdf2 * @param string $algo * @param string $password * @param string $salt @@ -205,6 +205,8 @@ function hash_pbkdf2($algo, $password, $salt, $iterations, $length = 0, $raw_out 'ripemd160' => 64, 'ripemd256' => 64, 'ripemd320' => 64, + 'salsa10' => 64, + 'salsa20' => 64, 'sha1' => 64, 'sha224' => 64, 'sha256' => 64, diff --git a/system/core/compat/index.html b/system/core/compat/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/core/compat/index.html +++ b/system/core/compat/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php index 41c86376c5c..552e727192c 100644 --- a/system/core/compat/mbstring.php +++ b/system/core/compat/mbstring.php @@ -45,7 +45,7 @@ * @category Compatibility * @author Andrey Andreev * @link https://codeigniter.com/user_guide/ - * @link https://secure.php.net/mbstring + * @link http://php.net/mbstring */ // ------------------------------------------------------------------------ @@ -65,7 +65,7 @@ * WARNING: This function WILL fall-back to strlen() * if iconv is not available! * - * @link https://secure.php.net/mb_strlen + * @link http://php.net/mb_strlen * @param string $str * @param string $encoding * @return int @@ -92,7 +92,7 @@ function mb_strlen($str, $encoding = NULL) * WARNING: This function WILL fall-back to strpos() * if iconv is not available! * - * @link https://secure.php.net/mb_strpos + * @link http://php.net/mb_strpos * @param string $haystack * @param string $needle * @param int $offset @@ -121,7 +121,7 @@ function mb_strpos($haystack, $needle, $offset = 0, $encoding = NULL) * WARNING: This function WILL fall-back to substr() * if iconv is not available. * - * @link https://secure.php.net/mb_substr + * @link http://php.net/mb_substr * @param string $str * @param int $start * @param int $length diff --git a/system/core/compat/password.php b/system/core/compat/password.php index f6517b46dee..5a3bc207624 100644 --- a/system/core/compat/password.php +++ b/system/core/compat/password.php @@ -45,7 +45,7 @@ * @category Compatibility * @author Andrey Andreev * @link https://codeigniter.com/user_guide/ - * @link https://secure.php.net/password + * @link http://php.net/password */ // ------------------------------------------------------------------------ @@ -67,7 +67,7 @@ /** * password_get_info() * - * @link https://secure.php.net/password_get_info + * @link http://php.net/password_get_info * @param string $hash * @return array */ @@ -86,7 +86,7 @@ function password_get_info($hash) /** * password_hash() * - * @link https://secure.php.net/password_hash + * @link http://php.net/password_hash * @param string $password * @param int $algo * @param array $options @@ -141,7 +141,7 @@ function password_hash($password, $algo, array $options = array()) } // Try not to waste entropy ... - stream_set_chunk_size($fp, 16); + is_php('5.4') && stream_set_chunk_size($fp, 16); $options['salt'] = ''; for ($read = 0; $read < 16; $read = ($func_overload) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) @@ -194,7 +194,7 @@ function password_hash($password, $algo, array $options = array()) /** * password_needs_rehash() * - * @link https://secure.php.net/password_needs_rehash + * @link http://php.net/password_needs_rehash * @param string $hash * @param int $algo * @param array $options @@ -228,7 +228,7 @@ function password_needs_rehash($hash, $algo, array $options = array()) /** * password_verify() * - * @link https://secure.php.net/password_verify + * @link http://php.net/password_verify * @param string $password * @param string $hash * @return bool diff --git a/system/core/compat/standard.php b/system/core/compat/standard.php index 31c39ca257e..2c528fd7cfb 100644 --- a/system/core/compat/standard.php +++ b/system/core/compat/standard.php @@ -61,7 +61,7 @@ /** * array_column() * - * @link https://secure.php.net/array_column + * @link http://php.net/array_column * @param array $array * @param mixed $column_key * @param mixed $index_key @@ -132,3 +132,51 @@ function array_column(array $array, $column_key, $index_key = NULL) return $result; } } + +// ------------------------------------------------------------------------ + +if (is_php('5.4')) +{ + return; +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('hex2bin')) +{ + /** + * hex2bin() + * + * @link http://php.net/hex2bin + * @param string $data + * @return string + */ + function hex2bin($data) + { + if (in_array($type = gettype($data), array('array', 'double', 'object', 'resource'), TRUE)) + { + if ($type === 'object' && method_exists($data, '__toString')) + { + $data = (string) $data; + } + else + { + trigger_error('hex2bin() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING); + return NULL; + } + } + + if (strlen($data) % 2 !== 0) + { + trigger_error('Hexadecimal input string must have an even length', E_USER_WARNING); + return FALSE; + } + elseif ( ! preg_match('/^[0-9a-f]*$/i', $data)) + { + trigger_error('Input string must be hexadecimal string', E_USER_WARNING); + return FALSE; + } + + return pack('H*', $data); + } +} diff --git a/system/core/index.html b/system/core/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/core/index.html +++ b/system/core/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/DB.php b/system/database/DB.php index 5582127186b..68ea22c43c6 100644 --- a/system/database/DB.php +++ b/system/database/DB.php @@ -82,7 +82,7 @@ function &DB($params = '', $query_builder_override = NULL) } } - if (empty($db)) + if ( ! isset($db) OR count($db) === 0) { show_error('No database connection settings were found in the database config file.'); } @@ -192,13 +192,10 @@ class CI_DB extends CI_DB_driver { } // Load the DB driver $driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php'; + file_exists($driver_file) OR show_error('Invalid DB driver'); require_once($driver_file); - // Load the result classes as well - require_once(BASEPATH.'database/DB_result.php'); - require_once(BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_result.php'); - // Instantiate the DB adapter $driver = 'CI_DB_'.$params['dbdriver'].'_driver'; $DB = new $driver($params); diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index f3433f849fe..eee9ef20fe8 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -380,8 +380,7 @@ public function __construct($params) /** * Initialize Database Settings * - * @return void - * @throws RuntimeException In case of failure + * @return bool */ public function initialize() { @@ -393,7 +392,7 @@ public function initialize() */ if ($this->conn_id) { - return; + return TRUE; } // ---------------------------------------------------------------- @@ -430,9 +429,19 @@ public function initialize() // We still don't have a connection? if ( ! $this->conn_id) { - throw new RuntimeException('Unable to connect to the database.'); + log_message('error', 'Unable to connect to the database'); + + if ($this->db_debug) + { + $this->display_error('db_unable_to_connect'); + } + + return FALSE; } } + + // Now we set the character set and that's all + return $this->db_set_charset($this->char_set); } // -------------------------------------------------------------------- @@ -507,6 +516,31 @@ public function error() // -------------------------------------------------------------------- + /** + * Set client character set + * + * @param string + * @return bool + */ + public function db_set_charset($charset) + { + if (method_exists($this, '_db_set_charset') && ! $this->_db_set_charset($charset)) + { + log_message('error', 'Unable to set database connection charset: '.$charset); + + if ($this->db_debug) + { + $this->display_error('db_unable_to_set_charset', $charset); + } + + return FALSE; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + /** * The name of the platform in use (mysql, mssql, etc...) * @@ -600,6 +634,7 @@ public function query($sql, $binds = FALSE, $return_object = NULL) // cached query if it exists if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init()) { + $this->load_rdriver(); if (FALSE !== ($cache = $this->CACHE->read($sql))) { return $cache; @@ -683,9 +718,9 @@ public function query($sql, $binds = FALSE, $return_object = NULL) return TRUE; } - // Instantiate the driver-specific result class - $driver = 'CI_DB_'.$this->dbdriver.'_result'; - $RES = new $driver($this); + // Load and instantiate the result driver + $driver = $this->load_rdriver(); + $RES = new $driver($this); // Is query caching enabled? If so, we'll serialize the // result object and save it to a cache file. @@ -714,6 +749,26 @@ public function query($sql, $binds = FALSE, $return_object = NULL) // -------------------------------------------------------------------- + /** + * Load the result drivers + * + * @return string the name of the result class + */ + public function load_rdriver() + { + $driver = 'CI_DB_'.$this->dbdriver.'_result'; + + if ( ! class_exists($driver, FALSE)) + { + require_once(BASEPATH.'database/DB_result.php'); + require_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php'); + } + + return $driver; + } + + // -------------------------------------------------------------------- + /** * Simple Query * This is a simplified version of the query() function. Internally @@ -725,7 +780,14 @@ public function query($sql, $binds = FALSE, $return_object = NULL) */ public function simple_query($sql) { - empty($this->conn_id) && $this->initialize(); + if ( ! $this->conn_id) + { + if ( ! $this->initialize()) + { + return FALSE; + } + } + return $this->_execute($sql); } @@ -1327,11 +1389,10 @@ public function field_data($table) * * This function escapes column and table names * - * @param mixed $item Identifier to escape - * @param bool $split Whether to split identifiers when a dot is encountered + * @param mixed * @return mixed */ - public function escape_identifiers($item, $split = TRUE) + public function escape_identifiers($item) { if ($this->_escape_char === '' OR empty($item) OR in_array($item, $this->_reserved_identifiers)) { @@ -1352,22 +1413,22 @@ public function escape_identifiers($item, $split = TRUE) return $item; } - static $preg_ec; + static $preg_ec = array(); if (empty($preg_ec)) { if (is_array($this->_escape_char)) { $preg_ec = array( - preg_quote($this->_escape_char[0]), - preg_quote($this->_escape_char[1]), + preg_quote($this->_escape_char[0], '/'), + preg_quote($this->_escape_char[1], '/'), $this->_escape_char[0], $this->_escape_char[1] ); } else { - $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char); + $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/'); $preg_ec[2] = $preg_ec[3] = $this->_escape_char; } } @@ -1376,13 +1437,11 @@ public function escape_identifiers($item, $split = TRUE) { if (strpos($item, '.'.$id) !== FALSE) { - return preg_replace('#'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\.#i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item); + return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item); } } - $dot = ($split !== FALSE) ? '\.' : ''; - - return preg_replace('#'.$preg_ec[0].'?([^'.$preg_ec[1].$dot.']+)'.$preg_ec[1].'?(\.)?#i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item); + return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item); } // -------------------------------------------------------------------- @@ -1796,14 +1855,14 @@ public function protect_identifiers($item, $prefix_single = FALSE, $protect_iden if ($offset = strripos($item, ' AS ')) { $alias = ($protect_identifiers) - ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4), FALSE) + ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4)) : substr($item, $offset); $item = substr($item, 0, $offset); } elseif ($offset = strrpos($item, ' ')) { $alias = ($protect_identifiers) - ? ' '.$this->escape_identifiers(substr($item, $offset + 1), FALSE) + ? ' '.$this->escape_identifiers(substr($item, $offset + 1)) : substr($item, $offset); $item = substr($item, 0, $offset); } diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index b086f7a8130..85b58fdeb83 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -895,33 +895,21 @@ protected function _attr_default(&$attributes, &$field) return; } - if ( ! array_key_exists('DEFAULT', $attributes)) + if (array_key_exists('DEFAULT', $attributes)) { - return; - } - - if ($attributes['DEFAULT'] === NULL) - { - $field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null; - - // Override the NULL attribute if that's our default - $attributes['NULL'] = TRUE; - $field['null'] = empty($this->_null) ? '' : ' '.$this->_null; - return; - } + if ($attributes['DEFAULT'] === NULL) + { + $field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null; - // White-list CURRENT_TIMESTAMP & similar (e.g. Oracle has stuff like SYSTIMESTAMP) defaults for date/time fields - if ( - isset($attributes['TYPE']) - && (stripos($attributes['TYPE'], 'time') !== FALSE OR stripos($attributes['TYPE'], 'date') !== FALSE) - && (stripos($attributes['DEFAULT'], 'time') !== FALSE OR stripos($attributes['DEFAULT'], 'date') !== FALSE) - ) - { - $field['default'] = $this->_default.$attributes['DEFAULT']; - return; + // Override the NULL attribute if that's our default + $attributes['NULL'] = TRUE; + $field['null'] = empty($this->_null) ? '' : ' '.$this->_null; + } + else + { + $field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']); + } } - - $field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']); } // -------------------------------------------------------------------- diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 357a2e35930..6f64c62ae27 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -525,8 +525,19 @@ public function from($from) */ public function join($table, $cond, $type = '', $escape = NULL) { - $type = trim(strtoupper($type).' JOIN'); - preg_match('#^(NATURAL\s+)?((LEFT|RIGHT|FULL)\s+)?((INNER|OUTER)\s+)?JOIN$#', $type) OR $type = 'JOIN'; + if ($type !== '') + { + $type = strtoupper(trim($type)); + + if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER', 'FULL OUTER', 'FULL'), TRUE)) + { + $type = ''; + } + else + { + $type .= ' '; + } + } // Extract any aliases that might exist. We use this information // in the protect_identifiers to know whether to add a table prefix @@ -534,11 +545,7 @@ public function join($table, $cond, $type = '', $escape = NULL) is_bool($escape) OR $escape = $this->_protect_identifiers; - if (strpos($type, 'NATURAL') === 0) - { - $cond = ''; - } - elseif ( ! $this->_has_operator($cond)) + if ( ! $this->_has_operator($cond)) { $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')'; } @@ -587,7 +594,7 @@ public function join($table, $cond, $type = '', $escape = NULL) } // Assemble the JOIN statement - $this->qb_join[] = $join = $type.' '.$table.$cond; + $this->qb_join[] = $join = $type.'JOIN '.$table.$cond; if ($this->qb_caching === TRUE) { @@ -717,9 +724,9 @@ protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = N * @param bool $escape * @return CI_DB_query_builder */ - public function where_in($key, array $values, $escape = NULL) + public function where_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_wh_in('qb_where', $key, $values, FALSE, 'AND ', $escape); + return $this->_where_in($key, $values, FALSE, 'AND ', $escape); } // -------------------------------------------------------------------- @@ -735,9 +742,9 @@ public function where_in($key, array $values, $escape = NULL) * @param bool $escape * @return CI_DB_query_builder */ - public function or_where_in($key, array $values, $escape = NULL) + public function or_where_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_wh_in('qb_where', $key, $values, FALSE, 'OR ', $escape); + return $this->_where_in($key, $values, FALSE, 'OR ', $escape); } // -------------------------------------------------------------------- @@ -753,9 +760,9 @@ public function or_where_in($key, array $values, $escape = NULL) * @param bool $escape * @return CI_DB_query_builder */ - public function where_not_in($key, array $values, $escape = NULL) + public function where_not_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_wh_in('qb_where', $key, $values, TRUE, 'AND ', $escape); + return $this->_where_in($key, $values, TRUE, 'AND ', $escape); } // -------------------------------------------------------------------- @@ -771,98 +778,21 @@ public function where_not_in($key, array $values, $escape = NULL) * @param bool $escape * @return CI_DB_query_builder */ - public function or_where_not_in($key, array $values, $escape = NULL) - { - return $this->_wh_in('qb_where', $key, $values, TRUE, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * HAVING IN - * - * Generates a HAVING field IN('item', 'item') SQL query, - * joined with 'AND' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function having_in($key, array $values, $escape = NULL) - { - return $this->_wh_in('qb_having', $key, $values, FALSE, 'AND ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR HAVING IN - * - * Generates a HAVING field IN('item', 'item') SQL query, - * joined with 'OR' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_having_in($key, array $values, $escape = NULL) - { - return $this->_wh_in('qb_having', $key, $values, FALSE, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * HAVING NOT IN - * - * Generates a HAVING field NOT IN('item', 'item') SQL query, - * joined with 'AND' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function having_not_in($key, array $values, $escape = NULL) + public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL) { - return $this->_wh_in('qb_having', $key, $values, TRUE, 'AND ', $escape); + return $this->_where_in($key, $values, TRUE, 'OR ', $escape); } // -------------------------------------------------------------------- /** - * OR HAVING NOT IN - * - * Generates a HAVING field NOT IN('item', 'item') SQL query, - * joined with 'OR' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_having_not_in($key, array $values, $escape = NULL) - { - return $this->_wh_in('qb_having', $key, $values, TRUE, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * Internal WHERE/HAVING IN + * Internal WHERE IN * * @used-by where_in() * @used-by or_where_in() * @used-by where_not_in() * @used-by or_where_not_in() - * @used-by having_in() - * @used-by or_having_in() - * @used-by having_not_in() - * @used-by or_having_not_in() * - * @param string $qb_key 'qb_where' or 'qb_having' * @param string $key The field to search * @param array $values The values searched on * @param bool $not If the statement would be IN or NOT IN @@ -870,18 +800,16 @@ public function or_having_not_in($key, array $values, $escape = NULL) * @param bool $escape * @return CI_DB_query_builder */ - protected function _wh_in($qb_key, $key, array $values, $not = FALSE, $type = 'AND ', $escape = NULL) + protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL) { - $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where'; - - if (empty($key) OR ! is_string($key)) + if ($key === NULL OR $values === NULL) { - throw new InvalidArgumentException(sprintf('%s() expects $key to be a non-empty string', debug_backtrace(0, 2)[1]['function'])); + return $this; } - if (empty($values)) + if ( ! is_array($values)) { - throw new InvalidArgumentException(sprintf('%s() expects $values to be a non-empty array', debug_backtrace(0, 2)[1]['function'])); + $values = array($values); } is_bool($escape) OR $escape = $this->_protect_identifiers; @@ -890,32 +818,32 @@ protected function _wh_in($qb_key, $key, array $values, $not = FALSE, $type = 'A if ($escape === TRUE) { - $wh_in = array(); + $where_in = array(); foreach ($values as $value) { - $wh_in[] = $this->escape($value); + $where_in[] = $this->escape($value); } } else { - $wh_in = array_values($values); + $where_in = array_values($values); } - $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0) + $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type); - $wh_in = array( - 'condition' => $prefix.$key.$not.' IN('.implode(', ', $wh_in).')', + $where_in = array( + 'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')', 'value' => NULL, 'escape' => $escape ); - $this->{$qb_key}[] = $wh_in; + $this->qb_where[] = $where_in; if ($this->qb_caching === TRUE) { - $this->{$qb_cache_key}[] = $wh_in; - $this->qb_cache_exists[] = substr($qb_key, 3); + $this->qb_cache_where[] = $where_in; + $this->qb_cache_exists[] = 'where'; } return $this; diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php index c2edfc9f378..6642fda8f66 100644 --- a/system/database/DB_utility.php +++ b/system/database/DB_utility.php @@ -235,8 +235,13 @@ public function repair_table($table_name) * @param string $enclosure Enclosure (default: ") * @return string */ - public function csv_from_result(CI_DB_result $query, $delim = ',', $newline = "\n", $enclosure = '"') + public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"') { + if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) + { + show_error('You must submit a valid result object'); + } + $out = ''; // First generate the headings from the table column names foreach ($query->list_fields() as $name) @@ -269,8 +274,13 @@ public function csv_from_result(CI_DB_result $query, $delim = ',', $newline = "\ * @param array $params Any preferences * @return string */ - public function xml_from_result(CI_DB_result $query, $params = array()) + public function xml_from_result($query, $params = array()) { + if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) + { + show_error('You must submit a valid result object'); + } + // Set our default values foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val) { diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/cubrid/index.html +++ b/system/database/drivers/cubrid/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/ibase/index.html b/system/database/drivers/ibase/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/ibase/index.html +++ b/system/database/drivers/ibase/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/index.html b/system/database/drivers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/index.html +++ b/system/database/drivers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/mssql/index.html b/system/database/drivers/mssql/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/mssql/index.html +++ b/system/database/drivers/mssql/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php index 51352e31427..e197cfb028f 100644 --- a/system/database/drivers/mssql/mssql_driver.php +++ b/system/database/drivers/mssql/mssql_driver.php @@ -108,7 +108,6 @@ public function __construct($params) */ public function db_connect($persistent = FALSE) { - ini_set('mssql.charset', $this->char_set); $this->conn_id = ($persistent) ? mssql_pconnect($this->hostname, $this->username, $this->password) : mssql_connect($this->hostname, $this->username, $this->password); @@ -249,6 +248,19 @@ public function insert_id() // -------------------------------------------------------------------- + /** + * Set client character set + * + * @param string $charset + * @return bool + */ + protected function _db_set_charset($charset) + { + return (ini_set('mssql.charset', $charset) !== FALSE); + } + + // -------------------------------------------------------------------- + /** * Version number query string * diff --git a/system/database/drivers/mysql/index.html b/system/database/drivers/mysql/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/mysql/index.html +++ b/system/database/drivers/mysql/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php index bdd80092c1d..440715ae16b 100644 --- a/system/database/drivers/mysql/mysql_driver.php +++ b/system/database/drivers/mysql/mysql_driver.php @@ -147,41 +147,29 @@ public function db_connect($persistent = FALSE) : FALSE; } - if (is_resource($this->conn_id)) + if (isset($this->stricton) && is_resource($this->conn_id)) { - if ( ! mysql_set_charset($this->char_set, $this->conn_id)) + if ($this->stricton) { - log_message('error', "Database: Unable to set the configured connection charset ('{$this->char_set}')."); - $this->close(); - return ($this->db->debug) ? $this->display_error('db_unable_to_set_charset', $this->char_set) : FALSE; + $this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")'); } - - if (isset($this->stricton)) + else { - if ($this->stricton) - { - $this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")'); - } - else - { - $this->simple_query( - 'SET SESSION sql_mode = - REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( - @@sql_mode, - "STRICT_ALL_TABLES,", ""), - ",STRICT_ALL_TABLES", ""), - "STRICT_ALL_TABLES", ""), - "STRICT_TRANS_TABLES,", ""), - ",STRICT_TRANS_TABLES", ""), - "STRICT_TRANS_TABLES", "")' - ); - } + $this->simple_query( + 'SET SESSION sql_mode = + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( + @@sql_mode, + "STRICT_ALL_TABLES,", ""), + ",STRICT_ALL_TABLES", ""), + "STRICT_ALL_TABLES", ""), + "STRICT_TRANS_TABLES,", ""), + ",STRICT_TRANS_TABLES", ""), + "STRICT_TRANS_TABLES", "")' + ); } - - return $this->conn_id; } - return FALSE; + return $this->conn_id; } // -------------------------------------------------------------------- @@ -229,6 +217,19 @@ public function db_select($database = '') // -------------------------------------------------------------------- + /** + * Set client character set + * + * @param string $charset + * @return bool + */ + protected function _db_set_charset($charset) + { + return mysql_set_charset($charset, $this->conn_id); + } + + // -------------------------------------------------------------------- + /** * Database version number * diff --git a/system/database/drivers/mysqli/index.html b/system/database/drivers/mysqli/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/mysqli/index.html +++ b/system/database/drivers/mysqli/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php index 6553a271f9f..0ca0f48fc92 100644 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ b/system/database/drivers/mysqli/mysqli_driver.php @@ -215,13 +215,6 @@ public function db_connect($persistent = FALSE) return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE; } - if ( ! $this->_mysqli->set_charset($this->char_set)) - { - log_message('error', "Database: Unable to set the configured connection charset ('{$this->char_set}')."); - $this->_mysqli->close(); - return ($this->db->db_debug) ? $this->display_error('db_unable_to_set_charset', $this->char_set) : FALSE; - } - return $this->_mysqli; } @@ -273,6 +266,19 @@ public function db_select($database = '') // -------------------------------------------------------------------- + /** + * Set client character set + * + * @param string $charset + * @return bool + */ + protected function _db_set_charset($charset) + { + return $this->conn_id->set_charset($charset); + } + + // -------------------------------------------------------------------- + /** * Database version number * diff --git a/system/database/drivers/oci8/index.html b/system/database/drivers/oci8/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/oci8/index.html +++ b/system/database/drivers/oci8/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/odbc/index.html b/system/database/drivers/odbc/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/odbc/index.html +++ b/system/database/drivers/odbc/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/pdo/index.html b/system/database/drivers/pdo/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/pdo/index.html +++ b/system/database/drivers/pdo/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/pdo/subdrivers/index.html +++ b/system/database/drivers/pdo/subdrivers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php index 2d0c74b2e79..a848c65d8b5 100644 --- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php +++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php @@ -255,7 +255,7 @@ protected function _list_columns($table = '') { return 'SELECT "column_name" FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); + WHERE "table_schema" = \''.$this->schema.'\' AND LOWER("table_name") = '.$this->escape(strtolower($table)); } // -------------------------------------------------------------------- @@ -270,7 +270,7 @@ public function field_data($table) { $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default" FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); + WHERE "table_schema" = \''.$this->schema.'\' AND LOWER("table_name") = '.$this->escape(strtolower($table)); if (($query = $this->query($sql)) === FALSE) { diff --git a/system/database/drivers/postgre/index.html b/system/database/drivers/postgre/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/postgre/index.html +++ b/system/database/drivers/postgre/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php index 19a09490c56..19bd775d079 100644 --- a/system/database/drivers/postgre/postgre_driver.php +++ b/system/database/drivers/postgre/postgre_driver.php @@ -163,13 +163,6 @@ public function db_connect($persistent = FALSE) return FALSE; } - if (pg_set_client_encoding($this->conn_id, $this->char_set) !== 0) - { - log_message('error', "Database: Unable to set the configured connection charset ('{$this->char_set}')."); - pg_close($this->conn_id); - return ($this->db->db_debug) ? $this->display_error('db_unable_to_set_charset', $this->char_set) : FALSE; - } - empty($this->schema) OR $this->simple_query('SET search_path TO '.$this->schema.',public'); } @@ -196,6 +189,19 @@ public function reconnect() // -------------------------------------------------------------------- + /** + * Set client character set + * + * @param string $charset + * @return bool + */ + protected function _db_set_charset($charset) + { + return (pg_set_client_encoding($this->conn_id, $charset) === 0); + } + + // -------------------------------------------------------------------- + /** * Database version number * @@ -315,7 +321,7 @@ protected function _escape_str($str) */ public function escape($str) { - if (is_string($str) OR (is_object($str) && method_exists($str, '__toString'))) + if (is_php('5.4.4') && (is_string($str) OR (is_object($str) && method_exists($str, '__toString')))) { return pg_escape_literal($this->conn_id, $str); } @@ -422,7 +428,7 @@ protected function _list_columns($table = '') { return 'SELECT "column_name" FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); + WHERE "table_schema" = \''.$this->schema.'\' AND LOWER("table_name") = '.$this->escape(strtolower($table)); } // -------------------------------------------------------------------- @@ -437,7 +443,7 @@ public function field_data($table) { $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default" FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); + WHERE "table_schema" = \''.$this->schema.'\' AND LOWER("table_name") = '.$this->escape(strtolower($table)); if (($query = $this->query($sql)) === FALSE) { diff --git a/application/views/index.html b/system/database/drivers/sqlite/index.html similarity index 87% rename from application/views/index.html rename to system/database/drivers/sqlite/index.html index bcb7cae3433..b702fbc3967 100644 --- a/application/views/index.html +++ b/system/database/drivers/sqlite/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php new file mode 100644 index 00000000000..aec3d748c14 --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_driver.php @@ -0,0 +1,330 @@ +database, 0666, $error) + : sqlite_open($this->database, 0666, $error); + + isset($error) && log_message('error', $error); + + return $conn_id; + } + + // -------------------------------------------------------------------- + + /** + * Database version number + * + * @return string + */ + public function version() + { + return isset($this->data_cache['version']) + ? $this->data_cache['version'] + : $this->data_cache['version'] = sqlite_libversion(); + } + + // -------------------------------------------------------------------- + + /** + * Execute the query + * + * @param string $sql an SQL query + * @return resource + */ + protected function _execute($sql) + { + return $this->is_write_type($sql) + ? sqlite_exec($this->conn_id, $sql) + : sqlite_query($this->conn_id, $sql); + } + + // -------------------------------------------------------------------- + + /** + * Begin Transaction + * + * @return bool + */ + protected function _trans_begin() + { + return $this->simple_query('BEGIN TRANSACTION'); + } + + // -------------------------------------------------------------------- + + /** + * Commit Transaction + * + * @return bool + */ + protected function _trans_commit() + { + return $this->simple_query('COMMIT'); + } + + // -------------------------------------------------------------------- + + /** + * Rollback Transaction + * + * @return bool + */ + protected function _trans_rollback() + { + return $this->simple_query('ROLLBACK'); + } + + // -------------------------------------------------------------------- + + /** + * Platform-dependant string escape + * + * @param string + * @return string + */ + protected function _escape_str($str) + { + return sqlite_escape_string($str); + } + + // -------------------------------------------------------------------- + + /** + * Affected Rows + * + * @return int + */ + public function affected_rows() + { + return sqlite_changes($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * Insert ID + * + * @return int + */ + public function insert_id() + { + return sqlite_last_insert_rowid($this->conn_id); + } + + // -------------------------------------------------------------------- + + /** + * List table query + * + * Generates a platform-specific query string so that the table names can be fetched + * + * @param bool $prefix_limit + * @return string + */ + protected function _list_tables($prefix_limit = FALSE) + { + $sql = "SELECT name FROM sqlite_master WHERE type='table'"; + + if ($prefix_limit !== FALSE && $this->dbprefix != '') + { + return $sql." AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); + } + + return $sql; + } + + // -------------------------------------------------------------------- + + /** + * Show column query + * + * Generates a platform-specific query string so that the column names can be fetched + * + * @param string $table + * @return bool + */ + protected function _list_columns($table = '') + { + // Not supported + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Returns an object with field data + * + * @param string $table + * @return array + */ + public function field_data($table) + { + if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE) + { + return FALSE; + } + + $query = $query->result_array(); + if (empty($query)) + { + return FALSE; + } + + $retval = array(); + for ($i = 0, $c = count($query); $i < $c; $i++) + { + $retval[$i] = new stdClass(); + $retval[$i]->name = $query[$i]['name']; + $retval[$i]->type = $query[$i]['type']; + $retval[$i]->max_length = NULL; + $retval[$i]->default = $query[$i]['dflt_value']; + $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Error + * + * Returns an array containing code and message of the last + * database error that has occured. + * + * @return array + */ + public function error() + { + $error = array('code' => sqlite_last_error($this->conn_id)); + $error['message'] = sqlite_error_string($error['code']); + return $error; + } + + // -------------------------------------------------------------------- + + /** + * Replace statement + * + * Generates a platform-specific replace string from the supplied data + * + * @param string $table Table name + * @param array $keys INSERT keys + * @param array $values INSERT values + * @return string + */ + protected function _replace($table, $keys, $values) + { + return 'INSERT OR '.parent::_replace($table, $keys, $values); + } + + // -------------------------------------------------------------------- + + /** + * Truncate statement + * + * Generates a platform-specific truncate string from the supplied data + * + * If the database does not support the TRUNCATE statement, + * then this function maps to 'DELETE FROM table' + * + * @param string $table + * @return string + */ + protected function _truncate($table) + { + return 'DELETE FROM '.$table; + } + + // -------------------------------------------------------------------- + + /** + * Close DB Connection + * + * @return void + */ + protected function _close() + { + sqlite_close($this->conn_id); + } + +} diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php new file mode 100644 index 00000000000..6aa9c61c473 --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_forge.php @@ -0,0 +1,205 @@ +db->database) OR ! @unlink($this->db->database)) + { + return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; + } + elseif ( ! empty($this->db->data_cache['db_names'])) + { + $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); + if ($key !== FALSE) + { + unset($this->db->data_cache['db_names'][$key]); + } + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * ALTER TABLE + * + * @todo implement drop_column(), modify_column() + * @param string $alter_type ALTER type + * @param string $table Table name + * @param mixed $field Column definition + * @return string|string[] + */ + protected function _alter_table($alter_type, $table, $field) + { + if ($alter_type === 'DROP' OR $alter_type === 'CHANGE') + { + // drop_column(): + // BEGIN TRANSACTION; + // CREATE TEMPORARY TABLE t1_backup(a,b); + // INSERT INTO t1_backup SELECT a,b FROM t1; + // DROP TABLE t1; + // CREATE TABLE t1(a,b); + // INSERT INTO t1 SELECT a,b FROM t1_backup; + // DROP TABLE t1_backup; + // COMMIT; + + return FALSE; + } + + return parent::_alter_table($alter_type, $table, $field); + } + + // -------------------------------------------------------------------- + + /** + * Process column + * + * @param array $field + * @return string + */ + protected function _process_column($field) + { + return $this->db->escape_identifiers($field['name']) + .' '.$field['type'] + .$field['auto_increment'] + .$field['null'] + .$field['unique'] + .$field['default']; + } + + // -------------------------------------------------------------------- + + /** + * Field attribute TYPE + * + * Performs a data type mapping between different databases. + * + * @param array &$attributes + * @return void + */ + protected function _attr_type(&$attributes) + { + switch (strtoupper($attributes['TYPE'])) + { + case 'ENUM': + case 'SET': + $attributes['TYPE'] = 'TEXT'; + return; + default: return; + } + } + + // -------------------------------------------------------------------- + + /** + * Field attribute AUTO_INCREMENT + * + * @param array &$attributes + * @param array &$field + * @return void + */ + protected function _attr_auto_increment(&$attributes, &$field) + { + if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) + { + $field['type'] = 'INTEGER PRIMARY KEY'; + $field['default'] = ''; + $field['null'] = ''; + $field['unique'] = ''; + $field['auto_increment'] = ' AUTOINCREMENT'; + + $this->primary_keys = array(); + } + } + +} diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php new file mode 100644 index 00000000000..30c93a26fa0 --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_result.php @@ -0,0 +1,164 @@ +num_rows) + ? $this->num_rows + : $this->num_rows = @sqlite_num_rows($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Number of fields in the result set + * + * @return int + */ + public function num_fields() + { + return @sqlite_num_fields($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Fetch Field Names + * + * Generates an array of column names + * + * @return array + */ + public function list_fields() + { + $field_names = array(); + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) + { + $field_names[$i] = sqlite_field_name($this->result_id, $i); + } + + return $field_names; + } + + // -------------------------------------------------------------------- + + /** + * Field data + * + * Generates an array of objects containing field meta-data + * + * @return array + */ + public function field_data() + { + $retval = array(); + for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) + { + $retval[$i] = new stdClass(); + $retval[$i]->name = sqlite_field_name($this->result_id, $i); + $retval[$i]->type = NULL; + $retval[$i]->max_length = NULL; + } + + return $retval; + } + + // -------------------------------------------------------------------- + + /** + * Data Seek + * + * Moves the internal pointer to the desired offset. We call + * this internally before fetching results to make sure the + * result set starts at zero. + * + * @param int $n + * @return bool + */ + public function data_seek($n = 0) + { + return sqlite_seek($this->result_id, $n); + } + + // -------------------------------------------------------------------- + + /** + * Result - associative array + * + * Returns the result set as an array + * + * @return array + */ + protected function _fetch_assoc() + { + return sqlite_fetch_array($this->result_id); + } + + // -------------------------------------------------------------------- + + /** + * Result - object + * + * Returns the result set as an object + * + * @param string $class_name + * @return object + */ + protected function _fetch_object($class_name = 'stdClass') + { + return sqlite_fetch_object($this->result_id, $class_name); + } + +} diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php new file mode 100644 index 00000000000..2c7f8099ecf --- /dev/null +++ b/system/database/drivers/sqlite/sqlite_utility.php @@ -0,0 +1,61 @@ +db->display_error('db_unsupported_feature'); + } + +} diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/sqlite3/index.html +++ b/system/database/drivers/sqlite3/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/drivers/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/drivers/sqlsrv/index.html +++ b/system/database/drivers/sqlsrv/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/database/index.html b/system/database/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/database/index.html +++ b/system/database/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/fonts/index.html b/system/fonts/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/fonts/index.html +++ b/system/fonts/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php index dcd6882c86b..5252d417ced 100644 --- a/system/helpers/captcha_helper.php +++ b/system/helpers/captcha_helper.php @@ -68,11 +68,10 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = 'img_url' => '', 'img_width' => '150', 'img_height' => '30', - 'img_alt' => 'captcha', 'font_path' => '', - 'font_size' => 16, 'expiration' => 7200, 'word_length' => 8, + 'font_size' => 16, 'img_id' => '', 'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 'colors' => array( @@ -83,8 +82,6 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = ) ); - $now = microtime(TRUE); - foreach ($defaults as $key => $val) { if ( ! is_array($data) && empty($$key)) @@ -115,42 +112,24 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = return FALSE; } - if ($img_url !== '' OR $img_path !== '') - { - if ($img_path === '' OR $img_url === '') - { - log_message('error', 'create_captcha(): $img_path and $img_url are required.'); - return FALSE; - } + // ----------------------------------- + // Remove old images + // ----------------------------------- - if ( ! is_dir($img_path) OR ! is_really_writable($img_path)) - { - log_message('error', "create_captcha(): '{$img_path}' is not a dir, nor is it writable."); - return FALSE; - } + $now = microtime(TRUE); - /** - * Remove old images - */ - $current_dir = @opendir($img_path); - while ($filename = @readdir($current_dir)) + $current_dir = @opendir($img_path); + while ($filename = @readdir($current_dir)) + { + if (in_array(substr($filename, -4), array('.jpg', '.png')) + && (str_replace(array('.jpg', '.png'), '', $filename) + $expiration) < $now) { - if (preg_match('#^(?\d{10})\.png$#', $filename, $match) && ($match['ts'] + $expiration) < $now) - { - @unlink($img_path.$filename); - } + @unlink($img_path.$filename); } - - @closedir($current_dir); - - // This variable will later be used later to determine whether we write to disk or output a data:image URI - $img_filename = $now.'.png'; - } - else - { - $img_filename = NULL; } + @closedir($current_dir); + // ----------------------------------- // Do we have a "word" yet? // ----------------------------------- @@ -259,8 +238,8 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = // Determine angle and position // ----------------------------------- $length = strlen($word); - $angle = ($length >= 6) ? mt_rand(-($length - 6), ($length - 6)) : 0; - $x_axis = mt_rand(6, (360 / $length)-16); + $angle = ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0; + $x_axis = mt_rand(6, (360/$length)-16); $y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height); // Create image @@ -348,31 +327,24 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = // ----------------------------------- // Generate the image // ----------------------------------- + $img_url = rtrim($img_url, '/').'/'; - if (isset($img_filename)) + if (function_exists('imagejpeg')) { - $img_src = rtrim($img_url, '/').'/'.$img_filename; + $img_filename = $now.'.jpg'; + imagejpeg($im, $img_path.$img_filename); + } + elseif (function_exists('imagepng')) + { + $img_filename = $now.'.png'; imagepng($im, $img_path.$img_filename); } else { - // I don't see an easier way to get the image contents without writing to file - $buffer = fopen('php://memory', 'wb+'); - imagepng($im, $buffer); - rewind($buffer); - $img_src = ''; - - // fread() will return an empty string (not FALSE) after the entire contents are read - while (strlen($read = fread($buffer, 4096))) - { - $img_src .= $read; - } - - fclose($buffer); - $img_src = 'data:image/png;base64,'.base64_encode($img_src); + return FALSE; } - $img = ''.$img_alt.''; + $img = ' '; ImageDestroy($im); return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename); diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php index d9724932eb0..b9c2cb68a01 100644 --- a/system/helpers/cookie_helper.php +++ b/system/helpers/cookie_helper.php @@ -59,7 +59,7 @@ * * @param mixed * @param string the value of the cookie - * @param int the number of seconds until expiration + * @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 @@ -67,7 +67,7 @@ * @param bool true makes the cookie accessible via http(s) only (no javascript) * @return void */ - function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) + function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) { // Set the config file options get_instance()->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly); @@ -85,8 +85,9 @@ function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', * @param bool * @return mixed */ - function get_cookie($index, $xss_clean = FALSE) + function get_cookie($index, $xss_clean = NULL) { + is_bool($xss_clean) OR $xss_clean = (config_item('global_xss_filtering') === TRUE); $prefix = isset($_COOKIE[$index]) ? '' : config_item('cookie_prefix'); return get_instance()->input->cookie($prefix.$index, $xss_clean); } diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index 6ee3c311989..5c660e2eee3 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -122,6 +122,46 @@ function mdate($datestr = '', $time = '') // ------------------------------------------------------------------------ +if ( ! function_exists('standard_date')) +{ + /** + * Standard Date + * + * Returns a date formatted according to the submitted standard. + * + * As of PHP 5.2, the DateTime extension provides constants that + * serve for the exact same purpose and are used with date(). + * + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 Use PHP's native date() instead. + * @link http://www.php.net/manual/en/class.datetime.php#datetime.constants.types + * + * @example date(DATE_RFC822, now()); // default + * @example date(DATE_W3C, $time); // a different format and time + * + * @param string $fmt = 'DATE_RFC822' the chosen format + * @param int $time = NULL Unix timestamp + * @return string + */ + function standard_date($fmt = 'DATE_RFC822', $time = NULL) + { + if (empty($time)) + { + $time = now(); + } + + // Procedural style pre-defined constants from the DateTime extension + if (strpos($fmt, 'DATE_') !== 0 OR defined($fmt) === FALSE) + { + return FALSE; + } + + return date(constant($fmt), $time); + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('timespan')) { /** diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php index 4d7829640d1..d8e30ae9f63 100644 --- a/system/helpers/download_helper.php +++ b/system/helpers/download_helper.php @@ -56,7 +56,7 @@ * * Generates headers that force a download to happen * - * @param mixed filename (or an array of local file path => destination filename) + * @param string filename * @param mixed the data to be downloaded * @param bool whether to try and send the actual file MIME type * @return void @@ -69,34 +69,14 @@ function force_download($filename = '', $data = '', $set_mime = FALSE) } elseif ($data === NULL) { - // Is $filename an array as ['local source path' => 'destination filename']? - if (is_array($filename)) - { - if (count($filename) !== 1) - { - return; - } - - reset($filename); - $filepath = key($filename); - $filename = current($filename); - - if (is_int($filepath)) - { - return; - } - } - else - { - $filepath = $filename; - $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename)); - $filename = end($filename); - } - - if ( ! @is_file($filepath) OR ($filesize = @filesize($filepath)) === FALSE) + if ( ! @is_file($filename) OR ($filesize = @filesize($filename)) === FALSE) { return; } + + $filepath = $filename; + $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename)); + $filename = end($filename); } else { @@ -141,23 +121,20 @@ function force_download($filename = '', $data = '', $set_mime = FALSE) $filename = implode('.', $x); } + if ($data === NULL && ($fp = @fopen($filepath, 'rb')) === FALSE) + { + return; + } + // Clean output buffer if (ob_get_level() !== 0 && @ob_end_clean() === FALSE) { @ob_clean(); } - // RFC 6266 allows for multibyte filenames, but only in UTF-8, - // so we have to make it conditional ... - $charset = strtoupper(config_item('charset')); - $utf8_filename = ($charset !== 'UTF-8') - ? get_instance()->utf8->convert_to_utf8($filename, $charset) - : $filename; - isset($utf8_filename[0]) && $utf8_filename = " filename*=UTF-8''".rawurlencode($utf8_filename); - // Generate the server headers header('Content-Type: '.$mime); - header('Content-Disposition: attachment; filename="'.$filename.'";'.$utf8_filename); + header('Content-Disposition: attachment; filename="'.$filename.'"'); header('Expires: 0'); header('Content-Transfer-Encoding: binary'); header('Content-Length: '.$filesize); @@ -169,12 +146,13 @@ function force_download($filename = '', $data = '', $set_mime = FALSE) exit($data); } - // Flush the file - if (@readfile($filepath) === FALSE) + // Flush 1MB chunks of data + while ( ! feof($fp) && ($data = fread($fp, 1048576)) !== FALSE) { - return; + echo $data; } + fclose($fp); exit; } } diff --git a/system/helpers/email_helper.php b/system/helpers/email_helper.php new file mode 100644 index 00000000000..b25875974d3 --- /dev/null +++ b/system/helpers/email_helper.php @@ -0,0 +1,84 @@ + 'file', 'name' => ''); is_array($data) OR $data = array('name' => $data); @@ -675,6 +676,25 @@ function form_close($extra = '') // ------------------------------------------------------------------------ +if ( ! function_exists('form_prep')) +{ + /** + * Form Prep + * + * Formats text so that it can be safely placed in a form field in the event it has HTML tags. + * + * @deprecated 3.0.0 An alias for html_escape() + * @param string|string[] $str Value to escape + * @return string|string[] Escaped values + */ + function form_prep($str) + { + return html_escape($str, TRUE); + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('set_value')) { /** diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php index 8b06e4406a2..76adcb23623 100644 --- a/system/helpers/html_helper.php +++ b/system/helpers/html_helper.php @@ -229,7 +229,7 @@ function img($src = '', $index_page = FALSE, $attributes = '') * @param string type The doctype to be generated * @return string */ - function doctype($type = 'html5') + function doctype($type = 'xhtml1-strict') { static $doctypes; @@ -360,32 +360,51 @@ function meta($name = '', $content = '', $type = 'name', $newline = "\n") $name = array($name); } - $allowed_types = array('charset', 'http-equiv', 'name', 'property'); $str = ''; foreach ($name as $meta) { - // This is to preserve BC with pre-3.1 versions where only - // 'http-equiv' (default) and 'name' were supported. - if (isset($meta['type'])) - { - if ($meta['type'] === 'equiv') - { - $meta['type'] = 'http-equiv'; - } - elseif ( ! in_array($meta['type'], $allowed_types, TRUE)) - { - $meta['type'] = 'name'; - } - } + $type = (isset($meta['type']) && $meta['type'] !== 'name') ? 'http-equiv' : 'name'; + $name = isset($meta['name']) ? $meta['name'] : ''; + $content = isset($meta['content']) ? $meta['content'] : ''; + $newline = isset($meta['newline']) ? $meta['newline'] : "\n"; - $type = isset($meta['type']) ? $meta['type'] : 'name'; - $name = isset($meta['name']) ? $meta['name'] : ''; - $content = isset($meta['content']) ? $meta['content'] : ''; - $newline = isset($meta['newline']) ? $meta['newline'] : "\n"; - - $str .= ''.$newline; + $str .= ''.$newline; } return $str; } } + +// ------------------------------------------------------------------------ + +if ( ! function_exists('br')) +{ + /** + * Generates HTML BR tags based on number supplied + * + * @deprecated 3.0.0 Use str_repeat() instead + * @param int $count Number of times to repeat the tag + * @return string + */ + function br($count = 1) + { + return str_repeat('
', $count); + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('nbs')) +{ + /** + * Generates non-breaking space entities based on number supplied + * + * @deprecated 3.0.0 Use str_repeat() instead + * @param int + * @return string + */ + function nbs($num = 1) + { + return str_repeat(' ', $num); + } +} diff --git a/system/helpers/index.html b/system/helpers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/helpers/index.html +++ b/system/helpers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index a36836b0094..1c14f4a3e4e 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -285,42 +285,3 @@ function is_countable($word) return word_is_countable($word); } } - -// ------------------------------------------------------------------------ - -if ( ! function_exists('ordinal_format')) -{ - /** - * Returns the English ordinal numeral for a given number - * - * @param int $number - * @return string - */ - function ordinal_format($number) - { - if ( ! ctype_digit((string) $number) OR $number < 1) - { - return $number; - } - - $last_digit = array( - 0 => 'th', - 1 => 'st', - 2 => 'nd', - 3 => 'rd', - 4 => 'th', - 5 => 'th', - 6 => 'th', - 7 => 'th', - 8 => 'th', - 9 => 'th' - ); - - if (($number % 100) >= 11 && ($number % 100) <= 13) - { - return $number.'th'; - } - - return $number.$last_digit[$number % 10]; - } -} diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php index dcf5b8b5813..b931c339356 100644 --- a/system/helpers/security_helper.php +++ b/system/helpers/security_helper.php @@ -80,6 +80,30 @@ function sanitize_filename($filename) } } +// -------------------------------------------------------------------- + +if ( ! function_exists('do_hash')) +{ + /** + * Hash encode a string + * + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 Use PHP's native hash() instead. + * @param string $str + * @param string $type = 'sha1' + * @return string + */ + function do_hash($str, $type = 'sha1') + { + if ( ! in_array(strtolower($type), hash_algos())) + { + $type = 'md5'; + } + + return hash($type, $str); + } +} + // ------------------------------------------------------------------------ if ( ! function_exists('strip_image_tags')) diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php new file mode 100644 index 00000000000..321e59cefc4 --- /dev/null +++ b/system/helpers/smiley_helper.php @@ -0,0 +1,255 @@ +field_id pairs + * @param string field_id if alias name was passed in + * @param bool + * @return array + */ + function smiley_js($alias = '', $field_id = '', $inline = TRUE) + { + static $do_setup = TRUE; + $r = ''; + + if ($alias !== '' && ! is_array($alias)) + { + $alias = array($alias => $field_id); + } + + if ($do_setup === TRUE) + { + $do_setup = FALSE; + $m = array(); + + if (is_array($alias)) + { + foreach ($alias as $name => $id) + { + $m[] = '"'.$name.'" : "'.$id.'"'; + } + } + + $m = '{'.implode(',', $m).'}'; + + $r .= << $id) + { + $r .= 'smiley_map["'.$name.'"] = "'.$id."\";\n"; + } + } + + return ($inline) + ? '' + : $r; + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('get_clickable_smileys')) +{ + /** + * Get Clickable Smileys + * + * Returns an array of image tag links that can be clicked to be inserted + * into a form field. + * + * @param string the URL to the folder containing the smiley images + * @param array + * @return array + */ + function get_clickable_smileys($image_url, $alias = '') + { + // For backward compatibility with js_insert_smiley + if (is_array($alias)) + { + $smileys = $alias; + } + elseif (FALSE === ($smileys = _get_smiley_array())) + { + return FALSE; + } + + // Add a trailing slash to the file path if needed + $image_url = rtrim($image_url, '/').'/'; + + $used = array(); + foreach ($smileys as $key => $val) + { + // Keep duplicates from being used, which can happen if the + // mapping array contains multiple identical replacements. For example: + // :-) and :) might be replaced with the same image so both smileys + // will be in the array. + if (isset($used[$smileys[$key][0]])) + { + continue; + } + + $link[] = ''.$smileys[$key][3].''; + $used[$smileys[$key][0]] = TRUE; + } + + return $link; + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('parse_smileys')) +{ + /** + * Parse Smileys + * + * Takes a string as input and swaps any contained smileys for the actual image + * + * @param string the text to be parsed + * @param string the URL to the folder containing the smiley images + * @param array + * @return string + */ + function parse_smileys($str = '', $image_url = '', $smileys = NULL) + { + if ($image_url === '' OR ( ! is_array($smileys) && FALSE === ($smileys = _get_smiley_array()))) + { + return $str; + } + + // Add a trailing slash to the file path if needed + $image_url = rtrim($image_url, '/').'/'; + + foreach ($smileys as $key => $val) + { + $str = str_replace($key, ''.$smileys[$key][3].'', $str); + } + + return $str; + } +} + +// ------------------------------------------------------------------------ + +if ( ! function_exists('_get_smiley_array')) +{ + /** + * Get Smiley Array + * + * Fetches the config/smiley.php file + * + * @return mixed + */ + function _get_smiley_array() + { + static $_smileys; + + if ( ! is_array($_smileys)) + { + if (file_exists(APPPATH.'config/smileys.php')) + { + include(APPPATH.'config/smileys.php'); + } + + if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys.php')) + { + include(APPPATH.'config/'.ENVIRONMENT.'/smileys.php'); + } + + if (empty($smileys) OR ! is_array($smileys)) + { + $_smileys = array(); + return FALSE; + } + + $_smileys = $smileys; + } + + return $_smileys; + } +} diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php index 7738bf97f9b..c7dd96977f0 100644 --- a/system/helpers/string_helper.php +++ b/system/helpers/string_helper.php @@ -49,6 +49,33 @@ // ------------------------------------------------------------------------ +if ( ! function_exists('trim_slashes')) +{ + /** + * Trim Slashes + * + * Removes any leading/trailing slashes from a string: + * + * /this/that/theother/ + * + * becomes: + * + * this/that/theother + * + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 This is just an alias for PHP's native trim() + * + * @param string + * @return string + */ + function trim_slashes($str) + { + return trim($str, '/'); + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('strip_slashes')) { /** @@ -255,3 +282,23 @@ function alternator() return $args[($i++ % count($args))]; } } + +// ------------------------------------------------------------------------ + +if ( ! function_exists('repeater')) +{ + /** + * Repeater function + * + * @todo Remove in version 3.1+. + * @deprecated 3.0.0 This is just an alias for PHP's native str_repeat() + * + * @param string $data String to repeat + * @param int $num Number of repeats + * @return string + */ + function repeater($data, $num = 1) + { + return ($num > 0) ? str_repeat($data, $num) : ''; + } +} diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php index 6a959f0e6da..bebfd258357 100644 --- a/system/helpers/url_helper.php +++ b/system/helpers/url_helper.php @@ -211,7 +211,7 @@ function anchor_popup($uri = '', $title = '', $attributes = FALSE) { $attributes = array($attributes); - // Ref: https://www.w3schools.com/jsref/met_win_open.asp + // Ref: http://www.w3schools.com/jsref/met_win_open.asp $window_name = '_blank'; } elseif ( ! empty($attributes['window_name'])) @@ -443,7 +443,7 @@ function auto_link($str, $type = 'both', $popup = FALSE) */ function prep_url($str = '') { - if ($str === '') + if ($str === 'http://' OR $str === '') { return ''; } @@ -546,7 +546,7 @@ function redirect($uri = '', $method = 'auto', $code = NULL) if (isset($_SERVER['SERVER_PROTOCOL'], $_SERVER['REQUEST_METHOD']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1') { $code = ($_SERVER['REQUEST_METHOD'] !== 'GET') - ? 303 // reference: https://en.wikipedia.org/wiki/Post/Redirect/Get + ? 303 // reference: http://en.wikipedia.org/wiki/Post/Redirect/Get : 307; } else diff --git a/system/index.html b/system/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/index.html +++ b/system/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php index 74a2512c4d9..bdb0254429d 100644 --- a/system/language/english/form_validation_lang.php +++ b/system/language/english/form_validation_lang.php @@ -43,7 +43,6 @@ $lang['form_validation_valid_emails'] = 'The {field} field must contain all valid email addresses.'; $lang['form_validation_valid_url'] = 'The {field} field must contain a valid URL.'; $lang['form_validation_valid_ip'] = 'The {field} field must contain a valid IP.'; -$lang['form_validation_valid_mac'] = 'The {field} field must contain a valid MAC.'; $lang['form_validation_valid_base64'] = 'The {field} field must contain a valid Base64 string.'; $lang['form_validation_min_length'] = 'The {field} field must be at least {param} characters in length.'; $lang['form_validation_max_length'] = 'The {field} field cannot exceed {param} characters in length.'; diff --git a/system/language/english/imglib_lang.php b/system/language/english/imglib_lang.php index 9a26b8a9bdb..c34b087c7f6 100644 --- a/system/language/english/imglib_lang.php +++ b/system/language/english/imglib_lang.php @@ -44,7 +44,6 @@ $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_webp_not_supported'] = 'WEBP 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.'; diff --git a/system/language/english/index.html b/system/language/english/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/language/english/index.html +++ b/system/language/english/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/language/index.html b/system/language/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/language/index.html +++ b/system/language/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php index b1241766015..450d57b8ae9 100644 --- a/system/libraries/Cache/Cache.php +++ b/system/libraries/Cache/Cache.php @@ -55,7 +55,6 @@ class CI_Cache extends CI_Driver_Library { */ protected $valid_drivers = array( 'apc', - 'apcu', 'dummy', 'file', 'memcached', @@ -253,16 +252,4 @@ public function is_supported($driver) return $support[$driver]; } - - // ------------------------------------------------------------------------ - - /** - * Get currently loaded driver - * - * @return string - */ - public function get_loaded_driver() - { - return $this->_adapter; - } } diff --git a/system/libraries/Cache/drivers/Cache_apcu.php b/system/libraries/Cache/drivers/Cache_apcu.php deleted file mode 100644 index 01f80e79bca..00000000000 --- a/system/libraries/Cache/drivers/Cache_apcu.php +++ /dev/null @@ -1,219 +0,0 @@ -is_supported()) - { - log_message('error', 'Cache: Failed to initialize APCu; extension not loaded/enabled?'); - } - } - - // ------------------------------------------------------------------------ - - /** - * Get - * - * Look for a value in the cache. If it exists, return the data - * if not, return FALSE - * - * @param string - * @return mixed value that is stored/FALSE on failure - */ - public function get($id) - { - $success = FALSE; - $data = apcu_fetch($id, $success); - - if ($success === TRUE) - { - return is_array($data) - ? $data[0] - : $data; - } - - return FALSE; - } - - // ------------------------------------------------------------------------ - - /** - * Cache Save - * - * @param string $id Cache ID - * @param mixed $data Data to store - * @param int $ttl Length of time (in seconds) to cache the data - * @param bool $raw Whether to store the raw value - * @return bool TRUE on success, FALSE on failure - */ - public function save($id, $data, $ttl = 60, $raw = FALSE) - { - $ttl = (int) $ttl; - - return apcu_store( - $id, - ($raw === TRUE ? $data : array($data, time(), $ttl)), - $ttl - ); - } - - // ------------------------------------------------------------------------ - - /** - * Delete from Cache - * - * @param mixed unique identifier of the item in the cache - * @return bool true on success/false on failure - */ - public function delete($id) - { - return apcu_delete($id); - } - - // ------------------------------------------------------------------------ - - /** - * Increment a raw value - * - * @param string $id Cache ID - * @param int $offset Step/value to add - * @return mixed New value on success or FALSE on failure - */ - public function increment($id, $offset = 1) - { - return apcu_inc($id, $offset); - } - - // ------------------------------------------------------------------------ - - /** - * Decrement a raw value - * - * @param string $id Cache ID - * @param int $offset Step/value to reduce by - * @return mixed New value on success or FALSE on failure - */ - public function decrement($id, $offset = 1) - { - return apcu_dec($id, $offset); - } - - // ------------------------------------------------------------------------ - - /** - * Clean the cache - * - * @return bool false on failure/true on success - */ - public function clean() - { - return apcu_clear_cache(); - } - - // ------------------------------------------------------------------------ - - /** - * Cache Info - * - * @return mixed array on success, false on failure - */ - public function cache_info() - { - return apcu_cache_info(); - } - - // ------------------------------------------------------------------------ - - /** - * Get Cache Metadata - * - * @param mixed key to get cache metadata on - * @return mixed array on success/false on failure - */ - public function get_metadata($id) - { - $success = FALSE; - $stored = apcu_fetch($id, $success); - - if ($success === FALSE OR count($stored) !== 3) - { - return FALSE; - } - - list($data, $time, $ttl) = $stored; - - return array( - 'expire' => $time + $ttl, - 'mtime' => $time, - 'data' => $data - ); - } - - // ------------------------------------------------------------------------ - - /** - * is_supported() - * - * Check to see if APCu is available on this system, bail if it isn't. - * - * @return bool - */ - public function is_supported() - { - return (extension_loaded('apcu') && ini_get('apc.enabled')); - } -} \ No newline at end of file diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php index 24969e0bf11..bdc86a5d689 100644 --- a/system/libraries/Cache/drivers/Cache_memcached.php +++ b/system/libraries/Cache/drivers/Cache_memcached.php @@ -102,22 +102,10 @@ public function __construct() return; } - foreach ($this->_config as $cache_name => $cache_server) + foreach ($this->_config as $cache_server) { - if ( ! isset($cache_server['hostname'])) - { - log_message('debug', 'Cache: Memcache(d) configuration "'.$cache_name.'" doesn\'t include a hostname; ignoring.'); - continue; - } - elseif ($cache_server['hostname'][0] === '/') - { - $cache_server['port'] = 0; - } - elseif (empty($cache_server['port'])) - { - $cache_server['port'] = $defaults['port']; - } - + isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host']; + isset($cache_server['port']) OR $cache_server['port'] = $defaults['port']; isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight']; if ($this->_memcached instanceof Memcache) diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php index 9b082d11b36..f0a72ee3cc0 100644 --- a/system/libraries/Cache/drivers/Cache_redis.php +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -55,11 +55,11 @@ class CI_Cache_redis extends CI_Driver * @var array */ protected static $_default_config = array( + 'socket_type' => 'tcp', 'host' => '127.0.0.1', 'password' => NULL, 'port' => 6379, - 'timeout' => 0, - 'database' => 0 + 'timeout' => 0 ); /** @@ -69,6 +69,12 @@ class CI_Cache_redis extends CI_Driver */ protected $_redis; + /** + * An internal cache for storing keys of serialized values. + * + * @var array + */ + protected $_serialized = array(); /** * del()/delete() method name depending on phpRedis version @@ -134,19 +140,23 @@ public function __construct() try { - if ( ! $this->_redis->connect($config['host'], ($config['host'][0] === '/' ? 0 : $config['port']), $config['timeout'])) + if ($config['socket_type'] === 'unix') { - log_message('error', 'Cache: Redis connection failed. Check your configuration.'); + $success = $this->_redis->connect($config['socket']); + } + else // tcp socket + { + $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']); } - if (isset($config['password']) && ! $this->_redis->auth($config['password'])) + if ( ! $success) { - log_message('error', 'Cache: Redis authentication failed.'); + log_message('error', 'Cache: Redis connection failed. Check your configuration.'); } - if (isset($config['database']) && $config['database'] > 0 && ! $this->_redis->select($config['database'])) + if (isset($config['password']) && ! $this->_redis->auth($config['password'])) { - log_message('error', 'Cache: Redis select database failed.'); + log_message('error', 'Cache: Redis authentication failed.'); } } catch (RedisException $e) @@ -165,30 +175,14 @@ public function __construct() */ public function get($key) { - $data = $this->_redis->hMGet($key, array('__ci_type', '__ci_value')); + $value = $this->_redis->get($key); if ($value !== FALSE && $this->_redis->sIsMember('_ci_redis_serialized', $key)) { - return FALSE; + return unserialize($value); } - switch ($data['__ci_type']) - { - case 'array': - case 'object': - return unserialize($data['__ci_value']); - case 'boolean': - case 'integer': - case 'double': // Yes, 'double' is returned and NOT 'float' - case 'string': - case 'NULL': - return settype($data['__ci_value'], $data['__ci_type']) - ? $data['__ci_value'] - : FALSE; - case 'resource': - default: - return FALSE; - } + return $value; } // ------------------------------------------------------------------------ @@ -204,33 +198,22 @@ public function get($key) */ public function save($id, $data, $ttl = 60, $raw = FALSE) { - switch ($data_type = gettype($data)) + if (is_array($data) OR is_object($data)) { - case 'array': - case 'object': - $data = serialize($data); - break; - case 'boolean': - case 'integer': - case 'double': // Yes, 'double' is returned and NOT 'float' - case 'string': - case 'NULL': - break; - case 'resource': - default: + if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id)) + { return FALSE; - } + } - if ( ! $this->_redis->hMSet($id, array('__ci_type' => $data_type, '__ci_value' => $data))) - { - return FALSE; + isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE; + $data = serialize($data); } else { $this->_redis->{static::$_sRemove_name}('_ci_redis_serialized', $id); } - return TRUE; + return $this->_redis->set($id, $data, $ttl); } // ------------------------------------------------------------------------ diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php index 703fece7a51..c20d0bc91df 100644 --- a/system/libraries/Cache/drivers/Cache_wincache.php +++ b/system/libraries/Cache/drivers/Cache_wincache.php @@ -41,7 +41,7 @@ * CodeIgniter Wincache Caching Class * * Read more about Wincache functions here: - * https://secure.php.net/manual/en/ref.wincache.php + * http://www.php.net/manual/en/ref.wincache.php * * @package CodeIgniter * @subpackage Libraries diff --git a/system/libraries/Cache/drivers/index.html b/system/libraries/Cache/drivers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/libraries/Cache/drivers/index.html +++ b/system/libraries/Cache/drivers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/libraries/Cache/index.html b/system/libraries/Cache/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/libraries/Cache/index.html +++ b/system/libraries/Cache/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php new file mode 100644 index 00000000000..6a107752caf --- /dev/null +++ b/system/libraries/Cart.php @@ -0,0 +1,567 @@ +CI =& get_instance(); + + // Are any config settings being passed manually? If so, set them + $config = is_array($params) ? $params : array(); + + // Load the Sessions class + $this->CI->load->driver('session', $config); + + // Grab the shopping cart array from the session table + $this->_cart_contents = $this->CI->session->userdata('cart_contents'); + if ($this->_cart_contents === NULL) + { + // No cart exists so we'll set some base values + $this->_cart_contents = array('cart_total' => 0, 'total_items' => 0); + } + + log_message('info', 'Cart Class Initialized'); + } + + // -------------------------------------------------------------------- + + /** + * Insert items into the cart and save it to the session table + * + * @param array + * @return bool + */ + public function insert($items = array()) + { + // Was any cart data passed? No? Bah... + if ( ! is_array($items) OR count($items) === 0) + { + log_message('error', 'The insert method must be passed an array containing data.'); + return FALSE; + } + + // You can either insert a single product using a one-dimensional array, + // or multiple products using a multi-dimensional one. The way we + // determine the array type is by looking for a required array key named "id" + // at the top level. If it's not found, we will assume it's a multi-dimensional array. + + $save_cart = FALSE; + if (isset($items['id'])) + { + if (($rowid = $this->_insert($items))) + { + $save_cart = TRUE; + } + } + else + { + foreach ($items as $val) + { + if (is_array($val) && isset($val['id'])) + { + if ($this->_insert($val)) + { + $save_cart = TRUE; + } + } + } + } + + // Save the cart data if the insert was successful + if ($save_cart === TRUE) + { + $this->_save_cart(); + return isset($rowid) ? $rowid : TRUE; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Insert + * + * @param array + * @return bool + */ + protected function _insert($items = array()) + { + // Was any cart data passed? No? Bah... + if ( ! is_array($items) OR count($items) === 0) + { + log_message('error', 'The insert method must be passed an array containing data.'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Does the $items array contain an id, quantity, price, and name? These are required + if ( ! isset($items['id'], $items['qty'], $items['price'], $items['name'])) + { + log_message('error', 'The cart array must contain a product ID, quantity, price, and name.'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Prep the quantity. It can only be a number. Duh... also trim any leading zeros + $items['qty'] = (float) $items['qty']; + + // If the quantity is zero or blank there's nothing for us to do + if ($items['qty'] == 0) + { + return FALSE; + } + + // -------------------------------------------------------------------- + + // Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods + // Not totally sure we should impose this rule, but it seems prudent to standardize IDs. + // Note: These can be user-specified by setting the $this->product_id_rules variable. + if ( ! preg_match('/^['.$this->product_id_rules.']+$/i', $items['id'])) + { + log_message('error', 'Invalid product ID. The product ID can only contain alpha-numeric characters, dashes, and underscores'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods. + // Note: These can be user-specified by setting the $this->product_name_rules variable. + if ($this->product_name_safe && ! preg_match('/^['.$this->product_name_rules.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $items['name'])) + { + log_message('error', 'An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces'); + return FALSE; + } + + // -------------------------------------------------------------------- + + // Prep the price. Remove leading zeros and anything that isn't a number or decimal point. + $items['price'] = (float) $items['price']; + + // We now need to create a unique identifier for the item being inserted into the cart. + // Every time something is added to the cart it is stored in the master cart array. + // Each row in the cart array, however, must have a unique index that identifies not only + // a particular product, but makes it possible to store identical products with different options. + // For example, what if someone buys two identical t-shirts (same product ID), but in + // different sizes? The product ID (and other attributes, like the name) will be identical for + // both sizes because it's the same shirt. The only difference will be the size. + // Internally, we need to treat identical submissions, but with different options, as a unique product. + // Our solution is to convert the options array to a string and MD5 it along with the product ID. + // This becomes the unique "row ID" + if (isset($items['options']) && count($items['options']) > 0) + { + $rowid = md5($items['id'].serialize($items['options'])); + } + else + { + // No options were submitted so we simply MD5 the product ID. + // Technically, we don't need to MD5 the ID in this case, but it makes + // sense to standardize the format of array indexes for both conditions + $rowid = md5($items['id']); + } + + // -------------------------------------------------------------------- + + // Now that we have our unique "row ID", we'll add our cart items to the master array + // grab quantity if it's already there and add it on + $old_quantity = isset($this->_cart_contents[$rowid]['qty']) ? (int) $this->_cart_contents[$rowid]['qty'] : 0; + + // Re-create the entry, just to make sure our index contains only the data from this submission + $items['rowid'] = $rowid; + $items['qty'] += $old_quantity; + $this->_cart_contents[$rowid] = $items; + + return $rowid; + } + + // -------------------------------------------------------------------- + + /** + * Update the cart + * + * This function permits the quantity of a given item to be changed. + * Typically it is called from the "view cart" page if a user makes + * changes to the quantity before checkout. That array must contain the + * product ID and quantity for each item. + * + * @param array + * @return bool + */ + public function update($items = array()) + { + // Was any cart data passed? + if ( ! is_array($items) OR count($items) === 0) + { + return FALSE; + } + + // You can either update a single product using a one-dimensional array, + // or multiple products using a multi-dimensional one. The way we + // determine the array type is by looking for a required array key named "rowid". + // If it's not found we assume it's a multi-dimensional array + $save_cart = FALSE; + if (isset($items['rowid'])) + { + if ($this->_update($items) === TRUE) + { + $save_cart = TRUE; + } + } + else + { + foreach ($items as $val) + { + if (is_array($val) && isset($val['rowid'])) + { + if ($this->_update($val) === TRUE) + { + $save_cart = TRUE; + } + } + } + } + + // Save the cart data if the insert was successful + if ($save_cart === TRUE) + { + $this->_save_cart(); + return TRUE; + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Update the cart + * + * This function permits changing item properties. + * Typically it is called from the "view cart" page if a user makes + * changes to the quantity before checkout. That array must contain the + * rowid and quantity for each item. + * + * @param array + * @return bool + */ + protected function _update($items = array()) + { + // Without these array indexes there is nothing we can do + if ( ! isset($items['rowid'], $this->_cart_contents[$items['rowid']])) + { + return FALSE; + } + + // Prep the quantity + if (isset($items['qty'])) + { + $items['qty'] = (float) $items['qty']; + // Is the quantity zero? If so we will remove the item from the cart. + // If the quantity is greater than zero we are updating + if ($items['qty'] == 0) + { + unset($this->_cart_contents[$items['rowid']]); + return TRUE; + } + } + + // find updatable keys + $keys = array_intersect(array_keys($this->_cart_contents[$items['rowid']]), array_keys($items)); + // if a price was passed, make sure it contains valid data + if (isset($items['price'])) + { + $items['price'] = (float) $items['price']; + } + + // product id & name shouldn't be changed + foreach (array_diff($keys, array('id', 'name')) as $key) + { + $this->_cart_contents[$items['rowid']][$key] = $items[$key]; + } + + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Save the cart array to the session DB + * + * @return bool + */ + protected function _save_cart() + { + // Let's add up the individual prices and set the cart sub-total + $this->_cart_contents['total_items'] = $this->_cart_contents['cart_total'] = 0; + foreach ($this->_cart_contents as $key => $val) + { + // We make sure the array contains the proper indexes + if ( ! is_array($val) OR ! isset($val['price'], $val['qty'])) + { + continue; + } + + $this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']); + $this->_cart_contents['total_items'] += $val['qty']; + $this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']); + } + + // Is our cart empty? If so we delete it from the session + if (count($this->_cart_contents) <= 2) + { + $this->CI->session->unset_userdata('cart_contents'); + + // Nothing more to do... coffee time! + return FALSE; + } + + // If we made it this far it means that our cart has data. + // Let's pass it to the Session class so it can be stored + $this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents)); + + // Woot! + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Cart Total + * + * @return int + */ + public function total() + { + return $this->_cart_contents['cart_total']; + } + + // -------------------------------------------------------------------- + + /** + * Remove Item + * + * Removes an item from the cart + * + * @param int + * @return bool + */ + public function remove($rowid) + { + // unset & save + unset($this->_cart_contents[$rowid]); + $this->_save_cart(); + return TRUE; + } + + // -------------------------------------------------------------------- + + /** + * Total Items + * + * Returns the total item count + * + * @return int + */ + public function total_items() + { + return $this->_cart_contents['total_items']; + } + + // -------------------------------------------------------------------- + + /** + * Cart Contents + * + * Returns the entire cart array + * + * @param bool + * @return array + */ + public function contents($newest_first = FALSE) + { + // do we want the newest first? + $cart = ($newest_first) ? array_reverse($this->_cart_contents) : $this->_cart_contents; + + // Remove these so they don't create a problem when showing the cart table + unset($cart['total_items']); + unset($cart['cart_total']); + + return $cart; + } + + // -------------------------------------------------------------------- + + /** + * Get cart item + * + * Returns the details of a specific item in the cart + * + * @param string $row_id + * @return array + */ + public function get_item($row_id) + { + return (in_array($row_id, array('total_items', 'cart_total'), TRUE) OR ! isset($this->_cart_contents[$row_id])) + ? FALSE + : $this->_cart_contents[$row_id]; + } + + // -------------------------------------------------------------------- + + /** + * Has options + * + * Returns TRUE if the rowid passed to this function correlates to an item + * that has options associated with it. + * + * @param string $row_id = '' + * @return bool + */ + public function has_options($row_id = '') + { + return (isset($this->_cart_contents[$row_id]['options']) && count($this->_cart_contents[$row_id]['options']) !== 0); + } + + // -------------------------------------------------------------------- + + /** + * Product options + * + * Returns the an array of options, for a particular product row ID + * + * @param string $row_id = '' + * @return array + */ + public function product_options($row_id = '') + { + return isset($this->_cart_contents[$row_id]['options']) ? $this->_cart_contents[$row_id]['options'] : array(); + } + + // -------------------------------------------------------------------- + + /** + * Format Number + * + * Returns the supplied number with commas and a decimal point. + * + * @param float + * @return string + */ + public function format_number($n = '') + { + return ($n === '') ? '' : number_format( (float) $n, 2, '.', ','); + } + + // -------------------------------------------------------------------- + + /** + * Destroy the cart + * + * Empties the cart and kills the session + * + * @return void + */ + public function destroy() + { + $this->_cart_contents = array('cart_total' => 0, 'total_items' => 0); + $this->CI->session->unset_userdata('cart_contents'); + } + +} diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 1912e0442d3..10b74777dec 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -147,7 +147,7 @@ class CI_Email { * * @var string */ - public $charset = 'utf-8'; + public $charset = 'UTF-8'; /** * Alternative message (for HTML messages only) @@ -161,7 +161,7 @@ class CI_Email { * * @var bool */ - public $validate = TRUE; + public $validate = FALSE; /** * X-Priority header value. @@ -174,7 +174,7 @@ class CI_Email { * Newline character sequence. * Use "\r\n" to comply with RFC 822. * - * @link https://www.ietf.org/rfc/rfc822.txt + * @link http://www.ietf.org/rfc/rfc822.txt * @var string "\r\n" or "\n" */ public $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822) @@ -188,7 +188,7 @@ class CI_Email { * switching to "\n", while improper, is the only solution * that seems to work for all environments. * - * @link https://www.ietf.org/rfc/rfc822.txt + * @link http://www.ietf.org/rfc/rfc822.txt * @var string */ public $crlf = "\n"; @@ -225,6 +225,13 @@ class CI_Email { // -------------------------------------------------------------------- + /** + * Whether PHP is running in safe mode. Initialized by the class constructor. + * + * @var bool + */ + protected $_safe_mode = FALSE; + /** * Subject header * @@ -388,6 +395,7 @@ public function __construct(array $config = array()) { $this->charset = config_item('charset'); $this->initialize($config); + $this->_safe_mode = ( ! is_php('5.4') && ini_get('safe_mode')); isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); @@ -667,6 +675,18 @@ public function subject($subject) public function message($body) { $this->_body = rtrim(str_replace("\r", '', $body)); + + /* strip slashes only if magic quotes is ON + if we do it with magic quotes OFF, it strips real, user-inputted chars. + + NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and + it will probably not exist in future versions at all. + */ + if ( ! is_php('5.4') && get_magic_quotes_gpc()) + { + $this->_body = stripslashes($this->_body); + } + return $this; } @@ -1012,15 +1032,16 @@ public function validate_email($email) */ public function valid_email($email) { - if (function_exists('idn_to_ascii') && preg_match('#\A([^@]+)@(.+)\z#', $email, $matches)) + if (function_exists('idn_to_ascii') && strpos($email, '@')) { + list($account, $domain) = explode('@', $email, 2); $domain = defined('INTL_IDNA_VARIANT_UTS46') - ? idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46) - : idn_to_ascii($matches[2]); + ? idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) + : idn_to_ascii($domain); if ($domain !== FALSE) { - $email = $matches[1].'@'.$domain; + $email = $account.'@'.$domain; } } @@ -1240,7 +1261,7 @@ protected function _write_headers() /** * Build Final Body and attachments * - * @return void + * @return bool */ protected function _build_message() { @@ -1407,6 +1428,8 @@ protected function _build_message() $this->_finalbody = ($this->_get_protocol() === 'mail') ? $body : $hdr.$this->newline.$this->newline.$body; + + return TRUE; } // -------------------------------------------------------------------- @@ -1467,7 +1490,7 @@ protected function _append_attachments(&$body, $boundary, $multipart = null) * Prep Quoted Printable * * Prepares string for Quoted-Printable Content-Transfer-Encoding - * Refer to RFC 2045 https://www.ietf.org/rfc/rfc2045.txt + * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt * * @param string * @return string @@ -1476,7 +1499,7 @@ protected function _prep_quoted_printable($str) { // ASCII code numbers for "safe" characters that can always be // used literally, without encoding, as described in RFC 2049. - // https://www.ietf.org/rfc/rfc2049.txt + // http://www.ietf.org/rfc/rfc2049.txt static $ascii_safe_chars = array( // ' ( ) + , - . / : = ? 39, 40, 41, 43, 44, 45, 46, 47, 58, 61, 63, @@ -1668,8 +1691,8 @@ public function send($auto_clear = TRUE) $this->reply_to($this->_headers['From']); } - if (empty($this->_recipients) && ! isset($this->_headers['To']) - && empty($this->_bcc_array) && ! isset($this->_headers['Bcc']) + if ( ! isset($this->_recipients) && ! isset($this->_headers['To']) + && ! isset($this->_bcc_array) && ! isset($this->_headers['Bcc']) && ! isset($this->_headers['Cc'])) { $this->_set_error_message('lang:email_no_recipients'); @@ -1680,17 +1703,21 @@ public function send($auto_clear = TRUE) if ($this->bcc_batch_mode && count($this->_bcc_array) > $this->bcc_batch_size) { - $this->batch_bcc_send(); + $result = $this->batch_bcc_send(); - if ($auto_clear) + if ($result && $auto_clear) { $this->clear(); } - return TRUE; + return $result; + } + + if ($this->_build_message() === FALSE) + { + return FALSE; } - $this->_build_message(); $result = $this->_spool_email(); if ($result && $auto_clear) @@ -1749,7 +1776,11 @@ public function batch_bcc_send() $this->_bcc_array = $bcc; } - $this->_build_message(); + if ($this->_build_message() === FALSE) + { + return FALSE; + } + $this->_spool_email(); } } @@ -1826,7 +1857,7 @@ protected function _spool_email() */ protected function _validate_email_for_shell(&$email) { - if (function_exists('idn_to_ascii') && $atpos = strpos($email, '@')) + if (function_exists('idn_to_ascii') && strpos($email, '@')) { list($account, $domain) = explode('@', $email, 2); $domain = defined('INTL_IDNA_VARIANT_UTS46') @@ -1860,14 +1891,16 @@ protected function _send_with_mail() // so this needs to be assigned to a variable $from = $this->clean_email($this->_headers['Return-Path']); - if ( ! $this->_validate_email_for_shell($from)) + if ($this->_safe_mode === TRUE || ! $this->_validate_email_for_shell($from)) { return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str); } - - // most documentation of sendmail using the "-f" flag lacks a space after it, however - // we've encountered servers that seem to require it to be in place. - return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$from); + else + { + // most documentation of sendmail using the "-f" flag lacks a space after it, however + // we've encountered servers that seem to require it to be in place. + return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$from); + } } // -------------------------------------------------------------------- @@ -1948,21 +1981,27 @@ protected function _send_with_smtp() } } - foreach ($this->_cc_array as $val) + if (count($this->_cc_array) > 0) { - if ($val !== '' && ! $this->_send_command('to', $val)) + foreach ($this->_cc_array as $val) { - $this->_smtp_end(); - return FALSE; + if ($val !== '' && ! $this->_send_command('to', $val)) + { + $this->_smtp_end(); + return FALSE; + } } } - foreach ($this->_bcc_array as $val) + if (count($this->_bcc_array) > 0) { - if ($val !== '' && ! $this->_send_command('to', $val)) + foreach ($this->_bcc_array as $val) { - $this->_smtp_end(); - return FALSE; + if ($val !== '' && ! $this->_send_command('to', $val)) + { + $this->_smtp_end(); + return FALSE; + } } } @@ -1976,6 +2015,7 @@ protected function _send_with_smtp() $this->_send_data($this->_header_str.preg_replace('/^\./m', '..$1', $this->_finalbody)); $this->_send_data('.'); + $reply = $this->_get_smtp_data(); $this->_set_error_message($reply); @@ -2001,7 +2041,9 @@ protected function _send_with_smtp() */ protected function _smtp_end() { - $this->_send_command($this->smtp_keepalive ? 'reset' : 'quit'); + ($this->smtp_keepalive) + ? $this->_send_command('reset') + : $this->_send_command('quit'); } // -------------------------------------------------------------------- @@ -2020,13 +2062,11 @@ protected function _smtp_connect() $ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : ''; - $this->_smtp_connect = fsockopen( - $ssl.$this->smtp_host, - $this->smtp_port, - $errno, - $errstr, - $this->smtp_timeout - ); + $this->_smtp_connect = fsockopen($ssl.$this->smtp_host, + $this->smtp_port, + $errno, + $errstr, + $this->smtp_timeout); if ( ! is_resource($this->_smtp_connect)) { @@ -2079,49 +2119,57 @@ protected 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 'starttls': - $this->_send_data('STARTTLS'); - $resp = 220; - break; - case 'from': - $this->_send_data('MAIL FROM:<'.$data.'>'); - $resp = 250; - break; - case 'to': - if ($this->dsn) - { - $this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data); - } - else - { - $this->_send_data('RCPT TO:<'.$data.'>'); - } - $resp = 250; - break; - case 'data': - $this->_send_data('DATA'); - $resp = 354; - break; + 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 'starttls' : + + $this->_send_data('STARTTLS'); + $resp = 220; + break; + case 'from' : + + $this->_send_data('MAIL FROM:<'.$data.'>'); + $resp = 250; + break; + case 'to' : + + if ($this->dsn) + { + $this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data); + } + else + { + $this->_send_data('RCPT TO:<'.$data.'>'); + } + + $resp = 250; + break; + case 'data' : + + $this->_send_data('DATA'); + $resp = 354; + break; case 'reset': - $this->_send_data('RSET'); - $resp = 250; - break; - case 'quit': - $this->_send_data('QUIT'); - $resp = 221; - break; + + $this->_send_data('RSET'); + $resp = 250; + break; + case 'quit' : + + $this->_send_data('QUIT'); + $resp = 221; + break; } $reply = $this->_get_smtp_data(); @@ -2163,6 +2211,7 @@ protected function _smtp_authenticate() } $this->_send_data('AUTH LOGIN'); + $reply = $this->_get_smtp_data(); if (strpos($reply, '503') === 0) // Already authenticated @@ -2176,6 +2225,7 @@ protected function _smtp_authenticate() } $this->_send_data(base64_encode($this->smtp_user)); + $reply = $this->_get_smtp_data(); if (strpos($reply, '334') !== 0) @@ -2185,6 +2235,7 @@ protected function _smtp_authenticate() } $this->_send_data(base64_encode($this->smtp_pass)); + $reply = $this->_get_smtp_data(); if (strpos($reply, '235') !== 0) @@ -2218,7 +2269,7 @@ protected function _send_data($data) { break; } - // See https://bugs.php.net/bug.php?id=39598 and https://secure.php.net/manual/en/function.fwrite.php#96951 + // See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951 elseif ($result === 0) { if ($timestamp === 0) @@ -2281,7 +2332,7 @@ protected function _get_smtp_data() * (eg: "[1.2.3.4]"). * * @link https://tools.ietf.org/html/rfc5321#section-2.3.5 - * @link https://cbl.abuseat.org/namingproblems.html + * @link http://cbl.abuseat.org/namingproblems.html * @return string */ protected function _get_hostname() @@ -2305,15 +2356,34 @@ protected function _get_hostname() */ public function print_debugger($include = array('headers', 'subject', 'body')) { - $msg = implode('', $this->_debug_msg); + $msg = ''; + + if (count($this->_debug_msg) > 0) + { + foreach ($this->_debug_msg as $val) + { + $msg .= $val; + } + } // Determine which parts of our raw data needs to be printed $raw_data = ''; is_array($include) OR $include = array($include); - in_array('headers', $include, TRUE) && $raw_data = htmlspecialchars($this->_header_str)."\n"; - in_array('subject', $include, TRUE) && $raw_data .= htmlspecialchars($this->_subject)."\n"; - in_array('body', $include, TRUE) && $raw_data .= htmlspecialchars($this->_finalbody); + if (in_array('headers', $include, TRUE)) + { + $raw_data = htmlspecialchars($this->_header_str)."\n"; + } + + if (in_array('subject', $include, TRUE)) + { + $raw_data .= htmlspecialchars($this->_subject)."\n"; + } + + if (in_array('body', $include, TRUE)) + { + $raw_data .= htmlspecialchars($this->_finalbody); + } return $msg.($raw_data === '' ? '' : '
'.$raw_data.'
'); } @@ -2407,6 +2477,9 @@ protected static function substr($str, $start, $length = NULL) { if (self::$func_overload) { + // mb_substr($str, $start, null, '8bit') returns an empty + // string on PHP 5.3 + isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); return mb_substr($str, $start, $length, '8bit'); } diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index fd858cb297b..4c1973fee55 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -482,7 +482,7 @@ protected function _openssl_encrypt($data, $params) $data, $params['handle'], $params['key'], - OPENSSL_RAW_DATA, + 1, // DO NOT TOUCH! $iv ); @@ -641,7 +641,7 @@ protected function _openssl_decrypt($data, $params) $data, $params['handle'], $params['key'], - OPENSSL_RAW_DATA, + 1, // DO NOT TOUCH! $iv ); } @@ -928,6 +928,9 @@ protected static function substr($str, $start, $length = NULL) { if (self::$func_overload) { + // mb_substr($str, $start, null, '8bit') returns an empty + // string on PHP 5.3 + isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); return mb_substr($str, $start, $length, '8bit'); } diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index de59ef9f736..fdf2020101c 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -104,6 +104,13 @@ class CI_Form_validation { */ protected $error_string = ''; + /** + * Whether the form data has been validated as safe + * + * @var bool + */ + protected $_safe_form_data = FALSE; + /** * Custom data to validate * @@ -157,7 +164,7 @@ public function __construct($rules = array()) * @param array $errors * @return CI_Form_validation */ - public function set_rules($field, $label = null, $rules = null, $errors = array()) + public function set_rules($field, $label = '', $rules = array(), $errors = array()) { // No reason to set rules if we have no POST data // or a validation array has not been specified @@ -190,22 +197,18 @@ public function set_rules($field, $label = null, $rules = null, $errors = array( return $this; } - elseif ( ! isset($rules)) - { - throw new BadMethodCallException('Form_validation: set_rules() called without a $rules parameter'); - } // No fields or no rules? Nothing to do... if ( ! is_string($field) OR $field === '' OR empty($rules)) { - throw new RuntimeException('Form_validation: set_rules() called with an empty $rules parameter'); + return $this; } elseif ( ! is_array($rules)) { // BC: Convert pipe-separated rules string to an array if ( ! is_string($rules)) { - throw new InvalidArgumentException('Form_validation: set_rules() expect $rules to be string or array; '.gettype($rules).' given'); + return $this; } $rules = preg_split('/\|(?![^\[]*\])/', $rules); @@ -407,11 +410,10 @@ public function error_string($prefix = '', $suffix = '') * * This function does all the work. * - * @param string $config - * @param array $data + * @param string $group * @return bool */ - public function run($config = NULL, &$data = NULL) + public function run($group = '') { $validation_array = empty($this->validation_data) ? $_POST @@ -422,19 +424,19 @@ public function run($config = NULL, &$data = NULL) if (count($this->_field_data) === 0) { // No validation rules? We're done... - if (empty($this->_config_rules)) + if (count($this->_config_rules) === 0) { return FALSE; } - if (empty($config)) + if (empty($group)) { // Is there a validation rule for the particular URI being accessed? - $config = trim($this->CI->uri->ruri_string(), '/'); - isset($this->_config_rules[$config]) OR $config = $this->CI->router->class.'/'.$this->CI->router->method; + $group = trim($this->CI->uri->ruri_string(), '/'); + isset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method; } - $this->set_rules(isset($this->_config_rules[$config]) ? $this->_config_rules[$config] : $this->_config_rules); + $this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules); // Were we able to set the rules correctly? if (count($this->_field_data) === 0) @@ -476,22 +478,17 @@ public function run($config = NULL, &$data = NULL) $this->_execute($row, $row['rules'], $row['postdata']); } - if ( ! empty($this->_error_array)) + // Did we end up with any errors? + $total_errors = count($this->_error_array); + if ($total_errors > 0) { - return FALSE; + $this->_safe_form_data = TRUE; } - // Fill $data if requested, otherwise modify $_POST, as long as - // set_data() wasn't used (yea, I know it sounds confusing) - if (func_num_args() >= 2) - { - $data = empty($this->validation_data) ? $_POST : $this->validation_data; - $this->_reset_data_array($data); - return TRUE; - } + // Now we need to re-set the POST data with the new, processed data + empty($this->validation_data) && $this->_reset_post_array(); - empty($this->validation_data) && $this->_reset_data_array($_POST); - return TRUE; + return ($total_errors === 0); } // -------------------------------------------------------------------- @@ -579,7 +576,7 @@ protected function _reduce_array($array, $keys, $i = 0) * * @return void */ - protected function _reset_data_array(&$data) + protected function _reset_post_array() { foreach ($this->_field_data as $field => $row) { @@ -587,26 +584,27 @@ protected function _reset_data_array(&$data) { if ($row['is_array'] === FALSE) { - isset($data[$field]) && $data[$field] = is_array($row['postdata']) ? NULL : $row['postdata']; + isset($_POST[$field]) && $_POST[$field] = is_array($row['postdata']) ? NULL : $row['postdata']; } else { - $data_ref =& $data; + // start with a reference + $post_ref =& $_POST; // before we assign values, make a reference to the right POST key if (count($row['keys']) === 1) { - $data_ref =& $data[current($row['keys'])]; + $post_ref =& $post_ref[current($row['keys'])]; } else { foreach ($row['keys'] as $val) { - $data_ref =& $data_ref[$val]; + $post_ref =& $post_ref[$val]; } } - $data_ref = $row['postdata']; + $post_ref = $row['postdata']; } } } @@ -625,13 +623,11 @@ protected function _reset_data_array(&$data) */ protected function _execute($row, $rules, $postdata = NULL, $cycles = 0) { - $allow_arrays = in_array('is_array', $rules, TRUE); - // If the $_POST data is an array we will run a recursive call // // Note: We MUST check if the array is empty or not! // Otherwise empty arrays will always pass validation. - if ($allow_arrays === FALSE && is_array($postdata) && ! empty($postdata)) + if (is_array($postdata) && ! empty($postdata)) { foreach ($postdata as $key => $val) { @@ -660,16 +656,14 @@ protected function _execute($row, $rules, $postdata = NULL, $cycles = 0) $postdata = $this->_field_data[$row['field']]['postdata'][$cycles]; $_in_array = TRUE; } - // If we get an array field, but it's not expected - then it is most likely - // somebody messing with the form on the client side, so we'll just consider - // it an empty field - elseif ($allow_arrays === FALSE && is_array($this->_field_data[$row['field']]['postdata'])) - { - $postdata = NULL; - } else { - $postdata = $this->_field_data[$row['field']]['postdata']; + // If we get an array field, but it's not expected - then it is most likely + // somebody messing with the form on the client side, so we'll just consider + // it an empty field + $postdata = is_array($this->_field_data[$row['field']]['postdata']) + ? NULL + : $this->_field_data[$row['field']]['postdata']; } // Is the rule a callback? @@ -704,7 +698,7 @@ protected function _execute($row, $rules, $postdata = NULL, $cycles = 0) // Ignore empty, non-required inputs with a few exceptions ... if ( - ($postdata === NULL OR ($allow_arrays === FALSE && $postdata === '')) + ($postdata === NULL OR $postdata === '') && $callback === FALSE && $callable === FALSE && ! in_array($rule, array('required', 'isset', 'matches'), TRUE) @@ -1299,31 +1293,6 @@ public function valid_ip($ip, $which = '') // -------------------------------------------------------------------- - /** - * Validate MAC address - * - * @param string $mac - * @return bool - */ - public function valid_mac($mac) - { - if ( ! is_php('5.5')) - { - // Most common format, with either dash or colon delimiters - if (preg_match('#\A[0-9a-f]{2}(?[:-])([0-9a-f]{2}(?P=delimiter)){4}[0-9a-f]{2}\z#i', $mac)) - { - return TRUE; - } - - // The less common format; e.g. 0123.4567.89ab - return (bool) preg_match('#((\A|\.)[0-9a-f]{4}){3}\z#i', $mac); - } - - return (bool) filter_var($mac, FILTER_VALIDATE_MAC); - } - - // -------------------------------------------------------------------- - /** * Alpha * @@ -1528,6 +1497,38 @@ public function valid_base64($str) // -------------------------------------------------------------------- + /** + * Prep data for form + * + * This function allows HTML to be safely shown in a form. + * Special characters are converted. + * + * @deprecated 3.0.6 Not used anywhere within the framework and pretty much useless + * @param mixed $data Input data + * @return mixed + */ + public function prep_for_form($data) + { + if ($this->_safe_form_data === FALSE OR empty($data)) + { + return $data; + } + + if (is_array($data)) + { + foreach ($data as $key => $val) + { + $data[$key] = $this->prep_for_form($val); + } + + return $data; + } + + return str_replace(array("'", '"', '<', '>'), array(''', '"', '<', '>'), stripslashes($data)); + } + + // -------------------------------------------------------------------- + /** * Prep URL * @@ -1536,7 +1537,12 @@ public function valid_base64($str) */ public function prep_url($str = '') { - if ($str !== '' && stripos($str, 'http://') !== 0 && stripos($str, 'https://') !== 0) + if ($str === 'http://' OR $str === '') + { + return ''; + } + + if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0) { return 'http://'.$str; } diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php index 0d9fa442035..b89bc5b7e37 100644 --- a/system/libraries/Image_lib.php +++ b/system/libraries/Image_lib.php @@ -946,10 +946,6 @@ public function image_process_netpbm($action = 'resize') $cmd_in = 'pngtopnm'; $cmd_out = 'ppmtopng'; break; - case 18 : - $cmd_in = 'webptopnm'; - $cmd_out = 'ppmtowebp'; - break; } if ($action === 'crop') @@ -1211,7 +1207,7 @@ public function overlay_watermark() } // Build the finalized image - if ($wm_img_type === 3) + if ($wm_img_type === 3 && function_exists('imagealphablending')) { @imagealphablending($src_img, TRUE); } @@ -1474,13 +1470,6 @@ public function image_create_gd($path = '', $image_type = '') $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported')); return FALSE; } - case 18: - if ( ! function_exists('imagecreatefromwebp')) - { - $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_webp_not_supported')); - return FALSE; - } - return imagecreatefromwebp($path); return imagecreatefrompng($path); default: @@ -1543,19 +1532,6 @@ public function image_save_gd($resource) return FALSE; } break; - case 18: - if ( ! function_exists('imagewebp')) - { - $this->set_error(array('imglib_unsupported_imagecreate', 'imglib_webp_not_supported')); - return FALSE; - } - - if ( ! @imagewebp($resource, $this->full_dst_path)) - { - $this->set_error('imglib_save_failed'); - return FALSE; - } - break; default: $this->set_error(array('imglib_unsupported_imagecreate')); return FALSE; @@ -1575,16 +1551,7 @@ public function image_save_gd($resource) */ public function image_display_gd($resource) { - // RFC 6266 allows for multibyte filenames, but only in UTF-8, - // so we have to make it conditional ... - $filename = basename(empty($this->new_image) ? $this->source_image : $this->new_image); - $charset = strtoupper(config_item('charset')); - $utf8_filename = ($charset !== 'UTF-8') - ? get_instance()->utf8->convert_to_utf8($filename, $charset) - : $filename; - isset($utf8_filename[0]) && $utf8_filename = " filename*=UTF-8''".rawurlencode($utf8_filename); - - header('Content-Disposition: filename="'.$filename.'";'.$utf8_filename); + 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'); @@ -1597,8 +1564,6 @@ public function image_display_gd($resource) break; case 3 : imagepng($resource); break; - case 18 : imagewebp($resource); - break; default: echo 'Unable to display the image'; break; } diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php new file mode 100644 index 00000000000..c9103945b73 --- /dev/null +++ b/system/libraries/Javascript.php @@ -0,0 +1,856 @@ + 'jquery', 'autoload' => TRUE); + + foreach ($defaults as $key => $val) + { + if (isset($params[$key]) && $params[$key] !== '') + { + $defaults[$key] = $params[$key]; + } + } + + extract($defaults); + + $this->CI =& get_instance(); + + // load the requested js library + $this->CI->load->library('Javascript/'.$js_library_driver, array('autoload' => $autoload)); + // make js to refer to current library + $this->js =& $this->CI->$js_library_driver; + + log_message('info', 'Javascript Class Initialized and loaded. Driver used: '.$js_library_driver); + } + + // -------------------------------------------------------------------- + // Event Code + // -------------------------------------------------------------------- + + /** + * Blur + * + * Outputs a javascript library blur event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function blur($element = 'this', $js = '') + { + return $this->js->_blur($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Change + * + * Outputs a javascript library change event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function change($element = 'this', $js = '') + { + return $this->js->_change($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Click + * + * Outputs a javascript library click event + * + * @param string The element to attach the event to + * @param string The code to execute + * @param bool whether or not to return false + * @return string + */ + public function click($element = 'this', $js = '', $ret_false = TRUE) + { + return $this->js->_click($element, $js, $ret_false); + } + + // -------------------------------------------------------------------- + + /** + * Double Click + * + * Outputs a javascript library dblclick event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function dblclick($element = 'this', $js = '') + { + return $this->js->_dblclick($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Error + * + * Outputs a javascript library error event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function error($element = 'this', $js = '') + { + return $this->js->_error($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Focus + * + * Outputs a javascript library focus event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function focus($element = 'this', $js = '') + { + return $this->js->_focus($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Hover + * + * Outputs a javascript library hover event + * + * @param string - element + * @param string - Javascript code for mouse over + * @param string - Javascript code for mouse out + * @return string + */ + public function hover($element = 'this', $over = '', $out = '') + { + return $this->js->_hover($element, $over, $out); + } + + // -------------------------------------------------------------------- + + /** + * Keydown + * + * Outputs a javascript library keydown event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function keydown($element = 'this', $js = '') + { + return $this->js->_keydown($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Keyup + * + * Outputs a javascript library keydown event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function keyup($element = 'this', $js = '') + { + return $this->js->_keyup($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Load + * + * Outputs a javascript library load event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function load($element = 'this', $js = '') + { + return $this->js->_load($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Mousedown + * + * Outputs a javascript library mousedown event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function mousedown($element = 'this', $js = '') + { + return $this->js->_mousedown($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Mouse Out + * + * Outputs a javascript library mouseout event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function mouseout($element = 'this', $js = '') + { + return $this->js->_mouseout($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Mouse Over + * + * Outputs a javascript library mouseover event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function mouseover($element = 'this', $js = '') + { + return $this->js->_mouseover($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Mouseup + * + * Outputs a javascript library mouseup event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function mouseup($element = 'this', $js = '') + { + return $this->js->_mouseup($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Output + * + * Outputs the called javascript to the screen + * + * @param string The code to output + * @return string + */ + public function output($js) + { + return $this->js->_output($js); + } + + // -------------------------------------------------------------------- + + /** + * Ready + * + * Outputs a javascript library mouseup event + * + * @param string $js Code to execute + * @return string + */ + public function ready($js) + { + return $this->js->_document_ready($js); + } + + // -------------------------------------------------------------------- + + /** + * Resize + * + * Outputs a javascript library resize event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function resize($element = 'this', $js = '') + { + return $this->js->_resize($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Scroll + * + * Outputs a javascript library scroll event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function scroll($element = 'this', $js = '') + { + return $this->js->_scroll($element, $js); + } + + // -------------------------------------------------------------------- + + /** + * Unload + * + * Outputs a javascript library unload event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + public function unload($element = 'this', $js = '') + { + return $this->js->_unload($element, $js); + } + + // -------------------------------------------------------------------- + // Effects + // -------------------------------------------------------------------- + + /** + * Add Class + * + * Outputs a javascript library addClass event + * + * @param string - element + * @param string - Class to add + * @return string + */ + public function addClass($element = 'this', $class = '') + { + return $this->js->_addClass($element, $class); + } + + // -------------------------------------------------------------------- + + /** + * Animate + * + * Outputs a javascript library animate event + * + * @param string $element = 'this' + * @param array $params = array() + * @param mixed $speed 'slow', 'normal', 'fast', or time in milliseconds + * @param string $extra + * @return string + */ + public function animate($element = 'this', $params = array(), $speed = '', $extra = '') + { + return $this->js->_animate($element, $params, $speed, $extra); + } + + // -------------------------------------------------------------------- + + /** + * Fade In + * + * Outputs a javascript library hide event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function fadeIn($element = 'this', $speed = '', $callback = '') + { + return $this->js->_fadeIn($element, $speed, $callback); + } + + // -------------------------------------------------------------------- + + /** + * Fade Out + * + * Outputs a javascript library hide event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function fadeOut($element = 'this', $speed = '', $callback = '') + { + return $this->js->_fadeOut($element, $speed, $callback); + } + // -------------------------------------------------------------------- + + /** + * Slide Up + * + * Outputs a javascript library slideUp event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function slideUp($element = 'this', $speed = '', $callback = '') + { + return $this->js->_slideUp($element, $speed, $callback); + + } + + // -------------------------------------------------------------------- + + /** + * Remove Class + * + * Outputs a javascript library removeClass event + * + * @param string - element + * @param string - Class to add + * @return string + */ + public function removeClass($element = 'this', $class = '') + { + return $this->js->_removeClass($element, $class); + } + + // -------------------------------------------------------------------- + + /** + * Slide Down + * + * Outputs a javascript library slideDown event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function slideDown($element = 'this', $speed = '', $callback = '') + { + return $this->js->_slideDown($element, $speed, $callback); + } + + // -------------------------------------------------------------------- + + /** + * Slide Toggle + * + * Outputs a javascript library slideToggle event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function slideToggle($element = 'this', $speed = '', $callback = '') + { + return $this->js->_slideToggle($element, $speed, $callback); + + } + + // -------------------------------------------------------------------- + + /** + * Hide + * + * Outputs a javascript library hide action + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function hide($element = 'this', $speed = '', $callback = '') + { + return $this->js->_hide($element, $speed, $callback); + } + + // -------------------------------------------------------------------- + + /** + * Toggle + * + * Outputs a javascript library toggle event + * + * @param string - element + * @return string + */ + public function toggle($element = 'this') + { + return $this->js->_toggle($element); + + } + + // -------------------------------------------------------------------- + + /** + * Toggle Class + * + * Outputs a javascript library toggle class event + * + * @param string $element = 'this' + * @param string $class = '' + * @return string + */ + public function toggleClass($element = 'this', $class = '') + { + return $this->js->_toggleClass($element, $class); + } + + // -------------------------------------------------------------------- + + /** + * Show + * + * Outputs a javascript library show event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function show($element = 'this', $speed = '', $callback = '') + { + return $this->js->_show($element, $speed, $callback); + } + + // -------------------------------------------------------------------- + + /** + * Compile + * + * gather together all script needing to be output + * + * @param string $view_var + * @param bool $script_tags + * @return string + */ + public function compile($view_var = 'script_foot', $script_tags = TRUE) + { + $this->js->_compile($view_var, $script_tags); + } + + // -------------------------------------------------------------------- + + /** + * Clear Compile + * + * Clears any previous javascript collected for output + * + * @return void + */ + public function clear_compile() + { + $this->js->_clear_compile(); + } + + // -------------------------------------------------------------------- + + /** + * External + * + * Outputs a + * + * @param string + * @return string + */ + protected function _close_script($extra = "\n") + { + return ''.$extra; + } + + // -------------------------------------------------------------------- + // AJAX-Y STUFF - still a testbed + // -------------------------------------------------------------------- + + /** + * Update + * + * Outputs a javascript library slideDown event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + public function update($element = 'this', $speed = '', $callback = '') + { + return $this->js->_updater($element, $speed, $callback); + } + + // -------------------------------------------------------------------- + + /** + * Generate JSON + * + * Can be passed a database result or associative array and returns a JSON formatted string + * + * @param mixed result set or array + * @param bool match array types (defaults to objects) + * @return string a json formatted string + */ + public function generate_json($result = NULL, $match_array_type = FALSE) + { + // JSON data can optionally be passed to this function + // either as a database result object or an array, or a user supplied array + if ($result !== NULL) + { + if (is_object($result)) + { + $json_result = is_callable(array($result, 'result_array')) ? $result->result_array() : (array) $result; + } + elseif (is_array($result)) + { + $json_result = $result; + } + else + { + return $this->_prep_args($result); + } + } + else + { + return 'null'; + } + + $json = array(); + $_is_assoc = TRUE; + + if ( ! is_array($json_result) && empty($json_result)) + { + show_error('Generate JSON Failed - Illegal key, value pair.'); + } + elseif ($match_array_type) + { + $_is_assoc = $this->_is_associative_array($json_result); + } + + foreach ($json_result as $k => $v) + { + if ($_is_assoc) + { + $json[] = $this->_prep_args($k, TRUE).':'.$this->generate_json($v, $match_array_type); + } + else + { + $json[] = $this->generate_json($v, $match_array_type); + } + } + + $json = implode(',', $json); + + return $_is_assoc ? '{'.$json.'}' : '['.$json.']'; + + } + + // -------------------------------------------------------------------- + + /** + * Is associative array + * + * Checks for an associative array + * + * @param array + * @return bool + */ + protected function _is_associative_array($arr) + { + foreach (array_keys($arr) as $key => $val) + { + if ($key !== $val) + { + return TRUE; + } + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** + * Prep Args + * + * Ensures a standard json value and escapes values + * + * @param mixed $result + * @param bool $is_key = FALSE + * @return string + */ + protected function _prep_args($result, $is_key = FALSE) + { + if ($result === NULL) + { + return 'null'; + } + elseif (is_bool($result)) + { + return ($result === TRUE) ? 'true' : 'false'; + } + elseif (is_string($result) OR $is_key) + { + return '"'.str_replace(array('\\', "\t", "\n", "\r", '"', '/'), array('\\\\', '\\t', '\\n', "\\r", '\"', '\/'), $result).'"'; + } + elseif (is_scalar($result)) + { + return $result; + } + } + +} diff --git a/system/libraries/Javascript/Jquery.php b/system/libraries/Javascript/Jquery.php new file mode 100644 index 00000000000..485d1dc1819 --- /dev/null +++ b/system/libraries/Javascript/Jquery.php @@ -0,0 +1,1076 @@ +CI =& get_instance(); + extract($params); + + if ($autoload === TRUE) + { + $this->script(); + } + + log_message('info', 'Jquery Class Initialized'); + } + + // -------------------------------------------------------------------- + // Event Code + // -------------------------------------------------------------------- + + /** + * Blur + * + * Outputs a jQuery blur event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _blur($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'blur'); + } + + // -------------------------------------------------------------------- + + /** + * Change + * + * Outputs a jQuery change event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _change($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'change'); + } + + // -------------------------------------------------------------------- + + /** + * Click + * + * Outputs a jQuery click event + * + * @param string The element to attach the event to + * @param string The code to execute + * @param bool whether or not to return false + * @return string + */ + protected function _click($element = 'this', $js = '', $ret_false = TRUE) + { + is_array($js) OR $js = array($js); + + if ($ret_false) + { + $js[] = 'return false;'; + } + + return $this->_add_event($element, $js, 'click'); + } + + // -------------------------------------------------------------------- + + /** + * Double Click + * + * Outputs a jQuery dblclick event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _dblclick($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'dblclick'); + } + + // -------------------------------------------------------------------- + + /** + * Error + * + * Outputs a jQuery error event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _error($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'error'); + } + + // -------------------------------------------------------------------- + + /** + * Focus + * + * Outputs a jQuery focus event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _focus($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'focus'); + } + + // -------------------------------------------------------------------- + + /** + * Hover + * + * Outputs a jQuery hover event + * + * @param string - element + * @param string - Javascript code for mouse over + * @param string - Javascript code for mouse out + * @return string + */ + protected function _hover($element = 'this', $over = '', $out = '') + { + $event = "\n\t$(".$this->_prep_element($element).").hover(\n\t\tfunction()\n\t\t{\n\t\t\t{$over}\n\t\t}, \n\t\tfunction()\n\t\t{\n\t\t\t{$out}\n\t\t});\n"; + + $this->jquery_code_for_compile[] = $event; + + return $event; + } + + // -------------------------------------------------------------------- + + /** + * Keydown + * + * Outputs a jQuery keydown event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _keydown($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'keydown'); + } + + // -------------------------------------------------------------------- + + /** + * Keyup + * + * Outputs a jQuery keydown event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _keyup($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'keyup'); + } + + // -------------------------------------------------------------------- + + /** + * Load + * + * Outputs a jQuery load event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _load($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'load'); + } + + // -------------------------------------------------------------------- + + /** + * Mousedown + * + * Outputs a jQuery mousedown event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _mousedown($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mousedown'); + } + + // -------------------------------------------------------------------- + + /** + * Mouse Out + * + * Outputs a jQuery mouseout event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _mouseout($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mouseout'); + } + + // -------------------------------------------------------------------- + + /** + * Mouse Over + * + * Outputs a jQuery mouseover event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _mouseover($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mouseover'); + } + + // -------------------------------------------------------------------- + + /** + * Mouseup + * + * Outputs a jQuery mouseup event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _mouseup($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'mouseup'); + } + + // -------------------------------------------------------------------- + + /** + * Output + * + * Outputs script directly + * + * @param array $array_js = array() + * @return void + */ + protected function _output($array_js = array()) + { + if ( ! is_array($array_js)) + { + $array_js = array($array_js); + } + + foreach ($array_js as $js) + { + $this->jquery_code_for_compile[] = "\t".$js."\n"; + } + } + + // -------------------------------------------------------------------- + + /** + * Resize + * + * Outputs a jQuery resize event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _resize($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'resize'); + } + + // -------------------------------------------------------------------- + + /** + * Scroll + * + * Outputs a jQuery scroll event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _scroll($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'scroll'); + } + + // -------------------------------------------------------------------- + + /** + * Unload + * + * Outputs a jQuery unload event + * + * @param string The element to attach the event to + * @param string The code to execute + * @return string + */ + protected function _unload($element = 'this', $js = '') + { + return $this->_add_event($element, $js, 'unload'); + } + + // -------------------------------------------------------------------- + // Effects + // -------------------------------------------------------------------- + + /** + * Add Class + * + * Outputs a jQuery addClass event + * + * @param string $element + * @param string $class + * @return string + */ + protected function _addClass($element = 'this', $class = '') + { + $element = $this->_prep_element($element); + return '$('.$element.').addClass("'.$class.'");'; + } + + // -------------------------------------------------------------------- + + /** + * Animate + * + * Outputs a jQuery animate event + * + * @param string $element + * @param array $params + * @param string $speed 'slow', 'normal', 'fast', or time in milliseconds + * @param string $extra + * @return string + */ + protected function _animate($element = 'this', $params = array(), $speed = '', $extra = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + $animations = "\t\t\t"; + + foreach ($params as $param => $value) + { + $animations .= $param.": '".$value."', "; + } + + $animations = substr($animations, 0, -2); // remove the last ", " + + if ($speed !== '') + { + $speed = ', '.$speed; + } + + if ($extra !== '') + { + $extra = ', '.$extra; + } + + return "$({$element}).animate({\n$animations\n\t\t}".$speed.$extra.');'; + } + + // -------------------------------------------------------------------- + + /** + * Fade In + * + * Outputs a jQuery hide event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _fadeIn($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return "$({$element}).fadeIn({$speed}{$callback});"; + } + + // -------------------------------------------------------------------- + + /** + * Fade Out + * + * Outputs a jQuery hide event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _fadeOut($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return '$('.$element.').fadeOut('.$speed.$callback.');'; + } + + // -------------------------------------------------------------------- + + /** + * Hide + * + * Outputs a jQuery hide action + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _hide($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return "$({$element}).hide({$speed}{$callback});"; + } + + // -------------------------------------------------------------------- + + /** + * Remove Class + * + * Outputs a jQuery remove class event + * + * @param string $element + * @param string $class + * @return string + */ + protected function _removeClass($element = 'this', $class = '') + { + $element = $this->_prep_element($element); + return '$('.$element.').removeClass("'.$class.'");'; + } + + // -------------------------------------------------------------------- + + /** + * Slide Up + * + * Outputs a jQuery slideUp event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _slideUp($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return '$('.$element.').slideUp('.$speed.$callback.');'; + } + + // -------------------------------------------------------------------- + + /** + * Slide Down + * + * Outputs a jQuery slideDown event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _slideDown($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return '$('.$element.').slideDown('.$speed.$callback.');'; + } + + // -------------------------------------------------------------------- + + /** + * Slide Toggle + * + * Outputs a jQuery slideToggle event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _slideToggle($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return '$('.$element.').slideToggle('.$speed.$callback.');'; + } + + // -------------------------------------------------------------------- + + /** + * Toggle + * + * Outputs a jQuery toggle event + * + * @param string - element + * @return string + */ + protected function _toggle($element = 'this') + { + $element = $this->_prep_element($element); + return '$('.$element.').toggle();'; + } + + // -------------------------------------------------------------------- + + /** + * Toggle Class + * + * Outputs a jQuery toggle class event + * + * @param string $element + * @param string $class + * @return string + */ + protected function _toggleClass($element = 'this', $class = '') + { + $element = $this->_prep_element($element); + return '$('.$element.').toggleClass("'.$class.'");'; + } + + // -------------------------------------------------------------------- + + /** + * Show + * + * Outputs a jQuery show event + * + * @param string - element + * @param string - One of 'slow', 'normal', 'fast', or time in milliseconds + * @param string - Javascript callback function + * @return string + */ + protected function _show($element = 'this', $speed = '', $callback = '') + { + $element = $this->_prep_element($element); + $speed = $this->_validate_speed($speed); + + if ($callback !== '') + { + $callback = ", function(){\n{$callback}\n}"; + } + + return '$('.$element.').show('.$speed.$callback.');'; + } + + // -------------------------------------------------------------------- + + /** + * Updater + * + * An Ajax call that populates the designated DOM node with + * returned content + * + * @param string The element to attach the event to + * @param string the controller to run the call against + * @param string optional parameters + * @return string + */ + + protected function _updater($container = 'this', $controller = '', $options = '') + { + $container = $this->_prep_element($container); + $controller = (strpos('://', $controller) === FALSE) ? $controller : $this->CI->config->site_url($controller); + + // ajaxStart and ajaxStop are better choices here... but this is a stop gap + if ($this->CI->config->item('javascript_ajax_img') === '') + { + $loading_notifier = 'Loading...'; + } + else + { + $loading_notifier = 'Loading'; + } + + $updater = '$('.$container.").empty();\n" // anything that was in... get it out + ."\t\t$(".$container.').prepend("'.$loading_notifier."\");\n"; // to replace with an image + + $request_options = ''; + if ($options !== '') + { + $request_options .= ', {' + .(is_array($options) ? "'".implode("', '", $options)."'" : "'".str_replace(':', "':'", $options)."'") + .'}'; + } + + return $updater."\t\t$($container).load('$controller'$request_options);"; + } + + // -------------------------------------------------------------------- + // Pre-written handy stuff + // -------------------------------------------------------------------- + + /** + * Zebra tables + * + * @param string $class + * @param string $odd + * @param string $hover + * @return string + */ + protected function _zebraTables($class = '', $odd = 'odd', $hover = '') + { + $class = ($class !== '') ? '.'.$class : ''; + $zebra = "\t\$(\"table{$class} tbody tr:nth-child(even)\").addClass(\"{$odd}\");"; + + $this->jquery_code_for_compile[] = $zebra; + + if ($hover !== '') + { + $hover = $this->hover("table{$class} tbody tr", "$(this).addClass('hover');", "$(this).removeClass('hover');"); + } + + return $zebra; + } + + // -------------------------------------------------------------------- + // Plugins + // -------------------------------------------------------------------- + + /** + * Corner Plugin + * + * @link http://www.malsup.com/jquery/corner/ + * @param string $element + * @param string $corner_style + * @return string + */ + public function corner($element = '', $corner_style = '') + { + // may want to make this configurable down the road + $corner_location = '/plugins/jquery.corner.js'; + + if ($corner_style !== '') + { + $corner_style = '"'.$corner_style.'"'; + } + + return '$('.$this->_prep_element($element).').corner('.$corner_style.');'; + } + + // -------------------------------------------------------------------- + + /** + * Modal window + * + * Load a thickbox modal window + * + * @param string $src + * @param bool $relative + * @return void + */ + public function modal($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * Effect + * + * Load an Effect library + * + * @param string $src + * @param bool $relative + * @return void + */ + public function effect($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * Plugin + * + * Load a plugin library + * + * @param string $src + * @param bool $relative + * @return void + */ + public function plugin($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * UI + * + * Load a user interface library + * + * @param string $src + * @param bool $relative + * @return void + */ + public function ui($src, $relative = FALSE) + { + $this->jquery_code_for_load[] = $this->external($src, $relative); + } + + // -------------------------------------------------------------------- + + /** + * Sortable + * + * Creates a jQuery sortable + * + * @param string $element + * @param array $options + * @return string + */ + public function sortable($element, $options = array()) + { + if (count($options) > 0) + { + $sort_options = array(); + foreach ($options as $k=>$v) + { + $sort_options[] = "\n\t\t".$k.': '.$v; + } + $sort_options = implode(',', $sort_options); + } + else + { + $sort_options = ''; + } + + return '$('.$this->_prep_element($element).').sortable({'.$sort_options."\n\t});"; + } + + // -------------------------------------------------------------------- + + /** + * Table Sorter Plugin + * + * @param string table name + * @param string plugin location + * @return string + */ + public function tablesorter($table = '', $options = '') + { + $this->jquery_code_for_compile[] = "\t$(".$this->_prep_element($table).').tablesorter('.$options.");\n"; + } + + // -------------------------------------------------------------------- + // Class functions + // -------------------------------------------------------------------- + + /** + * Add Event + * + * Constructs the syntax for an event, and adds to into the array for compilation + * + * @param string The element to attach the event to + * @param string The code to execute + * @param string The event to pass + * @return string + */ + protected function _add_event($element, $js, $event) + { + if (is_array($js)) + { + $js = implode("\n\t\t", $js); + } + + $event = "\n\t$(".$this->_prep_element($element).').'.$event."(function(){\n\t\t{$js}\n\t});\n"; + $this->jquery_code_for_compile[] = $event; + return $event; + } + + // -------------------------------------------------------------------- + + /** + * Compile + * + * As events are specified, they are stored in an array + * This function compiles them all for output on a page + * + * @param string $view_var + * @param bool $script_tags + * @return void + */ + protected function _compile($view_var = 'script_foot', $script_tags = TRUE) + { + // External references + $external_scripts = implode('', $this->jquery_code_for_load); + $this->CI->load->vars(array('library_src' => $external_scripts)); + + if (count($this->jquery_code_for_compile) === 0) + { + // no inline references, let's just return + return; + } + + // Inline references + $script = '$(document).ready(function() {'."\n" + .implode('', $this->jquery_code_for_compile) + .'});'; + + $output = ($script_tags === FALSE) ? $script : $this->inline($script); + + $this->CI->load->vars(array($view_var => $output)); + } + + // -------------------------------------------------------------------- + + /** + * Clear Compile + * + * Clears the array of script events collected for output + * + * @return void + */ + protected function _clear_compile() + { + $this->jquery_code_for_compile = array(); + } + + // -------------------------------------------------------------------- + + /** + * Document Ready + * + * A wrapper for writing document.ready() + * + * @param array $js + * @return void + */ + protected function _document_ready($js) + { + is_array($js) OR $js = array($js); + + foreach ($js as $script) + { + $this->jquery_code_for_compile[] = $script; + } + } + + // -------------------------------------------------------------------- + + /** + * Script Tag + * + * Outputs the script tag that loads the jquery.js file into an HTML document + * + * @param string $library_src + * @param bool $relative + * @return string + */ + public function script($library_src = '', $relative = FALSE) + { + $library_src = $this->external($library_src, $relative); + $this->jquery_code_for_load[] = $library_src; + return $library_src; + } + + // -------------------------------------------------------------------- + + /** + * Prep Element + * + * Puts HTML element in quotes for use in jQuery code + * unless the supplied element is the Javascript 'this' + * object, in which case no quotes are added + * + * @param string + * @return string + */ + protected function _prep_element($element) + { + if ($element !== 'this') + { + $element = '"'.$element.'"'; + } + + return $element; + } + + // -------------------------------------------------------------------- + + /** + * Validate Speed + * + * Ensures the speed parameter is valid for jQuery + * + * @param string + * @return string + */ + protected function _validate_speed($speed) + { + if (in_array($speed, array('slow', 'normal', 'fast'))) + { + return '"'.$speed.'"'; + } + elseif (preg_match('/[^0-9]/', $speed)) + { + return ''; + } + + return $speed; + } + +} diff --git a/system/libraries/Javascript/index.html b/system/libraries/Javascript/index.html new file mode 100644 index 00000000000..b702fbc3967 --- /dev/null +++ b/system/libraries/Javascript/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index 11d63fe50b9..5d501a966ba 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -686,7 +686,7 @@ protected function _parse_attributes($attributes) /** * Add "rel" attribute * - * @link https://www.w3.org/TR/html5/links.html#linkTypes + * @link http://www.w3.org/TR/html5/links.html#linkTypes * @param string $type * @return string */ diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index dfd0f432e87..9b834f86ae8 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -105,7 +105,23 @@ public function __construct(array $params = array()) $class = new $class($this->_config); if ($class instanceof SessionHandlerInterface) { - session_set_save_handler($class, TRUE); + if (is_php('5.4')) + { + session_set_save_handler($class, TRUE); + } + else + { + session_set_save_handler( + array($class, 'open'), + array($class, 'close'), + array($class, 'read'), + array($class, 'write'), + array($class, 'destroy'), + array($class, 'gc') + ); + + register_shutdown_function('session_write_close'); + } } else { @@ -174,6 +190,9 @@ public function __construct(array $params = array()) */ protected function _ci_load_classes($driver) { + // PHP 5.4 compatibility + interface_exists('SessionHandlerInterface', FALSE) OR require_once(BASEPATH.'libraries/Session/SessionHandlerInterface.php'); + $prefix = config_item('subclass_prefix'); if ( ! class_exists('CI_Session_driver', FALSE)) diff --git a/system/libraries/Session/SessionHandlerInterface.php b/system/libraries/Session/SessionHandlerInterface.php new file mode 100644 index 00000000000..240c5f54e88 --- /dev/null +++ b/system/libraries/Session/SessionHandlerInterface.php @@ -0,0 +1,59 @@ +\?.+)?$#', $this->_config['save_path'], $matches)) + elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(\?.+)?#', $this->_config['save_path'], $matches)) { - $save_path = array('path' => $matches[1]); - } - elseif (preg_match('#(?:tcp://)?([^:?]+)(?:\:(\d+))?(?\?.+)?#', $this->_config['save_path'], $matches)) - { - $save_path = array( - 'host' => $matches[1], - 'port' => empty($matches[2]) ? NULL : $matches[2], - 'timeout' => NULL // We always pass this to Redis::connect(), so it needs to exist + isset($matches[3]) OR $matches[3] = ''; // Just to avoid undefined index notices below + $this->_config['save_path'] = array( + 'host' => $matches[1], + 'port' => empty($matches[2]) ? NULL : $matches[2], + 'password' => preg_match('#auth=([^\s&]+)#', $matches[3], $match) ? $match[1] : NULL, + 'database' => preg_match('#database=(\d+)#', $matches[3], $match) ? (int) $match[1] : NULL, + 'timeout' => preg_match('#timeout=(\d+\.\d+)#', $matches[3], $match) ? (float) $match[1] : NULL ); + + preg_match('#prefix=([^\s&]+)#', $matches[3], $match) && $this->_key_prefix = $match[1]; } else { log_message('error', 'Session: Invalid Redis save path format: '.$this->_config['save_path']); } - if (isset($save_path)) + if ($this->_config['match_ip'] === TRUE) { - if (isset($matches['options'])) - { - $save_path['password'] = preg_match('#auth=([^\s&]+)#', $matches['options'], $match) ? $match[1] : NULL; - $save_path['database'] = preg_match('#database=(\d+)#', $matches['options'], $match) ? (int) $match[1] : NULL; - $save_path['timeout'] = preg_match('#timeout=(\d+\.\d+)#', $matches['options'], $match) ? (float) $match[1] : NULL; - - preg_match('#prefix=([^\s&]+)#', $matches['options'], $match) && $this->_key_prefix = $match[1]; - } - - $this->_config['save_path'] = $save_path; - - if ($this->_config['match_ip'] === TRUE) - { - $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':'; - } + $this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':'; } } @@ -189,30 +176,17 @@ public function open($save_path, $name) } $redis = new Redis(); - $connected = isset($this->_config['save_path']['path']) - ? $redis->connect($this->_config['save_path']['path']) - : $redis->connect( - $this->_config['save_path']['host'], - $this->_config['save_path']['port'], - $this->_config['save_path']['timeout'] - ); - - if ($connected) + if ( ! $redis->connect($this->_config['save_path']['host'], $this->_config['save_path']['port'], $this->_config['save_path']['timeout'])) { - if (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password'])) - { - log_message('error', 'Session: Unable to authenticate to Redis instance.'); - } - elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database'])) - { - log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']); - } - else - { - $this->_redis = $redis; - $this->php5_validate_id(); - return $this->_success; - } + log_message('error', 'Session: Unable to connect to Redis with the configured settings.'); + } + elseif (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password'])) + { + log_message('error', 'Session: Unable to authenticate to Redis instance.'); + } + elseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database'])) + { + log_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']); } else { diff --git a/system/libraries/Session/drivers/index.html b/system/libraries/Session/drivers/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/libraries/Session/drivers/index.html +++ b/system/libraries/Session/drivers/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/libraries/Session/index.html b/system/libraries/Session/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/libraries/Session/index.html +++ b/system/libraries/Session/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/system/libraries/Table.php b/system/libraries/Table.php index 05551269868..06e8d709889 100644 --- a/system/libraries/Table.php +++ b/system/libraries/Table.php @@ -427,7 +427,6 @@ public function clear() $this->rows = array(); $this->heading = array(); $this->auto_heading = TRUE; - $this->caption = NULL; return $this; } diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index 95f765b782c..ed78af18c43 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -1183,7 +1183,7 @@ public function display_errors($open = '

', $close = '

') * Prevents possible script execution from Apache's handling * of files' multiple extensions. * - * @link https://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext + * @link http://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext * * @param string $filename * @return string @@ -1257,7 +1257,9 @@ protected function _file_mime_type($file) */ if (DIRECTORY_SEPARATOR !== '\\') { - $cmd = 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1'; + $cmd = function_exists('escapeshellarg') + ? 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1' + : 'file --brief --mime '.$file['tmp_name'].' 2>&1'; if (function_usable('exec')) { @@ -1274,7 +1276,7 @@ protected function _file_mime_type($file) } } - if (function_usable('shell_exec')) + if ( ! ini_get('safe_mode') && function_usable('shell_exec')) { $mime = @shell_exec($cmd); if (strlen($mime) > 0) diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index 4e8c303c7d2..690b245be98 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -743,7 +743,7 @@ public function sendPayload($msg) { break; } - // See https://bugs.php.net/bug.php?id=39598 and https://secure.php.net/manual/en/function.fwrite.php#96951 + // See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951 elseif ($result === 0) { if ($timestamp === 0) @@ -836,7 +836,9 @@ public function __construct($val, $code = 0, $fstr = '') { // error $this->errno = $code; - $this->errstr = htmlspecialchars($fstr, ENT_XML1 | ENT_NOQUOTES, 'UTF-8'); + $this->errstr = htmlspecialchars($fstr, + (is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES), + 'UTF-8'); } elseif ( ! is_object($val)) { diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php index 4579e8c2b71..52fac2f8a34 100644 --- a/system/libraries/Zip.php +++ b/system/libraries/Zip.php @@ -41,7 +41,7 @@ * Zip Compression Class * * This class is based on a library I found at Zend: - * https://www.zend.com/codex.php?id=696&single=1 + * http://www.zend.com/codex.php?id=696&single=1 * * The original library is a little rough around the edges so I * refactored it and added several additional methods -- Rick Ellis @@ -366,7 +366,7 @@ public function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL) while (FALSE !== ($file = readdir($fp))) { - if ($file === '.' OR $file === '..') + if ($file[0] === '.') { continue; } @@ -520,6 +520,9 @@ protected static function substr($str, $start, $length = NULL) { if (self::$func_overload) { + // mb_substr($str, $start, null, '8bit') returns an empty + // string on PHP 5.3 + isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); return mb_substr($str, $start, $length, '8bit'); } diff --git a/system/libraries/index.html b/system/libraries/index.html index bcb7cae3433..b702fbc3967 100644 --- a/system/libraries/index.html +++ b/system/libraries/index.html @@ -1,5 +1,5 @@ - + 403 Forbidden diff --git a/tests/README.md b/tests/README.md index 365f551a182..04dfbc3d89b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,6 @@ # CodeIgniter Unit Tests # -Status : [![Build Status](https://secure.travis-ci.org/bcit-ci/CodeIgniter.png?branch=develop)](https://travis-ci.org/bcit-ci/CodeIgniter) +Status : [![Build Status](https://secure.travis-ci.org/bcit-ci/CodeIgniter.png?branch=develop)](http://travis-ci.org/bcit-ci/CodeIgniter) ### Introduction: @@ -8,7 +8,7 @@ This is the preliminary CodeIgniter testing documentation. It will cover both internal as well as external APIs and the reasoning behind their implementation, where appropriate. As with all CodeIgniter documentation, this file should maintain a mostly human readable -format to facilitate clean api design. [see https://arrenbrecht.ch/testing/] +format to facilitate clean api design. [see http://arrenbrecht.ch/testing/] *First public draft: everything is subject to change* diff --git a/tests/codeigniter/Setup_test.php b/tests/codeigniter/Setup_test.php deleted file mode 100644 index 5317c56c70b..00000000000 --- a/tests/codeigniter/Setup_test.php +++ /dev/null @@ -1,13 +0,0 @@ -assertTrue(defined('PROJECT_BASE')); - $this->assertTrue(defined('BASEPATH')); - $this->assertTrue(defined('APPPATH')); - $this->assertTrue(defined('VIEWPATH')); - } - -} \ No newline at end of file diff --git a/tests/codeigniter/core/Benchmark_test.php b/tests/codeigniter/core/Benchmark_test.php deleted file mode 100644 index 33bd742b2f6..00000000000 --- a/tests/codeigniter/core/Benchmark_test.php +++ /dev/null @@ -1,67 +0,0 @@ -benchmark = new CI_Benchmark(); - } - - // -------------------------------------------------------------------- - - public function test_mark() - { - $this->assertEmpty($this->benchmark->marker); - - $this->benchmark->mark('code_start'); - - $this->assertCount(1, $this->benchmark->marker); - $this->assertArrayHasKey('code_start', $this->benchmark->marker); - } - - // -------------------------------------------------------------------- - - public function test_elapsed_time() - { - $this->assertEquals('{elapsed_time}', $this->benchmark->elapsed_time()); - $this->assertEmpty($this->benchmark->elapsed_time('undefined_point')); - - $this->benchmark->mark('code_start'); - $this->benchmark->mark('code_end'); - - // Override values, because time isn't testable, but make sure the markers were set - if (isset($this->benchmark->marker['code_start']) && is_float($this->benchmark->marker['code_start'])) - { - $this->benchmark->marker['code_start'] = 1389956144.1944; - } - - if (isset($this->benchmark->marker['code_end']) && is_float($this->benchmark->marker['code_end'])) - { - $this->benchmark->marker['code_end'] = 1389956145.1946; - } - - $this->assertEquals('1', $this->benchmark->elapsed_time('code_start', 'code_end', 0)); - $this->assertEquals('1.0', $this->benchmark->elapsed_time('code_start', 'code_end', 1)); - $this->assertEquals('1.00', $this->benchmark->elapsed_time('code_start', 'code_end', 2)); - $this->assertEquals('1.000', $this->benchmark->elapsed_time('code_start', 'code_end', 3)); - $this->assertEquals('1.0002', $this->benchmark->elapsed_time('code_start', 'code_end', 4)); - $this->assertEquals('1.0002', $this->benchmark->elapsed_time('code_start', 'code_end')); - - // Test with non-existing 2nd marker, but again - we need to override the value - $this->benchmark->elapsed_time('code_start', 'code_end2'); - if (isset($this->benchmark->marker['code_end2']) && is_float($this->benchmark->marker['code_end2'])) - { - $this->benchmark->marker['code_end2'] = 1389956146.2046; - } - - $this->assertEquals('2.0102', $this->benchmark->elapsed_time('code_start', 'code_end2')); - } - - // -------------------------------------------------------------------- - - public function test_memory_usage() - { - $this->assertEquals('{memory_usage}', $this->benchmark->memory_usage()); - } - -} diff --git a/tests/codeigniter/core/Common_test.php b/tests/codeigniter/core/Common_test.php deleted file mode 100644 index effae50c596..00000000000 --- a/tests/codeigniter/core/Common_test.php +++ /dev/null @@ -1,69 +0,0 @@ -assertTrue(is_php('1.2.0')); - $this->assertFalse(is_php('9999.9.9')); - } - - // ------------------------------------------------------------------------ - - public function test_stringify_attributes() - { - $this->assertEquals(' class="foo" id="bar"', _stringify_attributes(array('class' => 'foo', 'id' => 'bar'))); - - $atts = new stdClass; - $atts->class = 'foo'; - $atts->id = 'bar'; - $this->assertEquals(' class="foo" id="bar"', _stringify_attributes($atts)); - - $atts = new stdClass; - $this->assertEquals('', _stringify_attributes($atts)); - - $this->assertEquals(' class="foo" id="bar"', _stringify_attributes('class="foo" id="bar"')); - - $this->assertEquals('', _stringify_attributes(array())); - } - - // ------------------------------------------------------------------------ - - public function test_stringify_js_attributes() - { - $this->assertEquals('width=800,height=600', _stringify_attributes(array('width' => '800', 'height' => '600'), TRUE)); - - $atts = new stdClass; - $atts->width = 800; - $atts->height = 600; - $this->assertEquals('width=800,height=600', _stringify_attributes($atts, TRUE)); - } - - // ------------------------------------------------------------------------ - - public function test_html_escape() - { - $this->assertEquals( - html_escape('Here is a string containing "quoted" text.'), - 'Here is a string containing "quoted" text.' - ); - - $this->assertEquals( - html_escape(array('associative' => 'and', array('multi' => 'dimentional'))), - array('associative' => 'and', array('multi' => 'dimentional')) - ); - } - - // ------------------------------------------------------------------------ - - public function test_remove_invisible_characters() - { - $raw_string = 'Here is a string containing invisible'.chr(0x08).' text %0e.'; - $removed_string = 'Here is a string containing invisible text %0e.'; - $this->assertEquals($removed_string, remove_invisible_characters($raw_string, FALSE)); - - $raw_string = 'Here is a string %0econtaining url_encoded invisible%1F text.'; - $removed_string = 'Here is a string containing url_encoded invisible text.'; - $this->assertEquals($removed_string, remove_invisible_characters($raw_string)); - } -} diff --git a/tests/codeigniter/core/Config_test.php b/tests/codeigniter/core/Config_test.php deleted file mode 100644 index 5201d46dcdd..00000000000 --- a/tests/codeigniter/core/Config_test.php +++ /dev/null @@ -1,233 +0,0 @@ -ci_core_class('cfg'); - - // set predictable config values - $this->cfg = array( - 'index_page' => 'index.php', - 'base_url' => 'http://example.com/', - 'subclass_prefix' => 'MY_' - ); - $this->ci_set_config($this->cfg); - - $this->config = new $cls; - } - - // -------------------------------------------------------------------- - - public function test_item() - { - $this->assertEquals($this->cfg['base_url'], $this->config->item('base_url')); - - // Bad Config value - $this->assertNull($this->config->item('no_good_item')); - - // Index - $this->assertNull($this->config->item('no_good_item', 'bad_index')); - $this->assertNull($this->config->item('no_good_item', 'default')); - } - - // -------------------------------------------------------------------- - - public function test_set_item() - { - $this->assertNull($this->config->item('not_yet_set')); - - $this->config->set_item('not_yet_set', 'is set'); - $this->assertEquals('is set', $this->config->item('not_yet_set')); - } - - // -------------------------------------------------------------------- - - public function test_slash_item() - { - // Bad Config value - $this->assertNull($this->config->slash_item('no_good_item')); - - $this->assertEquals($this->cfg['base_url'], $this->config->slash_item('base_url')); - $this->assertEquals($this->cfg['subclass_prefix'].'/', $this->config->slash_item('subclass_prefix')); - } - - // -------------------------------------------------------------------- - - public function test_base_url() - { - // Test regular base URL - $base_url = $this->cfg['base_url']; - $this->assertEquals($base_url, $this->config->base_url()); - - // Test with URI - $uri = 'test'; - $this->assertEquals($base_url.$uri, $this->config->base_url($uri)); - - // Clear base_url - $this->ci_set_config('base_url', ''); - - // Rerun constructor - $cls =& $this->ci_core_class('cfg'); - $this->config = new $cls; - - // Test default base - $this->assertEquals('http://localhost/', $this->config->base_url()); - - // Capture server vars - $old_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : NULL; - $old_script_name = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : NULL; - $old_script_filename = $_SERVER['SCRIPT_FILENAME']; - $old_https = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : NULL; - $old_server_addr = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : NULL; - - // The 'Host' header is user input and must not be trusted - $_SERVER['HTTP_HOST'] = 'test.com'; - $this->config = new $cls; - $this->assertEquals('http://localhost/', $this->config->base_url()); - - // However, we may fallback to the server's IP address - $_SERVER['SERVER_ADDR'] = '127.0.0.1'; - $_SERVER['SCRIPT_NAME'] = '/base_test.php'; - $_SERVER['SCRIPT_FILENAME'] = '/foo/bar/base_test.php'; - $this->config = new $cls; - $this->assertEquals('http://127.0.0.1/', $this->config->base_url()); - - // Making sure that HTTPS and URI path are also detected - $_SERVER['HTTPS'] = 'on'; - $_SERVER['SCRIPT_NAME'] = '/path/base_test.php'; - $_SERVER['SCRIPT_FILENAME'] = '/foo/bar/path/base_test.php'; - $this->config = new $cls; - $this->assertEquals('https://127.0.0.1/path/', $this->config->base_url()); - - // Restore server vars - $_SERVER['HTTP_HOST'] = $old_host; - $_SERVER['SCRIPT_NAME'] = $old_script_name; - $_SERVER['SCRIPT_FILENAME'] = $old_script_filename; - $_SERVER['HTTPS'] = $old_https; - $_SERVER['SERVER_ADDR'] = $old_server_addr; - } - - // -------------------------------------------------------------------- - - public function test_site_url() - { - $base_url = $this->cfg['base_url']; - $index_page = $this->cfg['index_page']; - $this->assertEquals($base_url.$index_page, $this->config->site_url()); - - $old_base = $this->config->item('base_url'); - $this->config->set_item('base_url', ''); - - $q_string = $this->config->item('enable_query_strings'); - $this->config->set_item('enable_query_strings', FALSE); - - $uri = 'test'; - $uri2 = '1'; - $this->assertEquals($index_page.'/'.$uri, $this->config->site_url($uri)); - $this->assertEquals($index_page.'/'.$uri.'/'.$uri2, $this->config->site_url(array($uri, $uri2))); - - $this->assertEquals($index_page.'/test/', $this->config->site_url('test/')); - - $suffix = 'ing'; - $this->config->set_item('url_suffix', $suffix); - - $arg = 'pass'; - $this->assertEquals($index_page.'/'.$uri.$suffix, $this->config->site_url($uri)); - $this->assertEquals($index_page.'/'.$uri.$suffix.'?'.$arg, $this->config->site_url($uri.'?'.$arg)); - - $this->config->set_item('url_suffix', FALSE); - $this->config->set_item('enable_query_strings', TRUE); - - $this->assertEquals($index_page.'?'.$uri, $this->config->site_url($uri)); - $this->assertEquals($index_page.'?0='.$uri.'&1='.$uri2, $this->config->site_url(array($uri, $uri2))); - - $this->config->set_item('base_url', $old_base); - - $this->assertEquals($base_url.$index_page.'?'.$uri, $this->config->site_url($uri)); - - // back to home base - $this->config->set_item('enable_query_strings', $q_string); - } - - // -------------------------------------------------------------------- - - public function test_load() - { - // Test regular load - $file = 'test.php'; - $key = 'testconfig'; - $val = 'my_value'; - $cfg = array($key => $val); - $this->ci_vfs_create($file, 'ci_app_root, 'config'); - $this->assertTrue($this->config->load($file)); - $this->assertEquals($val, $this->config->item($key)); - - // Test reload - value should not change - $val2 = 'new_value'; - $cfg = array($key => $val2); - $this->ci_vfs_create($file, 'ci_app_root, 'config'); - $this->assertTrue($this->config->load($file)); - $this->assertEquals($val, $this->config->item($key)); - - // Test section load - $file = 'secttest'; - $cfg = array( - 'one' => 'prime', - 'two' => 2, - 'three' => TRUE - ); - $this->ci_vfs_create($file.'.php', 'ci_app_root, 'config'); - $this->assertTrue($this->config->load($file, TRUE)); - $this->assertEquals($cfg, $this->config->item($file)); - - // Test section merge - $cfg2 = array( - 'three' => 'tres', - 'number' => 42, - 'letter' => 'Z' - ); - - $pkg_dir = 'package'; - $this->ci_vfs_create( - $file.'.php', - 'ci_app_root, - array($pkg_dir, 'config') - ); - array_unshift($this->config->_config_paths, $this->ci_vfs_path($pkg_dir.'/', APPPATH)); - $this->assertTrue($this->config->load($file, TRUE)); - $this->assertEquals(array_merge($cfg, $cfg2), $this->config->item($file)); - array_shift($this->config->_config_paths); - - // Test graceful fail of invalid file - $file = 'badfile'; - $this->ci_vfs_create($file, '', $this->ci_app_root, 'config'); - $this->assertFalse($this->config->load($file, FALSE, TRUE)); - - // Test regular fail of invalid file - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Your '.$this->ci_vfs_path('config/'.$file.'.php', APPPATH). - ' file does not appear to contain a valid configuration array.' - ); - $this->assertNull($this->config->load($file)); - } - - // -------------------------------------------------------------------- - - public function test_load_nonexistent() - { - // Test graceful fail of nonexistent file - $this->assertFalse($this->config->load('not_config_file', FALSE, TRUE)); - - // Test regular fail - $file = 'absentia'; - $this->setExpectedException( - 'RuntimeException', - 'CI Error: The configuration file '.$file.'.php does not exist.' - ); - $this->assertNull($this->config->load($file)); - } - -} diff --git a/tests/codeigniter/core/Input_test.php b/tests/codeigniter/core/Input_test.php deleted file mode 100644 index 07a99e13672..00000000000 --- a/tests/codeigniter/core/Input_test.php +++ /dev/null @@ -1,317 +0,0 @@ -ci_set_config('allow_get_array', TRUE); - $this->ci_set_config('global_xss_filtering', FALSE); - $this->ci_set_config('csrf_protection', FALSE); - - $security = new Mock_Core_Security('UTF-8'); - $this->input = new CI_Input($security); - } - - // -------------------------------------------------------------------- - - public function test_get_not_exists() - { - $this->assertSame(array(), $this->input->get()); - $this->assertNull($this->input->get('foo')); - } - - // -------------------------------------------------------------------- - - public function test_get_exist() - { - $_SERVER['REQUEST_METHOD'] = 'GET'; - $_GET['foo'] = 'bar'; - - $this->assertArrayHasKey('foo', $this->input->get()); - $this->assertEquals('bar', $this->input->get('foo')); - } - - // -------------------------------------------------------------------- - - public function test_get_exist_with_xss_clean() - { - $_SERVER['REQUEST_METHOD'] = 'GET'; - $_GET['harm'] = "Hello, i try to your site"; - - $this->assertArrayHasKey('harm', $this->input->get()); - $this->assertEquals("Hello, i try to your site", $this->input->get('harm')); - $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $this->input->get('harm', TRUE)); - } - - // -------------------------------------------------------------------- - - public function test_post_not_exists() - { - $this->assertSame(array(), $this->input->post()); - $this->assertNull($this->input->post('foo')); - } - - // -------------------------------------------------------------------- - - public function test_post_exist() - { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST['foo'] = 'bar'; - - $this->assertArrayHasKey('foo', $this->input->post()); - $this->assertEquals('bar', $this->input->post('foo')); - } - - // -------------------------------------------------------------------- - - public function test_post_exist_with_xss_clean() - { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST['harm'] = "Hello, i try to your site"; - - $this->assertArrayHasKey('harm', $this->input->post()); - $this->assertEquals("Hello, i try to your site", $this->input->post('harm')); - $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $this->input->post('harm', TRUE)); - } - - // -------------------------------------------------------------------- - - public function test_post_get() - { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST['foo'] = 'bar'; - - $this->assertEquals('bar', $this->input->post_get('foo')); - } - - // -------------------------------------------------------------------- - - public function test_post_get_array_notation() - { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST['foo']['bar'] = 'baz'; - $barArray = array('bar' => 'baz'); - - $this->assertEquals('baz', $this->input->get_post('foo[bar]')); - $this->assertEquals($barArray, $this->input->get_post('foo[]')); - $this->assertNull($this->input->get_post('foo[baz]')); - - $this->assertEquals('baz', $this->input->post_get('foo[bar]')); - $this->assertEquals($barArray, $this->input->post_get('foo[]')); - $this->assertNull($this->input->post_get('foo[baz]')); - } - - // -------------------------------------------------------------------- - - public function test_get_post() - { - $_SERVER['REQUEST_METHOD'] = 'GET'; - $_GET['foo'] = 'bar'; - - $this->assertEquals('bar', $this->input->get_post('foo')); - } - - // -------------------------------------------------------------------- - - public function test_get_post_array_notation() - { - $_SERVER['REQUEST_METHOD'] = 'GET'; - $_GET['foo']['bar'] = 'baz'; - $barArray = array('bar' => 'baz'); - - $this->assertEquals('baz', $this->input->get_post('foo[bar]')); - $this->assertEquals($barArray, $this->input->get_post('foo[]')); - $this->assertNull($this->input->get_post('foo[baz]')); - - $this->assertEquals('baz', $this->input->post_get('foo[bar]')); - $this->assertEquals($barArray, $this->input->post_get('foo[]')); - $this->assertNull($this->input->post_get('foo[baz]')); - } - - // -------------------------------------------------------------------- - - public function test_cookie() - { - $_COOKIE['foo'] = 'bar'; - $this->assertEquals('bar', $this->input->cookie('foo')); - $this->assertNull($this->input->cookie('bar')); - } - - // -------------------------------------------------------------------- - - public function test_server() - { - $this->assertEquals('GET', $this->input->server('REQUEST_METHOD')); - } - - // -------------------------------------------------------------------- - - public function test_fetch_from_array() - { - $reflection = new ReflectionMethod($this->input, '_fetch_from_array'); - $reflection->setAccessible(TRUE); - - $data = array( - 'foo' => 'bar', - 'harm' => 'Hello, i try to your site', - ); - - $foo = $reflection->invokeArgs($this->input, [&$data, 'foo']); - $harm = $reflection->invokeArgs($this->input, [&$data, 'harm']); - $harmless = $reflection->invokeArgs($this->input, [&$data, 'harm', TRUE]); - - $this->assertEquals('bar', $foo); - $this->assertEquals("Hello, i try to your site", $harm); - $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless); - - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST['foo']['bar'] = 'baz'; - $barArray = array('bar' => 'baz'); - - $this->assertEquals('baz', $this->input->post('foo[bar]')); - $this->assertEquals($barArray, $this->input->post('foo[]')); - $this->assertNull($this->input->post('foo[baz]')); - } - - // -------------------------------------------------------------------- - - public function test_valid_ip() - { - $this->assertTrue($this->input->valid_ip('192.18.0.1')); - $this->assertTrue($this->input->valid_ip('192.18.0.1', 'ipv4')); - $this->assertFalse($this->input->valid_ip('555.0.0.0')); - $this->assertFalse($this->input->valid_ip('2001:db8:0:85a3::ac1f:8001', 'ipv4')); - - // v6 tests - $this->assertFalse($this->input->valid_ip('192.18.0.1', 'ipv6')); - - $ip_v6 = array( - '2001:0db8:0000:85a3:0000:0000:ac1f:8001', - '2001:db8:0:85a3:0:0:ac1f:8001', - '2001:db8:0:85a3::ac1f:8001' - ); - - foreach ($ip_v6 as $ip) - { - $this->assertTrue($this->input->valid_ip($ip)); - $this->assertTrue($this->input->valid_ip($ip, 'ipv6')); - } - } - - // -------------------------------------------------------------------- - - public function test_method() - { - $_SERVER['REQUEST_METHOD'] = 'GET'; - $this->assertEquals('get', $this->input->method()); - $this->assertEquals('GET', $this->input->method(TRUE)); - $_SERVER['REQUEST_METHOD'] = 'POST'; - $this->assertEquals('post', $this->input->method()); - $this->assertEquals('POST', $this->input->method(TRUE)); - } - - // -------------------------------------------------------------------- - - public function test_is_ajax_request() - { - $this->assertFalse($this->input->is_ajax_request()); - $_SERVER['HTTP_X_REQUESTED_WITH'] = 'test'; - $this->assertFalse($this->input->is_ajax_request()); - $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; - $this->assertTrue($this->input->is_ajax_request()); - } - - // -------------------------------------------------------------------- - - public function test_input_stream() - { - $this->markTestSkipped('TODO: Find a way to test input://'); - } - - // -------------------------------------------------------------------- - - public function test_set_cookie() - { - $this->markTestSkipped('TODO: Find a way to test HTTP headers'); - } - - // -------------------------------------------------------------------- - - public function test_get_request_header() - { - $this->markTestSkipped('TODO: Find a way to test HTTP headers'); - } - - // -------------------------------------------------------------------- - - public function test_ip_address() - { - $reflection = new ReflectionProperty($this->input, 'ip_address'); - $reflection->setAccessible(TRUE); - - $reflection->setValue($this->input, '127.0.0.1'); - $this->assertEquals('127.0.0.1', $this->input->ip_address()); - - // 127.0.0.1 is set in our Bootstrap file - $reflection->setValue($this->input, FALSE); - $this->assertEquals('127.0.0.1', $this->input->ip_address()); - - // Invalid - $_SERVER['REMOTE_ADDR'] = 'invalid_ip_address'; - $reflection->setValue($this->input, FALSE); // reset cached value - $this->assertEquals('0.0.0.0', $this->input->ip_address()); - - $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; - - // Proxy_ips tests - $reflection->setValue($this->input, FALSE); - $this->ci_set_config('proxy_ips', '127.0.0.3, 127.0.0.4, 127.0.0.2'); - $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.2'; - $this->assertEquals('127.0.0.1', $this->input->ip_address()); - - // Invalid spoof - $reflection->setValue($this->input, FALSE); - $this->ci_set_config('proxy_ips', 'invalid_ip_address'); - $_SERVER['HTTP_CLIENT_IP'] = 'invalid_ip_address'; - $this->assertEquals('127.0.0.1', $this->input->ip_address()); - - $reflection->setValue($this->input, FALSE); - $this->ci_set_config('proxy_ips', 'http://foo/bar/baz, 127.0.0.1/1'); - $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1'; - $this->assertEquals('127.0.0.1', $this->input->ip_address()); - - $reflection->setValue($this->input, FALSE); - $this->ci_set_config('proxy_ips', 'http://foo/bar/baz, 127.0.0.2'); - $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.2'; - $_SERVER['REMOTE_ADDR'] = '127.0.0.2'; - $this->assertEquals('127.0.0.2', $this->input->ip_address()); - - // IPv6 - $reflection->setValue($this->input, FALSE); - $this->ci_set_config('proxy_ips', 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329/1, FE80:0000:0000:0000:0202:B3FF:FE1E:8300/2'); - $_SERVER['HTTP_CLIENT_IP'] = 'FE80:0000:0000:0000:0202:B3FF:FE1E:8300'; - $_SERVER['REMOTE_ADDR'] = 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329'; - $this->assertEquals('FE80:0000:0000:0000:0202:B3FF:FE1E:8300', $this->input->ip_address()); - - $reflection->setValue($this->input, FALSE); - $this->ci_set_config('proxy_ips', '0::/32'); - $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.7'; - $_SERVER['REMOTE_ADDR'] = '0000:0000:0000:0000:0000:0000:0000:0001'; - $this->assertEquals('127.0.0.7', $this->input->ip_address()); - - $reflection->setValue($this->input, FALSE); - $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; // back to reality - } - - // -------------------------------------------------------------------- - - public function test_user_agent() - { - $_SERVER['HTTP_USER_AGENT'] = 'test'; - $this->assertEquals('test', $this->input->user_agent()); - } -} diff --git a/tests/codeigniter/core/Lang_test.php b/tests/codeigniter/core/Lang_test.php deleted file mode 100644 index 4958f42e12c..00000000000 --- a/tests/codeigniter/core/Lang_test.php +++ /dev/null @@ -1,101 +0,0 @@ -ci_core_class('load'); - $this->ci_instance_var('load', new $loader_cls); - $cls = $this->ci_core_class('lang'); - $this->lang = new $cls; - } - - // -------------------------------------------------------------------- - - public function test_load() - { - // Regular usage - $this->ci_vfs_clone('system/language/english/profiler_lang.php'); - $this->assertTrue($this->lang->load('profiler', 'english')); - $this->assertEquals('URI STRING', $this->lang->language['profiler_uri_string']); - - // Already loaded file - $this->assertNull($this->lang->load('profiler', 'english')); - - // Unspecified language (defaults to english) - $this->ci_vfs_clone('system/language/english/date_lang.php'); - $this->assertTrue($this->lang->load('date')); - $this->assertEquals('Year', $this->lang->language['date_year']); - - // A language other than english - $this->ci_vfs_clone('system/language/english/email_lang.php', 'system/language/german/'); - $this->assertTrue($this->lang->load('email', 'german')); - $this->assertEquals('german', $this->lang->is_loaded['email_lang.php']); - - // Non-existent file - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested language file: language/english/nonexistent_lang.php' - ); - $this->lang->load('nonexistent'); - } - - // -------------------------------------------------------------------- - - public function test_non_alpha_idiom() - { - // Non-alpha idiom (should act the same as unspecified language) - // test with existing file - $this->ci_vfs_clone('system/language/english/number_lang.php'); - $this->ci_vfs_clone('system/language/english/number_lang.php', 'system/language/123funny/'); - $this->assertTrue($this->lang->load('number', '123funny')); - $this->assertEquals('Bytes', $this->lang->language['bytes']); - - // test without existing file - $this->ci_vfs_clone('system/language/english/email_lang.php'); - $this->assertTrue($this->lang->load('email', '456funny')); - $this->assertEquals('You did not specify a SMTP hostname.', $this->lang->language['email_no_hostname']); - } - - // -------------------------------------------------------------------- - - public function test_multiple_file_load() - { - // Multiple files - $this->ci_vfs_clone('system/language/english/profiler_lang.php'); - $files = array( - 0 => 'profiler', - 1 => 'nonexistent' - ); - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested language file: language/english/nonexistent_lang.php' - ); - $this->lang->load($files, 'english'); - } - - // -------------------------------------------------------------------- - - public function test_alternative_path_load() - { - // Alternative Path - $this->ci_vfs_clone('system/language/english/profiler_lang.php'); - $this->assertTrue($this->lang->load('profiler', 'english', FALSE, TRUE, 'vfs://system/')); - } - - // -------------------------------------------------------------------- - - /** - * @depends test_load - */ - public function test_line() - { - $this->ci_vfs_clone('system/language/english/profiler_lang.php'); - $this->lang->load('profiler', 'english'); - $this->assertEquals('URI STRING', $this->lang->line('profiler_uri_string')); - $this->assertFalse($this->lang->line('nonexistent_string')); - $this->assertFalse($this->lang->line(NULL)); - } -} diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php deleted file mode 100644 index df698f30ce5..00000000000 --- a/tests/codeigniter/core/Loader_test.php +++ /dev/null @@ -1,602 +0,0 @@ -ci_core_class('loader'); - $this->load = new $loader(); - - // Get CI instance - $this->ci_obj = $this->ci_instance(); - - // Set subclass prefix - $this->prefix = 'MY_'; - $this->ci_set_config('subclass_prefix', $this->prefix); - } - - // -------------------------------------------------------------------- - - public function test_library() - { - // Test getting CI_Loader object - $this->assertInstanceOf('CI_Loader', $this->load->library(NULL)); - - // Create library in VFS - $lib = 'unit_test_lib'; - $class = 'CI_'.ucfirst($lib); - $this->ci_vfs_create(ucfirst($lib), 'ci_base_root, 'libraries'); - - // Test is_loaded fail - $this->assertFalse($this->load->is_loaded(ucfirst($lib))); - - // Test loading as an array. - $this->assertInstanceOf('CI_Loader', $this->load->library(array($lib))); - $this->assertTrue(class_exists($class), $class.' does not exist'); - $this->assertAttributeInstanceOf($class, $lib, $this->ci_obj); - - // Create library in VFS - $lib = array('unit_test_lib' => 'unit_test_lib'); - - // Test loading as an array (int). - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - $this->assertTrue(class_exists($class), $class.' does not exist'); - - // Test a string given to params - $this->assertInstanceOf('CI_Loader', $this->load->library($lib, ' ')); - - // test non existent lib - $lib = 'non_existent_test_lib'; - - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested class: '.ucfirst($lib) - ); - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - } - - // -------------------------------------------------------------------- - - public function test_bad_library() - { - $lib = 'bad_test_lib'; - $this->ci_vfs_create(ucfirst($lib), '', $this->ci_app_root, 'libraries'); - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Non-existent class: '.ucfirst($lib) - ); - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - } - - // -------------------------------------------------------------------- - - public function test_library_extension() - { - // Create library and extension in VFS - $name = 'ext_test_lib'; - $lib = ucfirst($name); - $class = 'CI_'.$lib; - $ext = $this->prefix.$lib; - $this->ci_vfs_create($lib, 'ci_base_root, 'libraries'); - $this->ci_vfs_create($ext, 'ci_app_root, 'libraries'); - - // Test loading with extension - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - $this->assertTrue(class_exists($class), $class.' does not exist'); - $this->assertTrue(class_exists($ext), $ext.' does not exist'); - $this->assertAttributeInstanceOf($class, $name, $this->ci_obj); - $this->assertAttributeInstanceOf($ext, $name, $this->ci_obj); - - // Test reloading with object name - $obj = 'exttest'; - $this->assertInstanceOf('CI_Loader', $this->load->library($lib, NULL, $obj)); - $this->assertAttributeInstanceOf($class, $obj, $this->ci_obj); - $this->assertAttributeInstanceOf($ext, $obj, $this->ci_obj); - - // Test reloading - unset($this->ci_obj->$name); - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - $this->assertObjectHasAttribute($name, $this->ci_obj); - - // Create baseless library - $name = 'ext_baseless_lib'; - $lib = ucfirst($name); - $class = $this->prefix.$lib; - $this->ci_vfs_create($class, 'ci_app_root, 'libraries'); - - // Test missing base class - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested class: '.$lib - ); - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - } - - // -------------------------------------------------------------------- - - public function test_library_config() - { - // Create library in VFS - $lib = 'unit_test_config_lib'; - $class = 'CI_'.ucfirst($lib); - $content = 'config = $params; } }'; - $this->ci_vfs_create(ucfirst($lib), $content, $this->ci_base_root, 'libraries'); - - // Create config file - $cfg = array( - 'foo' => 'bar', - 'bar' => 'baz', - 'baz' => false - ); - $this->ci_vfs_create($lib, 'ci_app_root, 'config'); - - // Test object name and config - $obj = 'testy'; - $this->assertInstanceOf('CI_Loader', $this->load->library($lib, NULL, $obj)); - $this->assertTrue(class_exists($class), $class.' does not exist'); - $this->assertAttributeInstanceOf($class, $obj, $this->ci_obj); - $this->assertEquals($cfg, $this->ci_obj->$obj->config); - - // Test is_loaded - $this->assertEquals($obj, $this->load->is_loaded(ucfirst($lib))); - - // Test to load another class with the same object name - $lib = 'another_test_lib'; - $class = ucfirst($lib); - $this->ci_vfs_create(ucfirst($lib), 'ci_app_root, 'libraries'); - $this->setExpectedException( - 'RuntimeException', - "CI Error: Resource '".$obj."' already exists and is not a ".$class." instance." - ); - $this->load->library($lib, NULL, $obj); - } - - // -------------------------------------------------------------------- - - public function test_load_library_in_application_dir() - { - // Create library in VFS - $lib = 'super_test_library'; - $class = ucfirst($lib); - $this->ci_vfs_create(ucfirst($lib), 'ci_app_root, 'libraries'); - - // Load library - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - - // Was the model class instantiated. - $this->assertTrue(class_exists($class), $class.' does not exist'); - $this->assertAttributeInstanceOf($class, $lib, $this->ci_obj); - } - - // -------------------------------------------------------------------- - - public function test_driver() - { - // Call the autoloader, to include system/libraries/Driver.php - class_exists('CI_Driver_Library', TRUE); - - // Create driver in VFS - $driver = 'unit_test_driver'; - $dir = ucfirst($driver); - $class = 'CI_'.$dir; - $content = 'ci_vfs_create(ucfirst($driver), $content, $this->ci_base_root, 'libraries/'.$dir); - - // Test loading as an array. - $this->assertInstanceOf('CI_Loader', $this->load->driver(array($driver))); - $this->assertTrue(class_exists($class), $class.' does not exist'); - $this->assertAttributeInstanceOf($class, $driver, $this->ci_obj); - - // Test loading as a library with a name - $obj = 'testdrive'; - $this->assertInstanceOf('CI_Loader', $this->load->library($driver, NULL, $obj)); - $this->assertAttributeInstanceOf($class, $obj, $this->ci_obj); - - // Test a string given to params - $this->assertInstanceOf('CI_Loader', $this->load->driver($driver, ' ')); - } - - // -------------------------------------------------------------------- - - public function test_models() - { - $this->ci_set_core_class('model', 'CI_Model'); - - // Create model in VFS - $model = 'Unit_test_model'; - $content = 'ci_vfs_create($model, $content, $this->ci_app_root, 'models'); - - // Load model - $this->assertInstanceOf('CI_Loader', $this->load->model($model)); - - // Was the model class instantiated. - $this->assertTrue(class_exists($model)); - $this->assertObjectHasAttribute($model, $this->ci_obj); - - // Test no model given - $this->assertInstanceOf('CI_Loader', $this->load->model('')); - } - - // -------------------------------------------------------------------- - - public function test_model_subdir() - { - // Make sure base class is loaded - we'll test _ci_include later - $this->ci_core_class('model'); - - // Create modelin VFS - $model = 'Test_sub_model'; - $base = 'CI_Model'; - $subdir = 'cars'; - $this->ci_vfs_create($model, 'ci_app_root, - array('models', $subdir)); - - // Load model - $name = 'testors'; - $this->assertInstanceOf('CI_Loader', $this->load->model($subdir.'/'.$model, $name)); - - // Was the model class instantiated? - $this->assertTrue(class_exists($model)); - $this->assertObjectHasAttribute($name, $this->ci_obj); - $this->assertAttributeInstanceOf($base, $name, $this->ci_obj); - $this->assertAttributeInstanceOf($model, $name, $this->ci_obj); - - // Test name conflict - $obj = 'conflict'; - $this->ci_obj->$obj = new stdClass(); - $this->setExpectedException( - 'RuntimeException', - 'The model name you are loading is the name of a resource that is already being used: '.$obj - ); - $this->load->model('not_real', $obj); - } - - // -------------------------------------------------------------------- - - public function test_non_existent_model() - { - $this->setExpectedException( - 'RuntimeException', - 'Unable to locate the model you have specified: Ci_test_nonexistent_model.php' - ); - - $this->load->model('ci_test_nonexistent_model.php'); - } - - // -------------------------------------------------------------------- - - public function test_invalid_model() - { - $this->ci_set_core_class('model', 'CI_Model'); - - // Create model in VFS - $model = 'Unit_test_invalid_model'; - $content = 'ci_vfs_create($model, $content, $this->ci_app_root, 'models'); - - // Test no extending - $this->setExpectedException( - 'RuntimeException', - 'Class '.$model.' doesn\'t extend CI_Model' - ); - $this->load->model($model); - } - - // -------------------------------------------------------------------- - - // public function testDatabase() - // { - // $this->assertInstanceOf('CI_Loader', $this->load->database()); - // $this->assertInstanceOf('CI_Loader', $this->load->dbutil()); - // } - - // -------------------------------------------------------------------- - - public function test_load_view() - { - // Create view in VFS - $view = 'unit_test_view'; - $var = 'hello'; - $value = 'World!'; - $content = 'This is my test page. '; - $this->ci_vfs_create($view, $content.'ci_app_root, 'views'); - - // Test returning view - $out = $this->load->view($view, array($var => $value), TRUE); - $this->assertEquals($content.$value, $out); - - // Mock output class - $output = $this->getMockBuilder('CI_Output')->setMethods(array('append_output'))->getMock(); - $output->expects($this->once())->method('append_output')->with($content.$value); - $this->ci_instance_var('output', $output); - - // Test view output and $vars as an object - $vars = new stdClass(); - $vars->$var = $value; - $this->assertInstanceOf('CI_Loader', $this->load->view($view, $vars)); - } - - // -------------------------------------------------------------------- - - public function test_non_existent_view() - { - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested file: ci_test_nonexistent_view.php' - ); - - $this->load->view('ci_test_nonexistent_view', array('foo' => 'bar')); - } - - // -------------------------------------------------------------------- - - public function test_file() - { - // Create view in VFS - $dir = 'views'; - $file = 'ci_test_mock_file'; - $content = 'Here is a test file, which we will load now.'; - $this->ci_vfs_create($file, $content, $this->ci_app_root, $dir); - - // Just like load->view(), take the output class out of the mix here. - $out = $this->load->file(APPPATH.$dir.'/'.$file.'.php', TRUE); - $this->assertEquals($content, $out); - - // Test non-existent file - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested file: ci_test_file_not_exists' - ); - - $this->load->file('ci_test_file_not_exists', TRUE); - } - - // -------------------------------------------------------------------- - - public function test_vars() - { - $key1 = 'foo'; - $val1 = 'bar'; - $key2 = 'boo'; - $val2 = 'hoo'; - $this->assertInstanceOf('CI_Loader', $this->load->vars(array($key1 => $val1))); - $this->assertInstanceOf('CI_Loader', $this->load->vars($key2, $val2)); - $this->assertEquals($val1, $this->load->get_var($key1)); - $this->assertEquals(array($key1 => $val1, $key2 => $val2), $this->load->get_vars()); - } - - // -------------------------------------------------------------------- - - public function test_clear_vars() - { - $key1 = 'foo'; - $val1 = 'bar'; - $key2 = 'boo'; - $val2 = 'hoo'; - $this->assertInstanceOf('CI_Loader', $this->load->vars(array($key1 => $val1))); - $this->assertInstanceOf('CI_Loader', $this->load->vars($key2, $val2)); - $this->assertEquals($val1, $this->load->get_var($key1)); - $this->assertEquals(array($key1 => $val1, $key2 => $val2), $this->load->get_vars()); - - $this->assertInstanceOf('CI_Loader', $this->load->clear_vars()); - $this->assertEquals('', $this->load->get_var($key1)); - $this->assertEquals('', $this->load->get_var($key2)); - } - - // -------------------------------------------------------------------- - - public function test_helper() - { - // Create helper in VFS - $helper = 'test'; - $func = '_my_helper_test_func'; - $content = 'ci_vfs_create($helper.'_helper', $content, $this->ci_base_root, 'helpers'); - - // Create helper extension - $exfunc = '_my_extension_func'; - $content = 'ci_vfs_create($this->prefix.$helper.'_helper', $content, $this->ci_app_root, 'helpers'); - - // Load helper - $this->assertInstanceOf('CI_Loader', $this->load->helper($helper)); - $this->assertTrue(function_exists($func), $func.' does not exist'); - $this->assertTrue(function_exists($exfunc), $exfunc.' does not exist'); - - // Create baseless extension - $ext = 'bad_ext'; - $this->ci_vfs_create($this->prefix.$ext.'_helper', '', $this->ci_app_root, 'helpers'); - - // Test bad extension - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested file: helpers/'.$ext.'_helper.php' - ); - $this->load->helper($ext); - } - - // -------------------------------------------------------------------- - - public function test_non_existent_helper() - { - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested file: helpers/bad_helper.php' - ); - $this->load->helper('bad'); - } - - // -------------------------------------------------------------------- - - public function test_loading_multiple_helpers() - { - // Create helpers in VFS - $helpers = array(); - $funcs = array(); - $files = array(); - for ($i = 1; $i <= 3; ++$i) { - $helper = 'test'.$i; - $helpers[] = $helper; - $func = '_my_helper_test_func'.$i; - $funcs[] = $func; - $files[$helper.'_helper'] = 'ci_vfs_create($files, NULL, $this->ci_base_root, 'helpers'); - - // Load helpers - $this->assertInstanceOf('CI_Loader', $this->load->helpers($helpers)); - - // Verify helper existence - foreach ($funcs as $func) { - $this->assertTrue(function_exists($func), $func.' does not exist'); - } - } - - // -------------------------------------------------------------------- - - public function test_language() - { - // Mock lang class and test load call - $file = 'test'; - $lang = $this->getMockBuilder('CI_Lang')->setMethods(array('load'))->getMock(); - $lang->expects($this->once())->method('load')->with($file); - $this->ci_instance_var('lang', $lang); - $this->assertInstanceOf('CI_Loader', $this->load->language($file)); - } - - // -------------------------------------------------------------------- - - public function test_packages() - { - // Create model in VFS package path - $dir = 'third-party'; - $lib = 'unit_test_package'; - $class = ucfirst($lib); - $this->ci_vfs_create(ucfirst($lib), 'ci_app_root, array($dir, 'libraries')); - - // Get paths - $paths = $this->load->get_package_paths(TRUE); - - // Test failed load without path - $this->setExpectedException( - 'RuntimeException', - 'CI Error: Unable to load the requested class: '.ucfirst($lib) - ); - $this->load->library($lib); - - // Add path and verify - $path = APPPATH.$dir.'/'; - $this->assertInstanceOf('CI_Loader', $this->load->add_package_path($path)); - $this->assertContains($path, $this->load->get_package_paths(TRUE)); - - // Test successful load - $this->assertInstanceOf('CI_Loader', $this->load->library($lib)); - $this->assertTrue(class_exists($class), $class.' does not exist'); - - // Add another path - $path2 = APPPATH.'another/'; - $this->assertInstanceOf('CI_Loader', $this->load->add_package_path($path2)); - $this->assertContains($path2, $this->load->get_package_paths(TRUE)); - - // Remove last path - $this->assertInstanceOf('CI_Loader', $this->load->remove_package_path()); - $this->assertNotContains($path2, $this->load->get_package_paths(TRUE)); - - // Remove path and verify restored paths - $this->assertInstanceOf('CI_Loader', $this->load->remove_package_path($path)); - $this->assertEquals($paths, $this->load->get_package_paths(TRUE)); - } - - // -------------------------------------------------------------------- - - public function test_remove_package_path() - { - $dir = 'third-party'; - $path = APPPATH.$dir.'/'; - $path2 = APPPATH.'another/'; - $paths = $this->load->get_package_paths(TRUE); - - $this->assertInstanceOf('CI_Loader', $this->load->add_package_path($path)); - $this->assertInstanceOf('CI_Loader', $this->load->remove_package_path($path)); - $this->assertEquals($paths, $this->load->get_package_paths(TRUE)); - - $this->assertInstanceOf('CI_Loader', $this->load->add_package_path($path2)); - $this->assertInstanceOf('CI_Loader', $this->load->remove_package_path()); - $this->assertNotContains($path2, $this->load->get_package_paths(TRUE)); - } - - // -------------------------------------------------------------------- - - public function test_load_config() - { - $cfg = 'someconfig'; - $this->assertTrue($this->load->config($cfg, FALSE)); - $this->assertContains($cfg, $this->ci_obj->config->loaded); - } - - // -------------------------------------------------------------------- - - public function test_initialize() - { - // Create helper in VFS - $helper = 'autohelp'; - $hlp_func = '_autohelp_test_func'; - $content = 'ci_vfs_create($helper.'_helper', $content, $this->ci_app_root, 'helpers'); - - // Create library in VFS - $lib = 'autolib'; - $lib_class = 'CI_'.ucfirst($lib); - $this->ci_vfs_create(ucfirst($lib), 'ci_base_root, 'libraries'); - - // Create driver in VFS - $drv = 'autodrv'; - $subdir = ucfirst($drv); - $drv_class = 'CI_'.$subdir; - $this->ci_vfs_create(ucfirst($drv), 'ci_base_root, array('libraries', $subdir)); - - // Create model in VFS package path - $dir = 'testdir'; - $path = APPPATH.$dir.'/'; - $model = 'Automod'; - $this->ci_vfs_create($model, 'ci_app_root, array($dir, 'models')); - - // Create autoloader config - $cfg = array( - 'packages' => array($path), - 'helper' => array($helper), - 'libraries' => array($lib), - 'drivers' => array($drv), - 'model' => array($model), - 'config' => array('config1', 'config2') - ); - $this->ci_vfs_create('autoload', 'ci_app_root, 'config'); - - $this->load->initialize(); - - // Verify path - $this->assertContains($path, $this->load->get_package_paths()); - - // Verify helper - $this->assertTrue(function_exists($hlp_func), $hlp_func.' does not exist'); - - // Verify library - $this->assertTrue(class_exists($lib_class), $lib_class.' does not exist'); - $this->assertAttributeInstanceOf($lib_class, $lib, $this->ci_obj); - - // Verify driver - $this->assertTrue(class_exists($drv_class), $drv_class.' does not exist'); - $this->assertAttributeInstanceOf($drv_class, $drv, $this->ci_obj); - - // Verify model - $this->assertTrue(class_exists($model), $model.' does not exist'); - $this->assertAttributeInstanceOf($model, $model, $this->ci_obj); - - // Verify config calls - $this->assertEquals($cfg['config'], $this->ci_obj->config->loaded); - } -} diff --git a/tests/codeigniter/core/Log_test.php b/tests/codeigniter/core/Log_test.php deleted file mode 100644 index 9279843857e..00000000000 --- a/tests/codeigniter/core/Log_test.php +++ /dev/null @@ -1,63 +0,0 @@ -setAccessible(TRUE); - $threshold = new ReflectionProperty('CI_Log', '_threshold'); - $threshold->setAccessible(TRUE); - $date_fmt = new ReflectionProperty('CI_Log', '_date_fmt'); - $date_fmt->setAccessible(TRUE); - $file_ext = new ReflectionProperty('CI_Log', '_file_ext'); - $file_ext->setAccessible(TRUE); - $file_perms = new ReflectionProperty('CI_Log', '_file_permissions'); - $file_perms->setAccessible(TRUE); - $enabled = new ReflectionProperty('CI_Log', '_enabled'); - $enabled->setAccessible(TRUE); - - $this->ci_set_config('log_path', '/root/'); - $this->ci_set_config('log_threshold', 'z'); - $this->ci_set_config('log_date_format', 'd.m.Y'); - $this->ci_set_config('log_file_extension', ''); - $this->ci_set_config('log_file_permissions', ''); - $instance = new CI_Log(); - - $this->assertEquals($path->getValue($instance), '/root/'); - $this->assertEquals($threshold->getValue($instance), 1); - $this->assertEquals($date_fmt->getValue($instance), 'd.m.Y'); - $this->assertEquals($file_ext->getValue($instance), 'php'); - $this->assertEquals($file_perms->getValue($instance), 0644); - $this->assertFalse($enabled->getValue($instance)); - - $this->ci_set_config('log_path', ''); - $this->ci_set_config('log_threshold', '0'); - $this->ci_set_config('log_date_format', ''); - $this->ci_set_config('log_file_extension', '.log'); - $this->ci_set_config('log_file_permissions', 0600); - $instance = new CI_Log(); - - $this->assertEquals($path->getValue($instance), APPPATH.'logs/'); - $this->assertEquals($threshold->getValue($instance), 0); - $this->assertEquals($date_fmt->getValue($instance), 'Y-m-d H:i:s'); - $this->assertEquals($file_ext->getValue($instance), 'log'); - $this->assertEquals($file_perms->getValue($instance), 0600); - $this->assertEquals($enabled->getValue($instance), TRUE); - } - - // -------------------------------------------------------------------- - - public function test_format_line() - { - $this->ci_set_config('log_path', ''); - $this->ci_set_config('log_threshold', 0); - $instance = new CI_Log(); - - $format_line = new ReflectionMethod($instance, '_format_line'); - $format_line->setAccessible(TRUE); - $this->assertEquals( - $format_line->invoke($instance, 'LEVEL', 'Timestamp', 'Message'), - "LEVEL - Timestamp --> Message".PHP_EOL - ); - } -} diff --git a/tests/codeigniter/core/Model_test.php b/tests/codeigniter/core/Model_test.php deleted file mode 100644 index 80dc97b3bc0..00000000000 --- a/tests/codeigniter/core/Model_test.php +++ /dev/null @@ -1,37 +0,0 @@ -ci_core_class('loader'); - $this->load = new $loader(); - $this->ci_obj = $this->ci_instance(); - $this->ci_set_core_class('model', 'CI_Model'); - - $model_code =<<ci_vfs_create('Test_model', $model_code, $this->ci_app_root, 'models'); - $this->load->model('test_model'); - } - - // -------------------------------------------------------------------- - - public function test__get() - { - $this->assertEquals('foo', $this->ci_obj->test_model->property); - - $this->ci_obj->controller_property = 'bar'; - $this->assertEquals('bar', $this->ci_obj->test_model->controller_property); - } - -} \ No newline at end of file diff --git a/tests/codeigniter/core/Output_test.php b/tests/codeigniter/core/Output_test.php deleted file mode 100644 index 8c99c1fc5fe..00000000000 --- a/tests/codeigniter/core/Output_test.php +++ /dev/null @@ -1,63 +0,0 @@ -_output_data =<< - - Basic HTML - - - Test - - -HTML; - $this->ci_set_config('charset', 'UTF-8'); - $output = $this->ci_core_class('output'); - $this->output = new $output(); - } - - // -------------------------------------------------------------------- - - public function test_set_get_append_output() - { - $append = "\n"; - - $this->assertEquals( - $this->_output_data.$append, - $this->output - ->set_output($this->_output_data) - ->append_output("\n") - ->get_output() - ); - } - - // -------------------------------------------------------------------- - - public function test_get_content_type() - { - $this->assertEquals('text/html', $this->output->get_content_type()); - } - - // -------------------------------------------------------------------- - - public function test_get_header() - { - $this->assertNull($this->output->get_header('Non-Existent-Header')); - - // TODO: Find a way to test header() values as well. Currently, - // PHPUnit prevents this by not using output buffering. - - $this->output->set_content_type('text/plain', 'WINDOWS-1251'); - $this->assertEquals( - 'text/plain; charset=WINDOWS-1251', - $this->output->get_header('content-type') - ); - } - -} diff --git a/tests/codeigniter/core/Security_test.php b/tests/codeigniter/core/Security_test.php deleted file mode 100644 index 64efdf9c8c6..00000000000 --- a/tests/codeigniter/core/Security_test.php +++ /dev/null @@ -1,354 +0,0 @@ -ci_set_config('csrf_protection', TRUE); - $this->ci_set_config('csrf_token_name', 'ci_csrf_token'); - $this->ci_set_config('csrf_cookie_name', 'ci_csrf_cookie'); - - $_SERVER['REQUEST_METHOD'] = 'GET'; - $this->security = new Mock_Core_Security('UTF-8'); - } - - // -------------------------------------------------------------------- - - public function test_csrf_verify() - { - $_SERVER['REQUEST_METHOD'] = 'GET'; - - $this->assertInstanceOf('CI_Security', $this->security->csrf_verify()); - } - - // -------------------------------------------------------------------- - - public function test_csrf_verify_invalid() - { - // Without issuing $_POST[csrf_token_name], this request will triggering CSRF error - $_SERVER['REQUEST_METHOD'] = 'POST'; - - $this->setExpectedException('RuntimeException', 'CI Error: The action you have requested is not allowed'); - - $this->security->csrf_verify(); - } - - // -------------------------------------------------------------------- - - public function test_csrf_verify_valid() - { - $_SERVER['REQUEST_METHOD'] = 'POST'; - $_POST[$this->security->csrf_token_name] = $this->security->csrf_hash; - - $this->assertInstanceOf('CI_Security', $this->security->csrf_verify()); - } - - // -------------------------------------------------------------------- - - public function test_get_csrf_hash() - { - $this->assertEquals($this->security->csrf_hash, $this->security->get_csrf_hash()); - } - - // -------------------------------------------------------------------- - - public function test_get_csrf_token_name() - { - $this->assertEquals('ci_csrf_token', $this->security->get_csrf_token_name()); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean() - { - $harm_string = "Hello, i try to your site"; - - $harmless_string = $this->security->xss_clean($harm_string); - - $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless_string); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean_string_array() - { - $harm_strings = array( - "Hello, i try to your site", - "Simple clean string", - "Hello, i try to your site" - ); - - $harmless_strings = $this->security->xss_clean($harm_strings); - - $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless_strings[0]); - $this->assertEquals("Simple clean string", $harmless_strings[1]); - $this->assertEquals("Hello, i try to [removed]alert('Hack');[removed] your site", $harmless_strings[2]); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean_image_valid() - { - $harm_string = ''; - - $xss_clean_return = $this->security->xss_clean($harm_string, TRUE); - -// $this->assertTrue($xss_clean_return); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean_image_invalid() - { - $harm_string = ''; - - $xss_clean_return = $this->security->xss_clean($harm_string, TRUE); - - $this->assertFalse($xss_clean_return); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean_entity_double_encoded() - { - $input = 'Clickhere'; - $this->assertEquals('Clickhere', $this->security->xss_clean($input)); - } - - // -------------------------------------------------------------------- - - public function text_xss_clean_js_link_removal() - { - // This one is to prevent a false positive - $this->assertEquals( - "", - $this->security->xss_clean("") - ); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean_js_img_removal() - { - $input = 'Clickhere'; - $this->assertEquals('', $this->security->xss_clean($input)); - } - - // -------------------------------------------------------------------- - - public function test_xss_clean_sanitize_naughty_html_tags() - { - $this->assertEquals('<unclosedTag', $this->security->xss_clean('assertEquals('<blink>', $this->security->xss_clean('')); - $this->assertEquals('', $this->security->xss_clean('')); - - $this->assertEquals( - ' src="x">', - $this->security->xss_clean(' src="x">') - ); - - $this->assertEquals( - 'on=">"x onerror="alert(1)">', - $this->security->xss_clean('on=">"x onerror="alert(1)">') - ); - - $this->assertEquals( - "\n><!-\n