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..d7d71e9f85a 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('database','session'); /* | ------------------------------------------------------------------- @@ -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..2e58027c52b 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/vietgram-ci/'; /* |-------------------------------------------------------------------------- @@ -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'] = ''; @@ -314,7 +324,7 @@ | https://codeigniter.com/user_guide/libraries/encryption.html | */ -$config['encryption_key'] = ''; +$config['encryption_key'] = 'codeignitervietgram'; /* |-------------------------------------------------------------------------- @@ -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..3f7502dee36 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' => 'ci-vietgram', '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..a19acdabea3 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'] = 'auth'; $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/Auth.php b/application/controllers/Auth.php new file mode 100644 index 00000000000..96cc3b82041 --- /dev/null +++ b/application/controllers/Auth.php @@ -0,0 +1,54 @@ +load->model('UserModel'); + } + + public function index(){ + if($this->session->userdata('authenticated')) + redirect('page/feed'); + + $this->load->view('view_login'); + } + + public function login(){ + $username = $this->input->post('username'); + $password = $this->input->post('password'); + + $user = $this->UserModel->get($username); + + if (empty($user)){ + $this->session->set_flashdata('message', 'Wrong Username!'); + redirect('auth'); + } + else{ + if($password == $user->password){ + $session = array( + 'authenticated'=>true, + 'username'=>$user->username + ); + + $this->session->set_userdata($session); + redirect('page/feed'); + } + else{ + $this->session->set_flashdata('message','Wrong Password!'); + redirect('auth'); + } + } + } + + public function view_profile(){ + $this->load->view('page/view_profile'); + } + + public function logout(){ + $this->session->sess_destroy(); + redirect('auth'); + } +} \ No newline at end of file diff --git a/application/controllers/Page.php b/application/controllers/Page.php new file mode 100644 index 00000000000..7d4e832ed22 --- /dev/null +++ b/application/controllers/Page.php @@ -0,0 +1,13 @@ +load->view('feed'); + } + + public function view_profile(){ + $this->load->view('view_profile'); + } +} \ No newline at end of file diff --git a/application/controllers/Profile.php b/application/controllers/Profile.php new file mode 100644 index 00000000000..2a65af7899b --- /dev/null +++ b/application/controllers/Profile.php @@ -0,0 +1,39 @@ +load->model("profile_model"); + $this->load->library('form_validation'); + } + + public function index() + { + $data["products"] = $this->profile_model->getAll(); + $this->load->view("view_profile", $data); + } + + public edit($id = null) + { + if (!isset($id)) redirect('edit_profile'); + + $profile = $this->profile_model; + $validation = $this->form_validation; + $validation->set_rules($product->rules()); + + if ($validation->run()){ + $profile->update(); + $this->session->set_flashdata('success','Data Updated!'); + } + + $data["profile"] = $profile->getById($id); + if (!$data["profile"]) show_404(); + + $this->load->view("editprofile",$data); + } + +} \ 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/MY_Controller.php b/application/core/MY_Controller.php new file mode 100644 index 00000000000..dfe3d328c32 --- /dev/null +++ b/application/core/MY_Controller.php @@ -0,0 +1,10 @@ +session->userdata('authenticated')) + redirect('auth'); + } +} \ No newline at end of file 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/Profile_model.php b/application/models/Profile_model.php new file mode 100644 index 00000000000..78f6ed2c5d0 --- /dev/null +++ b/application/models/Profile_model.php @@ -0,0 +1,83 @@ + 'name', + 'label' => 'Name', + 'rules' => 'required'], + + [ + 'field' => 'username', + 'label' => 'Username', + 'rules' => 'required'], + + [ + 'field' => 'website', + 'label' => ' Website', + 'rules' => 'required'], + + [ + 'field' => 'bio', + 'label' => 'Bio', + 'rules' => 'required'], + + [ + 'field' => 'email', + 'label' => 'Email', + 'rules' => 'required'], + + [ + 'field' => 'phone', + 'label' => 'Phone', + 'rules' => 'required'], + ]; + } + + public function getAll() + { + return $this->db->get($this->_table)->result(); + } + + public function getById($id) + { + return $this->db->get_where($this->_table, ["id" => $id]) + } + + public function submit() + { + $post = $this->input->post(); + $this->id = uniqid(); + $this->name = $post["name"]; + $this->username = $post["username"]; + $this->website = $post["website"]; + $this->bio = $post["bio"]; + $this->email = $post["email"]; + $this->phone = $post["phone"]; + } + + public function update() + { + $post = this->input->post(); + $this->id = $post["id"]; + $this->name = $post["name"]; + $this->username = $post["username"]; + $this->website = $post["website"]; + $this->bio = $post["bio"]; + $this->email = $post["email"]; + $this->phone = $post["phone"]; + return $this->db->update($this->_table, $this, array('id' => $post['id'])); + } +} \ No newline at end of file diff --git a/application/models/UserModel.php b/application/models/UserModel.php new file mode 100644 index 00000000000..7cbd37d4c7b --- /dev/null +++ b/application/models/UserModel.php @@ -0,0 +1,11 @@ +db->where('username', $username); + $result = $this->db->get('user')->row(); + + return $result; + } +} \ No newline at end of file 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/edit-profile.php b/application/views/edit-profile.php new file mode 100644 index 00000000000..92ebc2fffd3 --- /dev/null +++ b/application/views/edit-profile.php @@ -0,0 +1,112 @@ + + + + + + + + Edit Profile | Vietgram + + + + + + +
+
+
+
+ +
+

serranoarevalo

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + + + \ 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..974b63825ad --- /dev/null +++ b/application/views/feed.php @@ -0,0 +1,150 @@ + + + + + + + + Feed | Vietgram + + + + + + +
+
+
+ + +
+ +
+
+ + + + + + +
+ +
    +
  • + serranoarevalo love this! +
  • +
  • + serranoarevalo love this! +
  • +
  • + serranoarevalo love this! +
  • +
  • + serranoarevalo love this! +
  • +
+ 2 hours ago +
+ + +
+
+
+
+
+ + +
+ +
+
+ + + + + + +
+ +
    +
  • + 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.html b/application/views/index.html index bcb7cae3433..45c60b87d4a 100644 --- a/application/views/index.html +++ b/application/views/index.html @@ -1,11 +1,66 @@ - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - + + + Vietgram | Login + + + + + + + + +
+
+ +
+
+ + + +
+
+ + + \ No newline at end of file diff --git a/application/views/view_login.php b/application/views/view_login.php new file mode 100644 index 00000000000..d5997881686 --- /dev/null +++ b/application/views/view_login.php @@ -0,0 +1,73 @@ + + + + Vietgram | Login + + + + + + + + +
+
+ +
+
+ + + +
+
+ session->flashdata('message')){ + echo $this->session->flashdata('message'); + } + ?> +
+
+ + + \ No newline at end of file diff --git a/application/views/view_profile.php b/application/views/view_profile.php new file mode 100644 index 00000000000..af2e31ca290 --- /dev/null +++ b/application/views/view_profile.php @@ -0,0 +1,152 @@ + + + + + + + + Profile | Vietgram + + + + + + +
+
+
+ +
+
+
+

username ?>

+ Edit profile + +
+
    +
  • + 333 posts +
  • +
  • + 1234 followers +
  • +
  • + 36 following +
  • +
+

+ + name ?> + bio ?> + website ?> +

+
+
+
+
+ +
+ + + 486 + + + + 344 + +
+
+
+ +
+ + + 486 + + + + 344 + +
+
+
+ +
+ + + 486 + + + + 344 + +
+
+
+ +
+ + + 486 + + + + 344 + +
+
+
+
+ + + + \ No newline at end of file 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/Capture4.PNG b/assets/images/Capture4.PNG new file mode 100644 index 00000000000..b3c46f1a382 Binary files /dev/null and b/assets/images/Capture4.PNG differ diff --git a/assets/images/The Arc.jpg b/assets/images/The Arc.jpg new file mode 100644 index 00000000000..dcce0002cda Binary files /dev/null and b/assets/images/The Arc.jpg differ 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..017e3d79376 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/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/system/database/drivers/sqlite/index.html b/system/database/drivers/sqlite/index.html new file mode 100644 index 00000000000..b702fbc3967 --- /dev/null +++ b/system/database/drivers/sqlite/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is 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_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/mocks/autoloader.php b/tests/mocks/autoloader.php index 4dd53d4af31..9360a2b34bb 100644 --- a/tests/mocks/autoloader.php +++ b/tests/mocks/autoloader.php @@ -33,6 +33,7 @@ function autoload($class) $ci_libraries = array( 'Calendar', + 'Cart', 'Driver_Library', 'Email', 'Encrypt', diff --git a/tests/mocks/core/input.php b/tests/mocks/core/input.php new file mode 100644 index 00000000000..40e27441f47 --- /dev/null +++ b/tests/mocks/core/input.php @@ -0,0 +1,49 @@ +_allow_get_array = (config_item('allow_get_array') === TRUE); + $this->_enable_xss = (config_item('global_xss_filtering') === TRUE); + $this->_enable_csrf = (config_item('csrf_protection') === TRUE); + + // Assign Security and Utf8 classes + $this->security = $security; + $this->uni = $utf8; + + // Sanitize global arrays + $this->_sanitize_globals(); + } + + public function fetch_from_array($array, $index = '', $xss_clean = FALSE) + { + return parent::_fetch_from_array($array, $index, $xss_clean); + } + + /** + * Lie about being a CLI request + * + * We take advantage of this in libraries/Session_test + */ + public function is_cli_request() + { + return FALSE; + } + + public function __set($name, $value) + { + if ($name === 'ip_address') + { + $this->ip_address = $value; + } + } + +} \ No newline at end of file diff --git a/tests/mocks/core/utf8.php b/tests/mocks/core/utf8.php new file mode 100644 index 00000000000..3a6282e1d9a --- /dev/null +++ b/tests/mocks/core/utf8.php @@ -0,0 +1,19 @@ + diff --git a/user_guide_src/source/_themes/sphinx_rtd_theme/versions.html b/user_guide_src/source/_themes/sphinx_rtd_theme/versions.html index a574bd7ef1a..8b3eb79d259 100644 --- a/user_guide_src/source/_themes/sphinx_rtd_theme/versions.html +++ b/user_guide_src/source/_themes/sphinx_rtd_theme/versions.html @@ -29,7 +29,7 @@
- Free document hosting provided by Read the Docs. + Free document hosting provided by Read the Docs. diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 87fd6b9a84b..2a4a5bd56ba 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -2,134 +2,6 @@ Change Log ########## -Version 3.2.0 -============= - -Release Date: Not Released - -- General Changes - - - Officially dropped any kind of support for anything under PHP 5.4.8. - - Updated Welcome view and HTML error templates with new styling. - - Updated configurable directory paths to handle missing trailing ``DIRECTORY_SEPARATOR`` automatically. - - Added support for HTTP status codes 103, 207, 308, 421 and 451 to :doc:`common function ` :php:func:`set_status_header()`. - -- Core - - - Removed ``$config['rewrite_short_tags']`` (irrelevant on PHP 5.4+). - - Removed previously deprecated ``$config['global_xss_filtering']``. - - Removed previously deprecated :doc:`Routing Class ` methods ``fetch_directory()``, ``fetch_class()`` and ``fetch_method()`` (use the respective class properties instead). - - Removed previously deprecated :doc:`Config Library ` method ``system_url()`` (encourages insecure practices). - - Changed :doc:`URI Library ` to ignore the ``$config['url_suffix']``, ``$config['permitted_uri_chars']`` configuration settings for CLI requests. - - Changed :doc:`Loader ` method ``model()`` to always check if the loaded class extends ``CI_Model``. - - Changed :doc:`Output Library ` method ``_display()`` default parameter value to ``NULL`` instead of empty string. - - - :doc:`Input Library ` changes include: - - - Removed previously deprecated ``$config['allow_get_array']``. - - Removed previously deprecated ``$config['standardize_newlines']``. - - Removed previously deprecated method ``is_cli_request()`` (use :php:func:`is_cli()` instead). - - Changed the ``set_cookie()`` method's default expiry time to 0 (expires when browser is closed). - - Changed the ``set_cookie()`` method to delete the cookie if a negative expiry time is passed to it. - - Allowed usage of nested array keys in ``get_post()``, ``post_get()`` methods. - -- Libraries - - - Removed previously deprecated *Cart Library*. - - Removed previously deprecated *Javascript Library* (it was always experimental in the first place). - - Added UNIX socket connection support to :doc:`Session Library ` 'redis' driver. - - Updated :doc:`ZIP Library ` method ``read_dir()`` to include hidden (dot-prefixed) files. - - - :doc:`Cache Library ` changes include: - - - Added 'apcu' driver. - - Added UNIX socket connection support to the 'memcached' driver. - - Added 'database' configuration option to the 'redis' driver, allowing to auto-select another database. - - Added method ``get_loaded_driver()`` to return the currently used driver. - - Changed the 'memcached' driver to ignore configurations that don't specify a hostname. - - Removed the *socket_type* configuration setting from the 'redis' driver. - - Changed data serialization logic in 'redis' driver for better performance. - - - :doc:`Form Validation Library ` changes include: - - - Removed previously deprecated method ``prep_for_form()`` / rule *prep_for_form*. - - Changed method ``set_rules()`` to throw a ``BadMethodCallException`` when its first parameter is not an array and the ``$rules`` one is unused. - - Added rule **valid_mac**, which replicates PHP's native ``filter_var()`` with ``FILTER_VALIDATE_MAC``. - - Added ability to validate entire arrays at once, if ``is_array`` is within the list of rules. - - Added ability to fetch processed data via a second parameter to ``run()``. - - - :doc:`HTML Table Library ` changes include: - - - Changed method ``clear()`` to also reset captions. - - - :doc:`Email Library ` changes include: - - - Changed the default value of the **validate** option to ``TRUE``. - - Changed the ``send()`` method to always return ``TRUE`` when sending multiple batches of emails. - - - - :doc:`Image Manipulation Library ` changes include: - - - Added option to change the output filename via the ``new_name`` option when rendering images with ``dynamic_output``. - - Updated to serve multibyte filenames when rendering images with ``dynamic_output``, if possible. - - Added WebP image support. - -- :doc:`Database ` changes include: - - - Removed previously deprecated 'sqlite' driver (used for SQLite version 2; no longer shipped with PHP 5.4+). - - Removed method ``db_set_charset()`` and the ability to change a connection character set at runtime. - - Changed method ``initialize()`` to return void and instead throw a ``RuntimeException`` in case of failure. - - Changed method ``db_connect()`` to always set the connection character set (if supported by the driver) and to fail if it can't. - - - :doc:`Database Forge `: - - - Added support for declaring date/time type fields default values as ``CURRENT_TIMESTAMP`` and similar. - - - :doc:`Query Builder `: - - - Added methods ``having_in()``, ``or_having_in()``, ``not_having_in()``, ``or_not_having_in()``. - - Updated methods ``where_in()``, ``or_where_in()``, ``not_where_in()``, ``or_not_where_in()`` to reject non-array inputs for the second parameter. - - Updated method ``join()`` to allow accepting ``NATURAL`` clauses in its third parameter. - - Updated logic to allow dots in alias names. - -- Helpers - - - Removed previously deprecated *Email Helper* (had only two functions, aliases for PHP's native ``filter_var()`` and ``mail()``). - - Removed previously deprecated *Smiley Helper*. - - Removed previously deprecated :doc:`Date Helper ` function ``standard_date()`` (use PHP's native ``date()`` instead). - - Removed previously deprecated :doc:`Security Helper ` function ``do_hash()`` (use PHP's native ``hash()`` instead). - - Removed previously deprecated :doc:`File Helper ` function ``read_file()`` (use PHP's native ``file_get_contents()`` instead). - - Added new function :php:func:`ordinal_format()` to :doc:`Inflector Helper `. - - - :doc:`Download Helper ` changes include: - - - Updated :php:func:`force_download()` to allow existing files to be renamed for download. - - Updated :php:func:`force_download()` to better utilize available server memory. - - Updated :php:func:`force_download()` to serve multibyte filenames when possible, via the ``filename*`` attribute specified by IETF `RFC 6266 `_. - - - :doc:`String Helper ` changes include: - - - Removed previously deprecated function ``trim_slashes()`` (use PHP's native ``trim()`` with ``'/'`` instead). - - Removed previously deprecated function ``repeater()`` (use PHP's native ``str_repeat()`` instead). - - - :doc:`HTML Helper ` changes include: - - - Removed previously deprecated function ``br()`` (use PHP's native ``str_repeat()`` with ``'
'`` instead). - - Removed previously deprecated function ``nbs()`` (use PHP's native ``str_repeat()`` with ``' '`` instead). - - Updated function :php:func:`meta()` with support for "charset" and "property" properties. - - Changed function :php:func:`doctype()` default document type to HTML 5. - - - :doc:`Form Helper ` changes include: - - - Removed previously deprecated function ``form_prep()`` (use :php:func:`html_escape()` instead). - - Removed the second (out of three) parameter from the :php:func:`form_upload()` function (it was never used). - - - :doc:`CAPTCHA Helper ` changes include: - - - Added 'img_alt' option with a default value of 'captcha'. - - Added ability to generate ``data:image/png;base64`` URIs instead of writing image files to disk. - - Updated to always create PNG images instead of JPEG. - Version 3.1.12 ============== @@ -140,6 +12,8 @@ Release Date: Not Released - Improved logging of error conditions in :doc:`CAPTCHA Helper ` function :php:func:`create_captcha()`. - Added ``AUTO_INCREMENT`` support for Oracle 12.1+ to :doc:`Database Forge `. - Added ``FULL [OUTER] JOIN`` support to :doc:`Query Builder `. + - Added support for detecting WebP image type to :doc:`File Uploading Library `. + - Added method :doc:`Database Library ` method ``trans_active()`` to expose transaction state. Bug fixes for 3.1.12 ==================== @@ -149,6 +23,7 @@ Bug fixes for 3.1.12 - Fixed a bug (#5857) - :doc:`Session ` data could be corrupted after a concurrent request write with the 'files' driver due to a filesize cache being incorrect. - Fixed a bug (#5861) - :doc:`Cache Library ` 'redis' driver would always use phpRedis 5 ``del()`` due to an incorrect version check. - Fixed a bug (#5879) - :doc:`Profiler Library ` triggered an ``E_DEPRECATED`` warning on PHP 7.4+. +- Fixed a bug (#5901) - :doc:`Database Library ` methods ``list_fields()`` and ``field_data()`` ignored the configured table schema on PostgreSQL. Version 3.1.11 ============== @@ -781,7 +656,7 @@ Release Date: March 30, 2015 - License - - CodeIgniter has been relicensed with the `MIT License `_, eliminating its old proprietary licensing. + - CodeIgniter has been relicensed with the `MIT License `_, eliminating its old proprietary licensing. - General Changes @@ -839,7 +714,7 @@ Release Date: March 30, 2015 - Added an optional third parameter to :php:func:`timespan()` that constrains the number of time units displayed. - Added an optional parameter to :php:func:`timezone_menu()` that allows more attributes to be added to the generated select tag. - Added function :php:func:`date_range()` that generates a list of dates between a specified period. - - Deprecated ``standard_date()``, which now just uses the native ``date()`` with `DateTime constants `_. + - Deprecated ``standard_date()``, which now just uses the native ``date()`` with `DateTime constants `_. - Changed :php:func:`now()` to work with all timezone strings supported by PHP. - Changed :php:func:`days_in_month()` to use the native ``cal_days_in_month()`` PHP function, if available. @@ -864,7 +739,7 @@ Release Date: March 30, 2015 - :doc:`Inflector Helper ` changes include: - Changed :php:func:`humanize()` to allow passing an input separator as its second parameter. - - Changed :php:func:`humanize()` and :php:func:`underscore()` to utilize `mbstring `_, if available. + - Changed :php:func:`humanize()` and :php:func:`underscore()` to utilize `mbstring `_, if available. - Changed :php:func:`plural()` and :php:func:`singular()` to avoid double pluralization and support more words. - :doc:`Download Helper ` changes include: @@ -876,15 +751,15 @@ Release Date: March 30, 2015 - :doc:`Form Helper ` changes include: - :php:func:`form_dropdown()` will now also take an array for unity with other form helpers. - - ``form_prep()`` is now DEPRECATED and only acts as an alias for :doc:`common function ` :php:func:`html_escape()`. + - :php:func:`form_prep()` is now DEPRECATED and only acts as an alias for :doc:`common function ` :php:func:`html_escape()`. - :php:func:`set_value()` will now also accept a third argument, allowing to turn off HTML escaping of the value. - :doc:`Security Helper ` changes include: - - ``do_hash()`` now uses PHP's native ``hash()`` function (supporting more algorithms) and is deprecated. + - :php:func:`do_hash()` now uses PHP's native ``hash()`` function (supporting more algorithms) and is deprecated. - :php:func:`strip_image_tags()` is now an alias for the same method in the :doc:`Security Library `. - - *Smiley Helper* changes include: + - :doc:`Smiley Helper ` changes include: - Deprecated the whole helper as too specific for CodeIgniter. - Removed previously deprecated function ``js_insert_smiley()``. @@ -915,12 +790,12 @@ Release Date: March 30, 2015 - :doc:`Text Helper ` changes include: - Changed the default tag for use in :php:func:`highlight_phrase()` to ```` (formerly ````). - - Changed :php:func:`character_limiter()`, :php:func:`word_wrap()` and :php:func:`ellipsize()` to utilize `mbstring `_ or `iconv `_, if available. + - Changed :php:func:`character_limiter()`, :php:func:`word_wrap()` and :php:func:`ellipsize()` to utilize `mbstring `_ or `iconv `_, if available. - :doc:`Directory Helper ` :php:func:`directory_map()` will now append ``DIRECTORY_SEPARATOR`` to directory names in the returned array. - :doc:`Array Helper ` :php:func:`element()` and :php:func:`elements()` now return NULL instead of FALSE when the required elements don't exist. - :doc:`Language Helper ` :php:func:`lang()` now accepts an optional list of additional HTML attributes. - - Deprecated the *Email Helper* as its ``valid_email()``, ``send_email()`` functions are now only aliases for PHP native functions ``filter_var()`` and ``mail()`` respectively. + - Deprecated the :doc:`Email Helper ` as its ``valid_email()``, ``send_email()`` functions are now only aliases for PHP native functions ``filter_var()`` and ``mail()`` respectively. - Database @@ -1095,7 +970,7 @@ Release Date: March 30, 2015 - Added support for templating via an array in addition to the encoded string. - Changed method ``get_total_days()`` to be an alias for :doc:`Date Helper ` :php:func:`days_in_month()`. - - *Cart Library* changes include: + - :doc:`Cart Library ` changes include: - Deprecated the library as too specific for CodeIgniter. - Added method ``remove()`` to remove a cart item, updating with quantity of 0 seemed like a hack but has remained to retain compatibility. @@ -1232,7 +1107,7 @@ Release Date: March 30, 2015 - Changed private methods to protected so that MY_URI can override them. - Renamed internal method ``_parse_cli_args()`` to ``_parse_argv()``. - Renamed internal method ``_detect_uri()`` to ``_parse_request_uri()``. - - Changed ``_parse_request_uri()`` to accept absolute URIs for compatibility with HTTP/1.1 as per `RFC2616 `. + - Changed ``_parse_request_uri()`` to accept absolute URIs for compatibility with HTTP/1.1 as per `RFC2616 `. - Added protected method ``_parse_query_string()`` to URI paths in the the **QUERY_STRING** value, like ``_parse_request_uri()`` does. - Changed URI string detection logic to always default to **REQUEST_URI** unless configured otherwise or under CLI. - Removed methods ``_remove_url_suffix()``, ``_explode_segments()`` and moved their logic into ``_set_uri_string()``. @@ -1327,7 +1202,7 @@ Release Date: March 30, 2015 - UTF-8 Library changes include: - - ``UTF8_ENABLED`` now requires only one of `Multibyte String `_ or `iconv `_ to be available instead of both. + - ``UTF8_ENABLED`` now requires only one of `Multibyte String `_ or `iconv `_ to be available instead of both. - Changed method ``clean_string()`` to utilize ``mb_convert_encoding()`` if it is available. - Renamed method ``_is_ascii()`` to ``is_ascii()`` and made it public. @@ -1339,9 +1214,9 @@ Release Date: March 30, 2015 - Added :doc:`compatibility layers ` for: - - `Multibyte String `_ (limited support). - - `Hash `_ (``hash_equals()``, ``hash_pbkdf2()``). - - `Password Hashing `_. + - `Multibyte String `_ (limited support). + - `Hash `_ (``hash_equals()``, ``hash_pbkdf2()``). + - `Password Hashing `_. - `Standard Functions ``array_column()``, ``array_replace()``, ``array_replace_recursive()``, ``hex2bin()``, ``quoted_printable_encode()``. - Removed ``CI_CORE`` boolean constant from *CodeIgniter.php* (no longer Reactor and Core versions). @@ -1364,7 +1239,7 @@ Bug fixes for 3.0 - Fixed a bug where :doc:`Database Forge ` method ``create_table()`` with PostgreSQL database could lead to fetching the whole table. - Fixed a bug (#795) - :doc:`Form Helper ` :php:func:`form_open()` didn't add the default form *method* and *accept-charset* when an empty array is passed to it. - Fixed a bug (#797) - :doc:`Date Helper ` :php:func:`timespan()` was using incorrect seconds for year and month. -- Fixed a bug in *Cart Library* method ``contents()`` where if called without a TRUE (or equal) parameter, it would fail due to a typo. +- Fixed a bug in :doc:`Cart Library ` method ``contents()`` where if called without a TRUE (or equal) parameter, it would fail due to a typo. - Fixed a bug (#406) - SQLSRV DB driver not returning resource on ``db_pconnect()``. - Fixed a bug in :doc:`Image Manipulation Library ` method ``gd_loaded()`` where it was possible for the script execution to end or a PHP E_WARNING message to be emitted. - Fixed a bug in the :doc:`Pagination library ` where when use_page_numbers=TRUE previous link and page 1 link did not have the same url. @@ -1446,7 +1321,7 @@ Bug fixes for 3.0 - Fixed a bug (#79) - :doc:`Form Validation Library ` didn't properly validate array fields that use associative keys or have custom indexes. - Fixed a bug (#427) - :doc:`Form Validation Library ` method ``strip_image_tags()`` was an alias to a non-existent method. - Fixed a bug (#1545) - :doc:`Query Builder ` method ``limit()`` wasn't executed properly under Oracle. -- Fixed a bug (#1551) - :doc:`Date Helper ` function ``standard_date()`` didn't properly format *W3C* and *ATOM* standard dates. +- Fixed a bug (#1551) - :doc:`Date Helper ` function :php:func:`standard_date()` didn't properly format *W3C* and *ATOM* standard dates. - Fixed a bug where :doc:`Query Builder ` method ``join()`` escaped literal values as if they were fields. - Fixed a bug (#135) - PHP Error logging was impossible without the errors being displayed. - Fixed a bug (#1613) - :doc:`Form Helper ` functions :php:func:`form_multiselect()`, :php:func:`form_dropdown()` didn't properly handle empty array option groups. @@ -1501,7 +1376,7 @@ Bug fixes for 3.0 - Fixed a bug (#2298) - :doc:`Database Results ` method ``next_row()`` kept returning the last row, allowing for infinite loops. - Fixed a bug (#2236, #2639) - :doc:`Form Helper ` functions :php:func:`set_value()`, :php:func:`set_select()`, :php:func:`set_radio()`, :php:func:`set_checkbox()` didn't parse array notation for keys if the rule was not present in the :doc:`Form Validation Library `. - Fixed a bug (#2353) - :doc:`Query Builder ` erroneously prefixed literal strings with **dbprefix**. -- Fixed a bug (#78) - *Cart Library* didn't allow non-English letters in product names. +- Fixed a bug (#78) - :doc:`Cart Library ` didn't allow non-English letters in product names. - Fixed a bug (#77) - :doc:`Database Class ` didn't properly handle the transaction "test mode" flag. - Fixed a bug (#2380) - :doc:`URI Routing ` method ``fetch_method()`` returned 'index' if the requested method name matches its controller name. - Fixed a bug (#2388) - :doc:`Email Library ` used to ignore attachment errors, resulting in broken emails being sent. @@ -1721,7 +1596,7 @@ Release Date: November 14, 2011 - Database - - Added a `CUBRID `_ driver to the :doc:`Database + - Added a `CUBRID `_ driver to the :doc:`Database Driver `. Thanks to the CUBRID team for supplying this patch. - Added a PDO driver to the :doc:`Database Driver `. @@ -1736,8 +1611,9 @@ Release Date: November 14, 2011 - Libraries - - Changed ``$this->cart->insert()`` in the *Cart Library* - to return the Row ID if a single item was inserted successfully. + - Changed ``$this->cart->insert()`` in the :doc:`Cart + Library ` to return the Row ID if a single + item was inserted successfully. - Added support to set an optional parameter in your callback rules of validation using the :doc:`Form Validation Library `. @@ -1845,8 +1721,9 @@ Release Date: August 20, 2011 string. See upgrade notes if using database sessions. - Added $this->db->set_dbprefix() to the :doc:`Database Driver `. - - Changed ``$this->cart->insert()`` in the *Cart Library* - to return the Row ID if a single item was inserted successfully. + - Changed $this->cart->insert() in the :doc:`Cart + Library ` to return the Row ID if a single + item was inserted successfully. - Added $this->load->get_var() to the :doc:`Loader library ` to retrieve global vars set with $this->load->view() and $this->load->vars(). @@ -1871,8 +1748,8 @@ Bug fixes for 2.0.3 properly escaped. - Fixed issue #199 - Attributes passed as string does not include a space between it and the opening tag. -- Fixed a bug where the method ``$this->cart->total_items()`` from - *Cart Library* now returns the sum of the quantity +- Fixed a bug where the method $this->cart->total_items() from :doc:`Cart + Library ` now returns the sum of the quantity of all items in the cart instead of your total count. - Fixed a bug where not setting 'null' when adding fields in db_forge for mysql and mysqli drivers would default to NULL instead of NOT @@ -1908,8 +1785,8 @@ Hg Tag: v2.0.2 - Helpers - - Removed the previously deprecated ``dohash()`` from the :doc:`Security - helper <./helpers/security_helper>`; use ``do_hash()`` instead. + - Removed the previously deprecated dohash() from the :doc:`Security + helper <./helpers/security_helper>`; use do_hash() instead. - Changed the 'plural' function so that it doesn't ruin the captalization of your string. It also take into consideration acronyms which are all caps. @@ -2151,7 +2028,7 @@ Hg Tag: v2.0.0 helper <./helpers/text_helper>`. - Added accept-charset to the list of inserted attributes of form_open() in the :doc:`Form Helper `. - - Deprecated the ``dohash()`` function in favour of ``do_hash()`` for + - Deprecated the dohash() function in favour of do_hash() for naming consistency. - Non-backwards compatible change made to get_dir_file_info() in the :doc:`File Helper `. No longer recurses @@ -2171,7 +2048,7 @@ Hg Tag: v2.0.0 string already has a scheme. - Modified get_file_info in the file helper, changing filectime() to filemtime() for dates. - - Modified ``smiley_js()`` to add optional third parameter to return + - Modified smiley_js() to add optional third parameter to return only the javascript with no script tags. - The img() function of the :doc:`HTML helper <./helpers/html_helper>` will now generate an empty @@ -2291,7 +2168,7 @@ Hg Tag: v1.7.2 - Libraries - - Added a new *Cart Class*. + - Added a new :doc:`Cart Class `. - Added the ability to pass $config['file_name'] for the :doc:`File Uploading Class ` and rename the uploaded file. @@ -2318,7 +2195,7 @@ Hg Tag: v1.7.2 - Modified form_hidden() in the :doc:`Form helper ` to accept multi-dimensional arrays. - - Modified ``form_prep()`` in the :doc:`Form + - Modified form_prep() in the :doc:`Form helper ` to keep track of prepped fields to avoid multiple prep/mutation from subsequent calls which can occur when using Form Validation and form helper functions to @@ -2326,7 +2203,7 @@ Hg Tag: v1.7.2 - Modified directory_map() in the :doc:`Directory helper ` to allow the inclusion of hidden files, and to return FALSE on failure to read directory. - - Modified the *Smiley helper* to work + - Modified the :doc:`Smiley helper ` to work with multiple fields and insert the smiley at the last known cursor position. @@ -2377,7 +2254,7 @@ Bug fixes for 1.7.2 - Fixed a case sensitive string replacement in xss_clean() - Fixed a bug in form_textarea() where form data was not prepped correctly. -- Fixed a bug in ``form_prep()`` causing it to not preserve entities in +- Fixed a bug in form_prep() causing it to not preserve entities in the user's original input when called back into a form element - Fixed a bug in _protect_identifiers() where the swap prefix ($swap_pre) was not being observed. @@ -3070,7 +2947,7 @@ Release Date: January 30, 2008 class. <./libraries/sessions>` - Removed 'last_visit' from the Session class. - Added a language entry for valid_ip validation error. - - Modified ``prep_for_form()`` in the Validation class to accept + - Modified prep_for_form() in the Validation class to accept arrays, adding support for POST array validation (via callbacks only) - Added an "integer" rule into the Validation library. @@ -3094,7 +2971,8 @@ Release Date: January 30, 2008 helper. <./helpers/html_helper>` - Added img() to the :doc:`HTML helper. <./helpers/html_helper>` - Added ability to :doc:`"extend" Helpers <./general/helpers>`. - - Added an *Email Helper* into core helpers. + - Added an :doc:`email helper <./helpers/email_helper>` into core + helpers. - Added strip_quotes() function to :doc:`string helper <./helpers/string_helper>`. - Added reduce_multiples() function to :doc:`string @@ -3295,7 +3173,7 @@ Release Date: July 12, 2007 - Fixed various doc typos. - Documented two functions from the :doc:`String helper <./helpers/string_helper>` that were missing from the - user guide: ``trim_slashes()`` and ``reduce_double_slashes()``. + user guide: trim_slashes() and reduce_double_slashes(). - Docs now validate to XHTML 1 transitional - Updated the XSS Filtering to take into account the IE expression() ability and improved certain deletions to prevent possible exploits @@ -3326,7 +3204,7 @@ Release Date: April 15, 2007 - Added array to string into the profiler - Code Igniter references updated to CodeIgniter - pMachine references updated to EllisLab -- Fixed a bug in the ``repeater()`` function of :doc:`string +- Fixed a bug in the repeater function of :doc:`string helper <./helpers/string_helper>`. - Fixed a bug in ODBC driver - Fixed a bug in result_array() that was returning an empty array when @@ -3425,7 +3303,8 @@ Release Date: October 30, 2006 - Added :doc:`Download Helper <./helpers/download_helper>`. - Added :doc:`simple_query() <./database/queries>` function to the database classes -- Added ``standard_date()`` function function to the :doc:`Date Helper `. +- Added :doc:`standard_date() <./helpers/date_helper>` function to + the Date Helper. - Added :doc:`$query->free_result() <./database/results>` to database class. - Added :doc:`$query->list_fields() <./database/metadata>` function to @@ -3433,7 +3312,7 @@ Release Date: October 30, 2006 - Added :doc:`$this->db->platform() <./database/helpers>` function - Added new :doc:`File Helper <./helpers/file_helper>`: get_filenames() -- Added new helper: *Smiley Helper* +- Added new helper: :doc:`Smiley Helper <./helpers/smiley_helper>` - Added support for
    and
      lists in the :doc:`HTML Helper <./helpers/html_helper>` - Added the ability to rewrite :doc:`short @@ -3466,7 +3345,7 @@ Release Date: October 30, 2006 - Fixed a bug in the validation class. - Fixed a bug in the typography helper that was incorrectly wrapping block level elements in paragraph tags. -- Fixed a problem in the ``form_prep()`` function that was double encoding +- Fixed a problem in the form_prep() function that was double encoding entities. - Fixed a bug that affects some versions of PHP when output buffering is nested. @@ -3828,7 +3707,7 @@ Release Date: March 10, 2006 - Fixed a pagination problem in the scaffolding. - Fixed a bug in the mysql class "where" function. - Fixed a regex problem in some code that trimmed duplicate slashes. -- Fixed a bug in the ``br()`` function in the HTML helper +- Fixed a bug in the br() function in the HTML helper - Fixed a syntax mistake in the form_dropdown function in the Form Helper. - Removed the "style" attributes form the form helpers. diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py index 9be656d8e78..25bdceeac18 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -48,9 +48,9 @@ # built documents. # # The short X.Y version. -version = '3.2.0-dev' +version = '3.1.12-dev' # The full version, including alpha/beta/rc tags. -release = '3.2.0-dev' +release = '3.1.12-dev' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/user_guide_src/source/contributing/index.rst b/user_guide_src/source/contributing/index.rst index 5bdeffde5e1..be776ec1fb6 100644 --- a/user_guide_src/source/contributing/index.rst +++ b/user_guide_src/source/contributing/index.rst @@ -31,7 +31,7 @@ Support Please note that GitHub is not for general support questions! If you are having trouble using a feature of CodeIgniter, ask for help on our -`forums `_ instead. +`forums `_ instead. If you are not sure whether you are using something correctly or if you have found a bug, again - please ask on the forums first. @@ -104,15 +104,15 @@ Compatibility ============= CodeIgniter recommends PHP 5.6 or newer to be used, but it should be -compatible with PHP 5.4.8 so all code supplied must stick to this -requirement. If PHP 5.5 (and above) functions or features are used then -there must be a fallback for PHP 5.4.8. +compatible with PHP 5.3.7 so all code supplied must stick to this +requirement. If PHP 5.4 (and above) functions or features are used then +there must be a fallback for PHP 5.3.7. Branching ========= CodeIgniter uses the `Git-Flow -`_ 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: diff --git a/user_guide_src/source/database/db_driver_reference.rst b/user_guide_src/source/database/db_driver_reference.rst index ad53c2bfc2d..da33662b068 100644 --- a/user_guide_src/source/database/db_driver_reference.rst +++ b/user_guide_src/source/database/db_driver_reference.rst @@ -17,8 +17,8 @@ This article is intended to be a reference for them. .. php:method:: initialize() - :rtype: void - :throws: RuntimeException In case of failure + :returns: TRUE on success, FALSE on failure + :rtype: bool Initialize database settings, establish a connection to the database. @@ -61,6 +61,14 @@ This article is intended to be a reference for them. Select / switch the current database. + .. php:method:: db_set_charset($charset) + + :param string $charset: Character set name + :returns: TRUE on success, FALSE on failure + :rtype: bool + + Set client character set. + .. php:method:: platform() :returns: Platform name @@ -156,7 +164,7 @@ This article is intended to be a reference for them. .. php:method:: trans_status() - :returns: TRUE if the transaction succeeded, FALSE if it failed + :returns: TRUE if the transaction succeeded, FALSE if it failed :rtype: bool Lets you retrieve the transaction status flag to @@ -312,10 +320,9 @@ This article is intended to be a reference for them. Gets a list containing field data about a table. - .. php:method:: escape_identifiers($item, $split = TRUE) + .. php:method:: escape_identifiers($item) :param mixed $item: The item or array of items to escape - :param bool $split: Whether to split identifiers when a dot is encountered :returns: The input item(s), escaped :rtype: mixed diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst index a085de293d3..83721c8b55a 100644 --- a/user_guide_src/source/database/query_builder.rst +++ b/user_guide_src/source/database/query_builder.rst @@ -453,52 +453,6 @@ setting it to FALSE. Identical to having(), only separates multiple clauses with "OR". -**$this->db->having_in()** - -Generates a HAVING field IN ('item', 'item') SQL query joined with AND if -appropriate - -:: - - $names = array('Frank', 'Todd', 'James'); - $this->db->having_in('username', $names); - // Produces: HAVING username IN ('Frank', 'Todd', 'James') - - -**$this->db->or_having_in()** - -Generates a HAVING field IN ('item', 'item') SQL query joined with OR if -appropriate - -:: - - $names = array('Frank', 'Todd', 'James'); - $this->db->or_having_in('username', $names); - // Produces: OR username IN ('Frank', 'Todd', 'James') - -**$this->db->having_not_in()** - -Generates a HAVING field NOT IN ('item', 'item') SQL query joined with -AND if appropriate - -:: - - $names = array('Frank', 'Todd', 'James'); - $this->db->having_not_in('username', $names); - // Produces: HAVING username NOT IN ('Frank', 'Todd', 'James') - - -**$this->db->or_having_not_in()** - -Generates a HAVING field NOT IN ('item', 'item') SQL query joined with OR -if appropriate - -:: - - $names = array('Frank', 'Todd', 'James'); - $this->db->or_having_not_in('username', $names); - // Produces: OR username NOT IN ('Frank', 'Todd', 'James') - **************** Ordering results **************** @@ -1281,7 +1235,7 @@ Class Reference Generates the WHERE portion of the query. Separates multiple calls with 'OR'. - .. php:method:: or_where_in([$key[, array $values[, $escape = NULL]]]) + .. php:method:: or_where_in([$key = NULL[, $values = NULL[, $escape = NULL]]]) :param string $key: The field to search :param array $values: The values searched on @@ -1292,7 +1246,7 @@ Class Reference Generates a WHERE field IN('item', 'item') SQL query, joined with 'OR' if appropriate. - .. php:method:: or_where_not_in([$key[, array $values[, $escape = NULL]]]) + .. php:method:: or_where_not_in([$key = NULL[, $values = NULL[, $escape = NULL]]]) :param string $key: The field to search :param array $values: The values searched on @@ -1303,7 +1257,7 @@ Class Reference Generates a WHERE field NOT IN('item', 'item') SQL query, joined with 'OR' if appropriate. - .. php:method:: where_in([$key[, array $values[, $escape = NULL]]]) + .. php:method:: where_in([$key = NULL[, $values = NULL[, $escape = NULL]]]) :param string $key: Name of field to examine :param array $values: Array of target values @@ -1314,7 +1268,7 @@ Class Reference Generates a WHERE field IN('item', 'item') SQL query, joined with 'AND' if appropriate. - .. php:method:: where_not_in([$key[, array $values[, $escape = NULL]]]) + .. php:method:: where_not_in([$key = NULL[, $values = NULL[, $escape = NULL]]]) :param string $key: Name of field to examine :param array $values: Array of target values @@ -1424,50 +1378,6 @@ Class Reference Adds a HAVING clause to a query, separating multiple calls with OR. - .. php:method:: or_having_in([$key[, array $values[, $escape = NULL]]]) - - :param string $key: The field to search - :param array $values: The values searched on - :param bool $escape: Whether to escape values and identifiers - :returns: DB_query_builder instance - :rtype: object - - Generates a HAVING field IN('item', 'item') SQL query, - joined with 'OR' if appropriate. - - .. php:method:: or_having_not_in([$key[, array $values[, $escape = NULL]]]) - - :param string $key: The field to search - :param array $values: The values searched on - :param bool $escape: Whether to escape values and identifiers - :returns: DB_query_builder instance - :rtype: object - - Generates a HAVING field NOT IN('item', 'item') SQL query, - joined with 'OR' if appropriate. - - .. php:method:: having_in([$key[, array $values[, $escape = NULL]]]) - - :param string $key: Name of field to examine - :param array $values: Array of target values - :param bool $escape: Whether to escape values and identifiers - :returns: DB_query_builder instance - :rtype: object - - Generates a HAVING field IN('item', 'item') SQL query, - joined with 'AND' if appropriate. - - .. php:method:: having_not_in([$key[, array $values[, $escape = NULL]]]) - - :param string $key: Name of field to examine - :param array $values: Array of target values - :param bool $escape: Whether to escape values and identifiers - :returns: DB_query_builder instance - :rtype: object - - Generates a HAVING field NOT IN('item', 'item') SQL query, - joined with 'AND' if appropriate. - .. php:method:: group_by($by[, $escape = NULL]) :param mixed $by: Field(s) to group by; string or array diff --git a/user_guide_src/source/general/alternative_php.rst b/user_guide_src/source/general/alternative_php.rst index 7f3a05e562f..418d2e6eb4e 100644 --- a/user_guide_src/source/general/alternative_php.rst +++ b/user_guide_src/source/general/alternative_php.rst @@ -10,6 +10,20 @@ alternative syntax for control structures and short tag echo statements. If you are not familiar with this syntax, it allows you to eliminate the braces from your code, and eliminate "echo" statements. +Automatic Short Tag Support +=========================== + +.. note:: If you find that the syntax described in this page does not + work on your server it might be that "short tags" are disabled in your + PHP ini file. CodeIgniter will optionally rewrite short tags on-the-fly, + allowing you to use that syntax even if your server doesn't support it. + This feature can be enabled in your *config/config.php* file. + +Please note that if you do use this feature, if PHP errors are +encountered in your **view files**, the error message and line number +will not be accurately shown. Instead, all errors will be shown as +``eval()`` errors. + Alternative Echos ================= @@ -58,4 +72,4 @@ Here is another example, using ``if``/``elseif``/``else``. Notice the colons::

      Hi unknown user

      - + \ No newline at end of file diff --git a/user_guide_src/source/general/cli.rst b/user_guide_src/source/general/cli.rst index aaeb47116ae..bfa30531b46 100644 --- a/user_guide_src/source/general/cli.rst +++ b/user_guide_src/source/general/cli.rst @@ -13,7 +13,7 @@ What is the CLI? The command-line interface is a text-based method of interacting with computers. For more information, check the `Wikipedia -article `_. +article `_. Why run via the command-line? ============================= diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index ef9058b2cb1..3e3e4226426 100644 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -24,9 +24,9 @@ loading any libraries or helpers. Example:: - if (is_php('5.5')) + if (is_php('5.3')) { - echo json_last_error_msg(); + $str = quoted_printable_encode($str); } Returns boolean TRUE if the installed version of PHP is equal to or @@ -110,7 +110,7 @@ loading any libraries or helpers. set_status_header(401); // Sets the header as: Unauthorized - `See here `_ for + `See here `_ for a full list of headers. .. php:function:: remove_invisible_characters($str[, $url_encoded = TRUE]) @@ -185,4 +185,4 @@ loading any libraries or helpers. .. note:: This function was introduced because Suhosin terminated script execution, but this turned out to be a bug. A fix has been available for some time (version 0.9.34), but is - unfortunately not released yet. + unfortunately not released yet. \ No newline at end of file diff --git a/user_guide_src/source/general/compatibility_functions.rst b/user_guide_src/source/general/compatibility_functions.rst index 0ae36e71082..584968663a7 100644 --- a/user_guide_src/source/general/compatibility_functions.rst +++ b/user_guide_src/source/general/compatibility_functions.rst @@ -26,12 +26,13 @@ Password Hashing **************** This set of compatibility functions offers a "backport" of PHP's -standard `Password Hashing extension `_ +standard `Password Hashing extension `_ that is otherwise available only since PHP 5.5. Dependencies ============ +- PHP 5.3.7 - ``CRYPT_BLOWFISH`` support for ``crypt()`` Constants @@ -50,7 +51,7 @@ Function reference :rtype: array For more information, please refer to the `PHP manual for - password_get_info() `_. + password_get_info() `_. .. php:function:: password_hash($password, $algo[, $options = array()]) @@ -61,7 +62,7 @@ Function reference :rtype: string For more information, please refer to the `PHP manual for - password_hash() `_. + password_hash() `_. .. note:: Unless you provide your own (and valid) salt, this function has a further dependency on an available CSPRNG source. Each @@ -80,7 +81,7 @@ Function reference :rtype: bool For more information, please refer to the `PHP manual for - password_needs_rehash() `_. + password_needs_rehash() `_. .. php:function:: password_verify($password, $hash) @@ -90,7 +91,7 @@ Function reference :rtype: bool For more information, please refer to the `PHP manual for - password_verify() `_. + password_verify() `_. ********************* Hash (Message Digest) @@ -116,7 +117,7 @@ Function reference :rtype: string For more information, please refer to the `PHP manual for - hash_equals() `_. + hash_equals() `_. .. php:function:: hash_pbkdf2($algo, $password, $salt, $iterations[, $length = 0[, $raw_output = FALSE]]) @@ -130,14 +131,14 @@ Function reference :rtype: string For more information, please refer to the `PHP manual for - hash_pbkdf2() `_. + hash_pbkdf2() `_. **************** Multibyte String **************** This set of compatibility functions offers limited support for PHP's -`Multibyte String extension `_. Because of +`Multibyte String extension `_. Because of the limited alternative solutions, only a few functions are available. .. note:: When a character set parameter is ommited, @@ -146,7 +147,7 @@ the limited alternative solutions, only a few functions are available. Dependencies ============ -- `iconv `_ extension +- `iconv `_ extension .. important:: This dependency is optional and these functions will always be declared. If iconv is not available, they WILL @@ -169,7 +170,7 @@ Function reference :rtype: string For more information, please refer to the `PHP manual for - mb_strlen() `_. + mb_strlen() `_. .. php:function:: mb_strpos($haystack, $needle[, $offset = 0[, $encoding = NULL]]) @@ -181,7 +182,7 @@ Function reference :rtype: mixed For more information, please refer to the `PHP manual for - mb_strpos() `_. + mb_strpos() `_. .. php:function:: mb_substr($str, $start[, $length = NULL[, $encoding = NULL]]) @@ -193,7 +194,7 @@ Function reference :rtype: string For more information, please refer to the `PHP manual for - mb_substr() `_. + mb_substr() `_. ****************** Standard Functions @@ -219,4 +220,13 @@ Function reference :rtype: array For more information, please refer to the `PHP manual for - array_column() `_. + array_column() `_. + +.. php:function:: hex2bin($data) + + :param array $data: Hexadecimal representation of data + :returns: Binary representation of the given data + :rtype: string + + For more information, please refer to the `PHP manual for hex2bin() + `_. diff --git a/user_guide_src/source/general/controllers.rst b/user_guide_src/source/general/controllers.rst index 77d19c1cf2a..14e5836360f 100644 --- a/user_guide_src/source/general/controllers.rst +++ b/user_guide_src/source/general/controllers.rst @@ -181,7 +181,7 @@ be passed as a parameter to the ``_remap()`` method:: Any extra segments after the method name are passed into ``_remap()`` as an optional second parameter. This array can be used in combination with -PHP's `call_user_func_array() `_ +PHP's `call_user_func_array() `_ to emulate CodeIgniter's default behavior. Example:: diff --git a/user_guide_src/source/general/credits.rst b/user_guide_src/source/general/credits.rst index 66b51a7adb1..d0f14b3bd20 100644 --- a/user_guide_src/source/general/credits.rst +++ b/user_guide_src/source/general/credits.rst @@ -12,7 +12,7 @@ It was, for years, developed and maintained by EllisLab, the ExpressionEngine Development Team and a group of community members called the Reactor Team. In 2014, CodeIgniter was acquired by the `British Columbia Institute of Technology -`_ and was then officially announced as a community-maintained +`_ and was then officially announced as a community-maintained project. Bleeding edge development is spearheaded by the handpicked contributors diff --git a/user_guide_src/source/general/requirements.rst b/user_guide_src/source/general/requirements.rst index 5b6a0109d57..f2729f3d50d 100644 --- a/user_guide_src/source/general/requirements.rst +++ b/user_guide_src/source/general/requirements.rst @@ -2,9 +2,9 @@ Server Requirements ################### -`PHP `_ version 5.6 or newer is recommended. +`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. @@ -15,7 +15,7 @@ Currently supported databases are: - Oracle via the *oci8* and *pdo* drivers - PostgreSQL via the *postgre* and *pdo* drivers - MS SQL via the *mssql*, *sqlsrv* (version 2005 and above only) and *pdo* drivers - - SQLite via the *sqlite3* and *pdo* drivers + - SQLite via the *sqlite* (version 2), *sqlite3* (version 3) and *pdo* drivers - CUBRID via the *cubrid* and *pdo* drivers - Interbase/Firebird via the *ibase* and *pdo* drivers - - ODBC via the *odbc* and *pdo* drivers (you should know that ODBC is actually an abstraction layer) + - ODBC via the *odbc* and *pdo* drivers (you should know that ODBC is actually an abstraction layer) \ No newline at end of file diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst index 9c6a339ccfd..909289d8d92 100644 --- a/user_guide_src/source/general/routing.rst +++ b/user_guide_src/source/general/routing.rst @@ -125,7 +125,7 @@ page after they log in, you may find this example useful:: passed to ``Auth::login()``. For those of you who don't know regular expressions and want to learn -more about them, `regular-expressions.info `_ +more about them, `regular-expressions.info `_ might be a good starting point. .. note:: You can also mix and match wildcards with regular expressions. diff --git a/user_guide_src/source/general/security.rst b/user_guide_src/source/general/security.rst index fb8cd31ff1f..744a2c934e9 100644 --- a/user_guide_src/source/general/security.rst +++ b/user_guide_src/source/general/security.rst @@ -130,7 +130,7 @@ with that. Please read below. Also, DON'T invent your own algorithms. Only use strong password hashing algorithms like BCrypt, which is used - in PHP's own `Password Hashing `_ functions. + in PHP's own `Password Hashing `_ functions. Please use them, even if you're not running PHP 5.5+, CodeIgniter provides them for you. diff --git a/user_guide_src/source/general/styleguide.rst b/user_guide_src/source/general/styleguide.rst index 6c141efbc46..9b4a84e1422 100644 --- a/user_guide_src/source/general/styleguide.rst +++ b/user_guide_src/source/general/styleguide.rst @@ -160,7 +160,7 @@ programmers, but can prove invaluable when returning to your own code months down the line. There is not a required format for comments, but the following are recommended. -`DocBlock `_ +`DocBlock `_ style comments preceding class, method, and property declarations so they can be picked up by IDEs:: @@ -319,7 +319,7 @@ Use **===** and **!==** as necessary. See also information regarding `typecasting -`_, +`_, which can be quite useful. Typecasting has a slightly different effect which may be desirable. When casting a variable as a string, for instance, NULL and boolean FALSE variables become empty strings, 0 (and @@ -346,7 +346,7 @@ Compatibility ============= CodeIgniter recommends PHP 5.6 or newer to be used, but it should be -compatible with PHP 5.4.8. Your code must either be compatible with this +compatible with PHP 5.3.7. Your code must either be compatible with this requirement, provide a suitable fallback, or be an optional feature that dies quietly without affecting a user's application. @@ -542,7 +542,7 @@ the ability to change this in the php.ini, you can often enable it with:: ini_set('display_errors', 1); .. note:: Setting the `display_errors - `_ + `_ setting with ``ini_set()`` at runtime is not identical to having it enabled in the PHP environment. Namely, it will not have any effect if the script has fatal errors. @@ -633,4 +633,4 @@ Whenever appropriate, provide function argument defaults, which helps prevent PHP errors with mistaken calls and provides common fallback values which can save a few lines of code. Example:: - function foo($bar = '', $baz = FALSE) + function foo($bar = '', $baz = FALSE) \ No newline at end of file diff --git a/user_guide_src/source/general/views.rst b/user_guide_src/source/general/views.rst index b84e8539956..2fc0cb2ca4b 100644 --- a/user_guide_src/source/general/views.rst +++ b/user_guide_src/source/general/views.rst @@ -22,7 +22,7 @@ Creating a View Using your text editor, create a file called blogview.php, and put this in it:: - + My Blog @@ -138,7 +138,7 @@ Let's try it with your controller file. Open it add this code:: Now open your view file and change the text to variables that correspond to the array keys in your data:: - + <?php echo $title;?> @@ -176,7 +176,7 @@ Here's a simple example. Add this to your controller:: Now open your view file and create a loop:: - + <?php echo $title;?> @@ -210,4 +210,4 @@ some way. If you set the parameter to TRUE (boolean) it will return data. The default behavior is false, which sends it to your browser. Remember to assign it to a variable if you want the data returned:: - $string = $this->load->view('myfile', '', TRUE); + $string = $this->load->view('myfile', '', TRUE); \ No newline at end of file diff --git a/user_guide_src/source/helpers/captcha_helper.rst b/user_guide_src/source/helpers/captcha_helper.rst index a1c13c5c8b2..be1b20aaf13 100644 --- a/user_guide_src/source/helpers/captcha_helper.rst +++ b/user_guide_src/source/helpers/captcha_helper.rst @@ -50,8 +50,7 @@ Once loaded you can generate a CAPTCHA like this:: echo $cap['image']; - The captcha function requires the GD image library. -- The **img_path** and **img_url** are both required if you want to write images to disk. - To create ``data:image/png;base64`` images, simply omit these options. +- Only the **img_path** and **img_url** are required. - If a **word** is not supplied, the function will generate a random ASCII string. You might put together your own word library that you can draw randomly from. @@ -90,6 +89,10 @@ Here is an example of usage with a database. On the page where the CAPTCHA will be shown you'll have something like this:: $this->load->helper('captcha'); + $vals = array(      + 'img_path' => './captcha/',      + 'img_url' => 'http://example.com/captcha/'      + ); $cap = create_captcha($vals); $data = array(      @@ -152,7 +155,7 @@ The following functions are available: The **image** is the actual image tag:: - + The **time** is the micro timestamp used as the image name without the file extension. It will be a number like this: 1139612155.3422 diff --git a/user_guide_src/source/helpers/cookie_helper.rst b/user_guide_src/source/helpers/cookie_helper.rst index 25c4c3a0bfc..2ad51e78ccd 100644 --- a/user_guide_src/source/helpers/cookie_helper.rst +++ b/user_guide_src/source/helpers/cookie_helper.rst @@ -25,7 +25,7 @@ Available Functions The following functions are available: -.. php:function:: set_cookie($name[, $value = ''[, $expire = 0[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]]) +.. php:function:: set_cookie($name[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]]) :param mixed $name: Cookie name *or* associative array of all of the parameters available to this function :param string $value: Cookie value @@ -42,7 +42,7 @@ The following functions are available: a description of its use, as this function is an alias for ``CI_Input::set_cookie()``. -.. php:function:: get_cookie($index[, $xss_clean = FALSE]) +.. php:function:: get_cookie($index[, $xss_clean = NULL]) :param string $index: Cookie name :param bool $xss_clean: Whether to apply XSS filtering to the returned value diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst index c63a9d291be..6bc6c2b05a6 100644 --- a/user_guide_src/source/helpers/date_helper.rst +++ b/user_guide_src/source/helpers/date_helper.rst @@ -50,7 +50,7 @@ The following functions are available: :returns: MySQL-formatted date :rtype: string - This function is identical to PHP's `date() `_ + This function is identical to PHP's `date() `_ function, except that it lets you use MySQL style date codes, where each code letter is preceded with a percent sign, e.g. `%Y %m %d` @@ -67,6 +67,45 @@ The following functions are available: If a timestamp is not included in the second parameter the current time will be used. +.. php:function:: standard_date([$fmt = 'DATE_RFC822'[, $time = NULL]]) + + :param string $fmt: Date format + :param int $time: UNIX timestamp + :returns: Formatted date or FALSE on invalid format + :rtype: string + + Lets you generate a date string in one of several standardized formats. + + Example:: + + $format = 'DATE_RFC822'; + $time = time(); + echo standard_date($format, $time); + + .. note:: This function is DEPRECATED. Use the native ``date()`` combined with + `DateTime's format constants + `_ + instead:: + + echo date(DATE_RFC822, time()); + + **Supported formats:** + + =============== ======================= ====================================== + Constant Description Example + =============== ======================= ====================================== + DATE_ATOM Atom 2005-08-15T16:13:03+0000 + DATE_COOKIE HTTP Cookies Sun, 14 Aug 2005 16:13:03 UTC + DATE_ISO8601 ISO-8601 2005-08-14T16:13:03+00:00 + DATE_RFC822 RFC 822 Sun, 14 Aug 05 16:13:03 UTC + DATE_RFC850 RFC 850 Sunday, 14-Aug-05 16:13:03 UTC + DATE_RFC1036 RFC 1036 Sunday, 14-Aug-05 16:13:03 UTC + DATE_RFC1123 RFC 1123 Sun, 14 Aug 2005 16:13:03 UTC + DATE_RFC2822 RFC 2822 Sun, 14 Aug 2005 16:13:03 +0000 + DATE_RSS RSS Sun, 14 Aug 2005 16:13:03 UTC + DATE_W3C W3C 2005-08-14T16:13:03+0000 + =============== ======================= ====================================== + .. php:function:: local_to_gmt([$time = '']) :param int $time: UNIX timestamp diff --git a/user_guide_src/source/helpers/download_helper.rst b/user_guide_src/source/helpers/download_helper.rst index e11d92a1449..1a406507310 100644 --- a/user_guide_src/source/helpers/download_helper.rst +++ b/user_guide_src/source/helpers/download_helper.rst @@ -26,7 +26,7 @@ The following functions are available: .. php:function:: force_download([$filename = ''[, $data = ''[, $set_mime = FALSE]]]) - :param mixed $filename: Filename + :param string $filename: Filename :param mixed $data: File contents :param bool $set_mime: Whether to try to send the actual MIME type :rtype: void @@ -37,11 +37,8 @@ The following functions are available: file data. If you set the second parameter to NULL and ``$filename`` is an existing, readable - file path, then its content will be read instead. You may also set ``$filename`` - as an associative array with a single element, where the key of that element would be - the local file you are trying to read and where the value is the name of the downloadable - file that will be sent to browser. An example of this is provided below. - + file path, then its content will be read instead. + If you set the third parameter to boolean TRUE, then the actual file MIME type (based on the filename extension) will be sent, so that if your browser has a handler for that type - it can use it. @@ -56,10 +53,4 @@ The following functions are available: do the following:: // Contents of photo.jpg will be automatically read - force_download('/path/to/photo.jpg', NULL); - - If you want to download an existing file from your server, but change the name - of the actual file sent to browser, you will need this:: - - // Contents of photo.jpg will be automatically read and sent as my-photo.jpg - force_download(array('/path/to/photo.jpg' => 'my-photo.jpg'), NULL); \ No newline at end of file + force_download('/path/to/photo.jpg', NULL); \ No newline at end of file diff --git a/user_guide_src/source/helpers/email_helper.rst b/user_guide_src/source/helpers/email_helper.rst new file mode 100644 index 00000000000..1ee97d90298 --- /dev/null +++ b/user_guide_src/source/helpers/email_helper.rst @@ -0,0 +1,75 @@ +############ +Email Helper +############ + +The Email Helper provides some assistive functions for working with +Email. For a more robust email solution, see CodeIgniter's :doc:`Email +Class <../libraries/email>`. + +.. important:: The Email helper is DEPRECATED and is currently + only kept for backwards compatibility. + +.. contents:: + :local: + +.. raw:: html + +
      + +Loading this Helper +=================== + +This helper is loaded using the following code:: + + $this->load->helper('email'); + +Available Functions +=================== + +The following functions are available: + + +.. php:function:: valid_email($email) + + :param string $email: E-mail address + :returns: TRUE if a valid email is supplied, FALSE otherwise + :rtype: bool + + Checks if the input is a correctly formatted e-mail address. Note that is + doesn't actually prove that the address will be able recieve mail, but + simply that it is a validly formed address. + + Example:: + + if (valid_email('email@somesite.com')) + { + echo 'email is valid'; + } + else + { + echo 'email is not valid'; + } + + .. note:: All that this function does is to use PHP's native ``filter_var()``:: + + (bool) filter_var($email, FILTER_VALIDATE_EMAIL); + +.. php:function:: send_email($recipient, $subject, $message) + + :param string $recipient: E-mail address + :param string $subject: Mail subject + :param string $message: Message body + :returns: TRUE if the mail was successfully sent, FALSE in case of an error + :rtype: bool + + Sends an email using PHP's native `mail() `_ + function. + + .. note:: All that this function does is to use PHP's native ``mail`` + + :: + + mail($recipient, $subject, $message); + + For a more robust email solution, see CodeIgniter's :doc:`Email Library + <../libraries/email>`. \ No newline at end of file diff --git a/user_guide_src/source/helpers/file_helper.rst b/user_guide_src/source/helpers/file_helper.rst index e96546a11a1..833cddea44f 100644 --- a/user_guide_src/source/helpers/file_helper.rst +++ b/user_guide_src/source/helpers/file_helper.rst @@ -23,6 +23,32 @@ Available Functions The following functions are available: + +.. php:function:: read_file($file) + + :param string $file: File path + :returns: File contents or FALSE on failure + :rtype: string + + Returns the data contained in the file specified in the path. + + Example:: + + $string = read_file('./path/to/file.php'); + + The path can be a relative or full server path. Returns FALSE (boolean) on failure. + + .. note:: The path is relative to your main site index.php file, NOT your + controller or view files. CodeIgniter uses a front controller so paths + are always relative to the main site index. + + .. note:: This function is DEPRECATED. Use the native ``file_get_contents()`` + instead. + + .. important:: If your server is running an **open_basedir** restriction this + function might not work if you are trying to access a file above the + calling script. + .. php:function:: write_file($path, $data[, $mode = 'wb']) :param string $path: File path @@ -50,7 +76,7 @@ The following functions are available: write_file('./path/to/file.php', $data, 'r+'); - The default mode is 'wb'. Please see the `PHP user guide `_ + The default mode is 'wb'. Please see the `PHP user guide `_ for mode options. .. note: In order for this function to write data to a file, its permissions must @@ -173,4 +199,4 @@ The following functions are available: :: - echo octal_permissions(fileperms('./index.php')); // 644 + echo octal_permissions(fileperms('./index.php')); // 644 \ No newline at end of file diff --git a/user_guide_src/source/helpers/form_helper.rst b/user_guide_src/source/helpers/form_helper.rst index 50cda2ed4e4..5002a25e469 100644 --- a/user_guide_src/source/helpers/form_helper.rst +++ b/user_guide_src/source/helpers/form_helper.rst @@ -243,9 +243,10 @@ The following functions are available: function above except that it uses the "password" input type. -.. php:function:: form_upload([$data = '', $extra = '']]) +.. php:function:: form_upload([$data = ''[, $value = ''[, $extra = '']]]) :param array $data: Field attributes data + :param string $value: Field value :param mixed $extra: Extra attributes to be added to the tag either as an array or a literal string :returns: An HTML file upload input field tag :rtype: string @@ -723,3 +724,20 @@ The following functions are available: The "password" field doesn't match the "repeat_password" field! */ + +.. php:function:: form_prep($str) + + :param string $str: Value to escape + :returns: Escaped value + :rtype: string + + Allows you to safely use HTML and characters such as quotes within form + elements without breaking out of the form. + + .. note:: If you use any of the form helper functions listed in this page the form + values will be prepped automatically, so there is no need to call this + function. Use it only if you are creating your own form elements. + + .. note:: This function is DEPRECATED and is just an alias for + :doc:`common function <../general/common_functions>` + :func:`html_escape()` - please use that instead. diff --git a/user_guide_src/source/helpers/html_helper.rst b/user_guide_src/source/helpers/html_helper.rst index e4738b1572c..2c748bea00c 100644 --- a/user_guide_src/source/helpers/html_helper.rst +++ b/user_guide_src/source/helpers/html_helper.rst @@ -286,7 +286,7 @@ The following functions are available: // Generates: echo meta('Content-type', 'text/html; charset=utf-8', 'equiv'); - // Note the third parameter. Can be "charset", "http-equiv", "name" or "property" + // Note the third parameter. Can be "equiv" or "name" // Generates: echo meta(array('name' => 'robots', 'content' => 'no-cache')); @@ -310,13 +310,8 @@ The following functions are available: 'content' => 'no-cache' ), array( - 'name' => 'Content-Type', - 'type' => 'http-equiv', - 'content' => 'text/html; charset=utf-8' - ), - array( - 'name' => 'UTF-8', - 'type' => 'charset' + 'name' => 'Content-type', + 'content' => 'text/html; charset=utf-8', 'type' => 'equiv' ) ); @@ -326,24 +321,23 @@ The following functions are available: // // // - // - // + // -.. php:function:: doctype([$type = 'html5']) +.. php:function:: doctype([$type = 'xhtml1-strict']) :param string $type: Doctype name :returns: HTML DocType tag :rtype: string - Helps you generate document type declarations, or DTD's. HTML 5 - is used by default, but many doctypes are available. + Helps you generate document type declarations, or DTD's. XHTML 1.0 + Strict is used by default, but many doctypes are available. Example:: - echo doctype(); // + echo doctype(); // - echo doctype('html4-trans'); // + echo doctype('html4-trans'); // The following is a list of doctype choices. These are configurable, and pulled from application/config/doctypes.php @@ -351,23 +345,63 @@ The following functions are available: =============================== =================== ================================================================================================================================================== Document type Option Result =============================== =================== ================================================================================================================================================== - XHTML 1.1 xhtml11 - XHTML 1.0 Strict xhtml1-strict - XHTML 1.0 Transitional xhtml1-trans - XHTML 1.0 Frameset xhtml1-frame - XHTML Basic 1.1 xhtml-basic11 + XHTML 1.1 xhtml11 + XHTML 1.0 Strict xhtml1-strict + XHTML 1.0 Transitional xhtml1-trans + XHTML 1.0 Frameset xhtml1-frame + XHTML Basic 1.1 xhtml-basic11 HTML 5 html5 - HTML 4 Strict html4-strict - HTML 4 Transitional html4-trans - HTML 4 Frameset html4-frame - MathML 1.01 mathml1 - MathML 2.0 mathml2 - SVG 1.0 svg10 - SVG 1.1 Full svg11 - SVG 1.1 Basic svg11-basic - SVG 1.1 Tiny svg11-tiny - XHTML+MathML+SVG (XHTML host) xhtml-math-svg-xh - XHTML+MathML+SVG (SVG host) xhtml-math-svg-sh - XHTML+RDFa 1.0 xhtml-rdfa-1 - XHTML+RDFa 1.1 xhtml-rdfa-2 + HTML 4 Strict html4-strict + HTML 4 Transitional html4-trans + HTML 4 Frameset html4-frame + MathML 1.01 mathml1 + MathML 2.0 mathml2 + SVG 1.0 svg10 + SVG 1.1 Full svg11 + SVG 1.1 Basic svg11-basic + SVG 1.1 Tiny svg11-tiny + XHTML+MathML+SVG (XHTML host) xhtml-math-svg-xh + XHTML+MathML+SVG (SVG host) xhtml-math-svg-sh + XHTML+RDFa 1.0 xhtml-rdfa-1 + XHTML+RDFa 1.1 xhtml-rdfa-2 =============================== =================== ================================================================================================================================================== + +.. php:function:: br([$count = 1]) + + :param int $count: Number of times to repeat the tag + :returns: HTML line break tag + :rtype: string + + Generates line break tags (
      ) based on the number you submit. + Example:: + + echo br(3); + + The above would produce: + + .. code-block:: html + +


      + + .. note:: This function is DEPRECATED. Use the native ``str_repeat()`` + in combination with ``
      `` instead. + +.. php:function:: nbs([$num = 1]) + + :param int $num: Number of space entities to produce + :returns: A sequence of non-breaking space HTML entities + :rtype: string + + Generates non-breaking spaces ( ) based on the number you submit. + Example:: + + echo nbs(3); + + The above would produce: + + .. code-block:: html + +     + + .. note:: This function is DEPRECATED. Use the native ``str_repeat()`` + in combination with `` `` instead. diff --git a/user_guide_src/source/helpers/inflector_helper.rst b/user_guide_src/source/helpers/inflector_helper.rst index ca781d2adaf..e3c01493934 100644 --- a/user_guide_src/source/helpers/inflector_helper.rst +++ b/user_guide_src/source/helpers/inflector_helper.rst @@ -97,19 +97,3 @@ The following functions are available: .. note:: This function used to be called ``is_countable()`` in in previous CodeIgniter versions. - -.. php:function:: ordinal_format($number) - - :param int $number: non-negative natural number to be converted - :returns: Ordinal numeral for given number or original value on failure - :rtype: string - - Returns the ordinal numeral (1st, 2nd, 3rd etc.) for a - non-negative natural number. If the input is not a natural number - greater than 0, the function will return the original value. Examples:: - - echo ordinal_format(1); // Returns 1st - echo ordinal_format(3); // Returns 3rd - echo ordinal_format(21); // Returns 21st - echo ordinal_format(102); // Returns 102nd - echo ordinal_format(-5); // Invalid input, will return -5 diff --git a/user_guide_src/source/helpers/security_helper.rst b/user_guide_src/source/helpers/security_helper.rst index e981bc6b652..103880cf9cc 100644 --- a/user_guide_src/source/helpers/security_helper.rst +++ b/user_guide_src/source/helpers/security_helper.rst @@ -48,6 +48,31 @@ The following functions are available: For more info, please see the :doc:`Security Library <../libraries/security>` documentation. + +.. php:function:: do_hash($str[, $type = 'sha1']) + + :param string $str: Input + :param string $type: Algorithm + :returns: Hex-formatted hash + :rtype: string + + Permits you to create one way hashes suitable for encrypting + passwords. Will use SHA1 by default. + + See `hash_algos() `_ + for a full list of supported algorithms. + + Examples:: + + $str = do_hash($str); // SHA1 + $str = do_hash($str, 'md5'); // MD5 + + .. note:: This function was formerly named ``dohash()``, which has been + removed in favor of ``do_hash()``. + + .. note:: This function is DEPRECATED. Use the native ``hash()`` instead. + + .. php:function:: strip_image_tags($str) :param string $str: Input string @@ -78,4 +103,4 @@ The following functions are available: Example:: - $string = encode_php_tags($string); + $string = encode_php_tags($string); \ No newline at end of file diff --git a/user_guide_src/source/helpers/smiley_helper.rst b/user_guide_src/source/helpers/smiley_helper.rst new file mode 100644 index 00000000000..3e766994204 --- /dev/null +++ b/user_guide_src/source/helpers/smiley_helper.rst @@ -0,0 +1,169 @@ +############# +Smiley Helper +############# + +The Smiley Helper file contains functions that let you manage smileys +(emoticons). + +.. important:: The Smiley helper is DEPRECATED and should not be used. + It is currently only kept for backwards compatibility. + +.. contents:: + :local: + +.. raw:: html + +
      + +Loading this Helper +=================== + +This helper is loaded using the following code:: + + $this->load->helper('smiley'); + +Overview +======== + +The Smiley helper has a renderer that takes plain text smileys, like +:-) and turns them into a image representation, like |smile!| + +It also lets you display a set of smiley images that when clicked will +be inserted into a form field. For example, if you have a blog that +allows user commenting you can show the smileys next to the comment +form. Your users can click a desired smiley and with the help of some +JavaScript it will be placed into the form field. + +Clickable Smileys Tutorial +========================== + +Here is an example demonstrating how you might create a set of clickable +smileys next to a form field. This example requires that you first +download and install the smiley images, then create a controller and the +View as described. + +.. important:: Before you begin, please `download the smiley images + `_ + and put them in a publicly accessible place on your server. + This helper also assumes you have the smiley replacement array + located at `application/config/smileys.php` + +The Controller +-------------- + +In your **application/controllers/** directory, create a file called +Smileys.php and place the code below in it. + +.. important:: Change the URL in the :php:func:`get_clickable_smileys()` + function below so that it points to your smiley folder. + +You'll notice that in addition to the smiley helper, we are also using +the :doc:`Table Class <../libraries/table>`:: + + load->helper('smiley'); + $this->load->library('table'); + + $image_array = get_clickable_smileys('http://example.com/images/smileys/', 'comments'); + $col_array = $this->table->make_columns($image_array, 8); + + $data['smiley_table'] = $this->table->generate($col_array); + $this->load->view('smiley_view', $data); + } + + } + +In your **application/views/** directory, create a file called **smiley_view.php** +and place this code in it:: + + + + Smileys + + + +
      + +
      +

      Click to insert a smiley!

      + + When you have created the above controller and view, load it by visiting http://www.example.com/index.php/smileys/ + + + +Field Aliases +------------- + +When making changes to a view it can be inconvenient to have the field +id in the controller. To work around this, you can give your smiley +links a generic name that will be tied to a specific id in your view. + +:: + + $image_array = get_smiley_links("http://example.com/images/smileys/", "comment_textarea_alias"); + +To map the alias to the field id, pass them both into the +:func:`smiley_js()` function:: + + $image_array = smiley_js("comment_textarea_alias", "comments"); + +Available Functions +=================== + +.. php:function:: get_clickable_smileys($image_url[, $alias = ''[, $smileys = NULL]]) + + :param string $image_url: URL path to the smileys directory + :param string $alias: Field alias + :returns: An array of ready to use smileys + :rtype: array + + Returns an array containing your smiley images wrapped in a clickable + link. You must supply the URL to your smiley folder and a field id or + field alias. + + Example:: + + $image_array = get_clickable_smileys('http://example.com/images/smileys/', 'comment'); + +.. php:function:: smiley_js([$alias = ''[, $field_id = ''[, $inline = TRUE]]]) + + :param string $alias: Field alias + :param string $field_id: Field ID + :param bool $inline: Whether we're inserting an inline smiley + :returns: Smiley-enabling JavaScript code + :rtype: string + + Generates the JavaScript that allows the images to be clicked and + inserted into a form field. If you supplied an alias instead of an id + when generating your smiley links, you need to pass the alias and + corresponding form id into the function. This function is designed to be + placed into the area of your web page. + + Example:: + + + +.. php:function:: parse_smileys([$str = ''[, $image_url = ''[, $smileys = NULL]]]) + + :param string $str: Text containing smiley codes + :param string $image_url: URL path to the smileys directory + :param array $smileys: An array of smileys + :returns: Parsed smileys + :rtype: string + + Takes a string of text as input and replaces any contained plain text + smileys into the image equivalent. The first parameter must contain your + string, the second must contain the URL to your smiley folder + + Example:: + + $str = 'Here are some smileys: :-) ;-)'; + $str = parse_smileys($str, 'http://example.com/images/smileys/'); + echo $str; + +.. |smile!| image:: ../images/smile.gif \ No newline at end of file diff --git a/user_guide_src/source/helpers/string_helper.rst b/user_guide_src/source/helpers/string_helper.rst index 4663bb08b29..6dabc60d3c1 100644 --- a/user_guide_src/source/helpers/string_helper.rst +++ b/user_guide_src/source/helpers/string_helper.rst @@ -27,6 +27,7 @@ Available Functions The following functions are available: + .. php:function:: random_string([$type = 'alnum'[, $len = 8]]) :param string $type: Randomization type @@ -101,6 +102,24 @@ The following functions are available: .. note:: To use multiple separate calls to this function simply call the function with no arguments to re-initialize. +.. php:function:: repeater($data[, $num = 1]) + + :param string $data: Input + :param int $num: Number of times to repeat + :returns: Repeated string + :rtype: string + + Generates repeating copies of the data you submit. Example:: + + $string = "\n"; + echo repeater($string, 30); + + The above would generate 30 newlines. + + .. note:: This function is DEPRECATED. Use the native ``str_repeat()`` + instead. + + .. php:function:: reduce_double_slashes($str) :param string $str: Input string @@ -115,6 +134,7 @@ The following functions are available: $string = "http://example.com//index.php"; echo reduce_double_slashes($string); // results in "http://example.com/index.php" + .. php:function:: strip_slashes($data) :param mixed $data: Input string or an array of strings @@ -143,6 +163,21 @@ The following functions are available: and handle string inputs. This however makes it just an alias for ``stripslashes()``. +.. php:function:: trim_slashes($str) + + :param string $str: Input string + :returns: Slash-trimmed string + :rtype: string + + Removes any leading/trailing slashes from a string. Example:: + + $string = "/this/that/theother/"; + echo trim_slashes($string); // results in this/that/theother + + .. note:: This function is DEPRECATED. Use the native ``trim()`` instead: + | + | trim($str, '/'); + .. php:function:: reduce_multiples($str[, $character = ''[, $trim = FALSE]]) :param string $str: Text to search in diff --git a/user_guide_src/source/helpers/url_helper.rst b/user_guide_src/source/helpers/url_helper.rst index adeab8c5870..e117d37c0d6 100644 --- a/user_guide_src/source/helpers/url_helper.rst +++ b/user_guide_src/source/helpers/url_helper.rst @@ -204,7 +204,7 @@ The following functions are available: | echo anchor_popup('news/local/123', 'Click Me!', array()); .. note:: The **window_name** is not really an attribute, but an argument to - the JavaScript `window.open() ` + the JavaScript `window.open() ` method, which accepts either a window name or a window target. .. note:: Any other attribute than the listed above will be parsed as an diff --git a/user_guide_src/source/images/smile.gif b/user_guide_src/source/images/smile.gif new file mode 100644 index 00000000000..bf0922504ed Binary files /dev/null and b/user_guide_src/source/images/smile.gif differ diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst index de9a22a580b..180734448be 100644 --- a/user_guide_src/source/installation/downloads.rst +++ b/user_guide_src/source/installation/downloads.rst @@ -2,8 +2,7 @@ Downloading CodeIgniter ####################### -- `CodeIgniter v3.2.0-dev (Current version) `_ -- `CodeIgniter v3.1.12-dev `_ +- `CodeIgniter v3.1.12-dev (Current version) `_ - `CodeIgniter v3.1.11 `_ - `CodeIgniter v3.1.10 `_ - `CodeIgniter v3.1.9 `_ @@ -40,7 +39,7 @@ Downloading CodeIgniter GitHub ****** -`Git `_ is a distributed version control system. +`Git `_ is a distributed version control system. Public Git access is available at `GitHub `_. Please note that while every effort is made to keep this code base diff --git a/user_guide_src/source/installation/upgrade_220.rst b/user_guide_src/source/installation/upgrade_220.rst index 489dd631269..91f9e00cd58 100644 --- a/user_guide_src/source/installation/upgrade_220.rst +++ b/user_guide_src/source/installation/upgrade_220.rst @@ -7,7 +7,7 @@ Upgrading from 2.1.4 to 2.2.x without Mcrypt, then this is a breaking change. You must install the Mcrypt extension in order to upgrade. For information on installing Mcrypt please see the PHP `documentation - `. + `. Before performing an update you should take your site offline by replacing the index.php file with a static one. diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst index 18814484488..5b2d3947d6f 100644 --- a/user_guide_src/source/installation/upgrade_300.rst +++ b/user_guide_src/source/installation/upgrade_300.rst @@ -532,9 +532,9 @@ the ``EXT`` constant has been removed. Use just '.php' instead. Smiley helper ============= -The *Smiley Helper* is a legacy feature from EllisLab's ExpressionEngine product. -However, it is too specific for a general purpose framework like CodeIgniter -and as such it is now deprecated. +The :doc:`Smiley Helper <../helpers/smiley_helper>` is a legacy feature from EllisLab's +ExpressionEngine product. However, it is too specific for a general purpose framework like +CodeIgniter and as such it is now deprecated. Also, the previously deprecated ``js_insert_smiley()`` (since version 1.7.2) is now removed. @@ -545,8 +545,8 @@ Following numerous vulnerability reports, the :doc:`Encrypt Library <../librarie been deprecated and a new, :doc:`Encryption Library <../libraries/encryption>` is added to take its place. -The new library requires either the `MCrypt extension `_ (and /dev/urandom -availability) or PHP 5.3.3 and the `OpenSSL extension `_. +The new library requires either the `MCrypt extension `_ (and /dev/urandom +availability) or PHP 5.3.3 and the `OpenSSL extension `_. While this might be rather inconvenient, it is a requirement that allows us to have properly implemented cryptographic functions. @@ -559,12 +559,12 @@ implemented cryptographic functions. The Cart library ================ -The *Cart Library*, similarly to the *Smiley Helper* is too specific for -CodeIgniter. It is now deprecated and scheduled for removal in -CodeIgniter 3.1+. +The :doc:`Cart Library <../libraries/cart>`, similarly to the :doc:`Smiley Helper +<../helpers/smiley_helper>` is too specific for CodeIgniter. It is now deprecated +and scheduled for removal in CodeIgniter 3.1+. -.. note:: The library is still available, but you're strongly encouraged to - remove its usage sooner rather than later. +.. note:: The library is still available, but you're strongly encouraged to remove its usage sooner + rather than later. Database drivers 'mysql', 'sqlite', 'mssql', 'pdo/dblib' ======================================================== @@ -624,7 +624,7 @@ CodeIgniter 3.1+. String helper repeater() ======================== -:doc:`String Helper <../helpers/string_helper>` function ``repeater()`` is now just an alias for +:doc:`String Helper <../helpers/string_helper>` function :php:func:`repeater()` is now just an alias for PHP's native ``str_repeat()`` function. It is deprecated and scheduled for removal in CodeIgniter 3.1+. .. note:: This function is still available, but you're strongly encouraged to remove its usage sooner @@ -633,7 +633,7 @@ PHP's native ``str_repeat()`` function. It is deprecated and scheduled for remov String helper trim_slashes() ============================ -:doc:`String Helper <../helpers/string_helper>` function ``trim_slashes()`` is now just an alias +:doc:`String Helper <../helpers/string_helper>` function :php:func:`trim_slashes()` is now just an alias for PHP's native ``trim()`` function (with a slash passed as its second argument). It is deprecated and scheduled for removal in CodeIgniter 3.1+. @@ -643,8 +643,8 @@ scheduled for removal in CodeIgniter 3.1+. Form helper form_prep() ======================= -:doc:`Form Helper <../helpers/form_helper>` function ``form_prep()`` is now -just an alias for :doc:`common function ` +:doc:`Form Helper <../helpers/form_helper>` function :php:func:`form_prep()` +is now just an alias for :doc:`common function ` :func:`html_escape()`. It is deprecated and will be removed in the future. Please use :php:func:`html_escape()` instead. @@ -655,13 +655,14 @@ Please use :php:func:`html_escape()` instead. Email helper functions ====================== -The *Email Helper* only has two functions: +:doc:`Email Helper <../helpers/email_helper>` only has two functions - - ``valid_email()`` - - ``send_email()`` + - :php:func:`valid_email()` + - :php:func:`send_email()` Both of them are now aliases for PHP's native ``filter_var()`` and ``mail()`` functions, respectively. -Therefore, the *Email Helper* altogether is being deprecated and is scheduled for removal in CodeIgniter 3.1+. +Therefore the :doc:`Email Helper <../helpers/email_helper>` altogether is being deprecated and +is scheduled for removal in CodeIgniter 3.1+. .. note:: These functions are still available, but you're strongly encouraged to remove their usage sooner rather than later. @@ -670,7 +671,7 @@ Date helper standard_date() =========================== :doc:`Date Helper <../helpers/date_helper>` function ``standard_date()`` is being deprecated due -to the availability of native PHP `constants `_, +to the availability of native PHP `constants `_, which when combined with ``date()`` provide the same functionality. Furthermore, they have the exact same names as the ones supported by ``standard_date()``. Here are examples of how to replace its usage: @@ -844,8 +845,8 @@ CodeIgniter 3.1+. The Javascript library ====================== -The *Javascript Library* has always had an 'experimental' status and was -never really useful, nor a proper solution. +The :doc:`Javascript Library <../libraries/javascript>` has always had an +'experimental' status and was never really useful, nor a proper solution. It is now deprecated and scheduled for removal in CodeIgniter 3.1+. diff --git a/user_guide_src/source/installation/upgrade_310.rst b/user_guide_src/source/installation/upgrade_310.rst index cae81432770..9e0108691ec 100644 --- a/user_guide_src/source/installation/upgrade_310.rst +++ b/user_guide_src/source/installation/upgrade_310.rst @@ -35,4 +35,4 @@ does not provide a function that allows to safely escape user-supplied strings f inside an SQL query (which our :doc:`Query Builder <../database/query_builder>` relies on). Thus, user inputs MUST be bound, as shown in :doc:`Running Queries <../database/queries>`, -under the "Query Bindings" section. +under the "Query Bindings" section. \ No newline at end of file diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index 789c9b32e5c..2499fe24bd2 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -8,7 +8,6 @@ upgrading from. .. toctree:: :titlesonly: - Upgrading from 3.1.10+ to 3.2.x Upgrading from 3.1.11 to 3.1.12 Upgrading from 3.1.10 to 3.1.11 Upgrading from 3.1.9 to 3.1.10 diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst index be3f894ec91..a7081ec6b61 100644 --- a/user_guide_src/source/libraries/caching.rst +++ b/user_guide_src/source/libraries/caching.rst @@ -42,8 +42,7 @@ to avoid collisions when you're running multiple applications on the same enviro :: - $this->load->driver( - 'cache', + $this->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file', 'key_prefix' => 'my_') ); @@ -102,7 +101,7 @@ Class Reference $this->cache->save('cache_item_id', 'data_to_cache'); - .. note:: The ``$raw`` parameter is only utilized by APC, APCu and Memcache, + .. note:: The ``$raw`` parameter is only utilized by APC and Memcache, in order to allow usage of ``increment()`` and ``decrement()``. .. php:method:: delete($id) @@ -188,16 +187,6 @@ Class Reference .. note:: The information returned and the structure of the data is dependent on which adapter is being used. - .. php:method:: get_loaded_driver() - - :returns: Loaded driver name after initialization ('apc', 'apcu', 'dummy', 'file', 'memcached', 'redis' or 'wincache') - :rtype: string - - This method will return the caching driver currently used after initialization. - :: - - echo $this->cache->get_loaded_driver(); // Will return something like "file" - ******* Drivers ******* @@ -212,19 +201,7 @@ specific adapter to the driver loader as follows:: $this->cache->apc->save('foo', 'bar', 10); For more information on APC, please see -`https://php.net/apc `_. - -APC User Cache (APCu) Caching -============================= - -All of the methods listed above can be accessed without passing a -specific adapter to the driver loader as follows:: - - $this->load->driver('cache'); - $this->cache->apcu->save('foo', 'bar', 10); - -For more information on APCu, please see -`https://php.net/apcu `_. +`http://php.net/apc `_. File-based Caching ================== @@ -253,7 +230,7 @@ specific adapter to the driver loader as follows:: $this->cache->memcached->save('foo', 'bar', 10); For more information on Memcached, please see -`https://php.net/memcached `_. +`http://php.net/memcached `_. WinCache Caching ================ @@ -267,7 +244,7 @@ specific adapter to the driver loader as follows:: $this->cache->wincache->save('foo', 'bar', 10); For more information on WinCache, please see -`https://php.net/wincache `_. +`http://php.net/wincache `_. Redis Caching ============= @@ -278,6 +255,8 @@ To use it, you need `Redis server and phpredis PHP extension cache->redis->save('foo', 'bar', 10); For more information on Redis, please see -`https://redis.io `_. +`http://redis.io `_. Dummy Cache =========== This is a caching backend that will always 'miss.' It stores no data, but lets you keep your caching code in place in environments that don't -support your chosen cache. +support your chosen cache. \ No newline at end of file diff --git a/user_guide_src/source/libraries/cart.rst b/user_guide_src/source/libraries/cart.rst new file mode 100644 index 00000000000..be343320db8 --- /dev/null +++ b/user_guide_src/source/libraries/cart.rst @@ -0,0 +1,398 @@ +################### +Shopping Cart Class +################### + +The Cart Class permits items to be added to a session that stays active +while a user is browsing your site. These items can be retrieved and +displayed in a standard "shopping cart" format, allowing the user to +update the quantity or remove items from the cart. + +.. important:: The Cart library is DEPRECATED and should not be used. + It is currently only kept for backwards compatibility. + +Please note that the Cart Class ONLY provides the core "cart" +functionality. It does not provide shipping, credit card authorization, +or other processing components. + +.. contents:: + :local: + +.. raw:: html + +
      + +******************** +Using the Cart Class +******************** + +Initializing the Shopping Cart Class +==================================== + +.. important:: The Cart class utilizes CodeIgniter's :doc:`Session + Class ` to save the cart information to a database, so + before using the Cart class you must set up a database table as + indicated in the :doc:`Session Documentation `, and set the + session preferences in your application/config/config.php file to + utilize a database. + +To initialize the Shopping Cart Class in your controller constructor, +use the ``$this->load->library()`` method:: + + $this->load->library('cart'); + +Once loaded, the Cart object will be available using:: + + $this->cart + +.. note:: The Cart Class will load and initialize the Session Class + automatically, so unless you are using sessions elsewhere in your + application, you do not need to load the Session class. + +Adding an Item to The Cart +========================== + +To add an item to the shopping cart, simply pass an array with the +product information to the ``$this->cart->insert()`` method, as shown +below:: + + $data = array( + 'id' => 'sku_123ABC', + 'qty' => 1, + 'price' => 39.95, + 'name' => 'T-Shirt', + 'options' => array('Size' => 'L', 'Color' => 'Red') + ); + + $this->cart->insert($data); + +.. important:: The first four array indexes above (id, qty, price, and + name) are **required**. If you omit any of them the data will not be + saved to the cart. The fifth index (options) is optional. It is intended + to be used in cases where your product has options associated with it. + Use an array for options, as shown above. + +The five reserved indexes are: + +- **id** - Each product in your store must have a unique identifier. + Typically this will be an "sku" or other such identifier. +- **qty** - The quantity being purchased. +- **price** - The price of the item. +- **name** - The name of the item. +- **options** - Any additional attributes that are needed to identify + the product. These must be passed via an array. + +In addition to the five indexes above, there are two reserved words: +rowid and subtotal. These are used internally by the Cart class, so +please do NOT use those words as index names when inserting data into +the cart. + +Your array may contain additional data. Anything you include in your +array will be stored in the session. However, it is best to standardize +your data among all your products in order to make displaying the +information in a table easier. + +:: + + $data = array( + 'id' => 'sku_123ABC', + 'qty' => 1, + 'price' => 39.95, + 'name' => 'T-Shirt', + 'coupon' => 'XMAS-50OFF' + ); + + $this->cart->insert($data); + +The ``insert()`` method will return the $rowid if you successfully insert a +single item. + +Adding Multiple Items to The Cart +================================= + +By using a multi-dimensional array, as shown below, it is possible to +add multiple products to the cart in one action. This is useful in cases +where you wish to allow people to select from among several items on the +same page. + +:: + + $data = array( + array( + 'id' => 'sku_123ABC', + 'qty' => 1, + 'price' => 39.95, + 'name' => 'T-Shirt', + 'options' => array('Size' => 'L', 'Color' => 'Red') + ), + array( + 'id' => 'sku_567ZYX', + 'qty' => 1, + 'price' => 9.95, + 'name' => 'Coffee Mug' + ), + array( + 'id' => 'sku_965QRS', + 'qty' => 1, + 'price' => 29.95, + 'name' => 'Shot Glass' + ) + ); + + $this->cart->insert($data); + +Displaying the Cart +=================== + +To display the cart you will create a :doc:`view +file ` with code similar to the one shown below. + +Please note that this example uses the :doc:`form +helper `. + +:: + + + + + + + + + + + + + + + cart->contents() as $items): ?> + + + + + + + + + + + + + + + + + + + + +
      QTYItem DescriptionItem PriceSub-Total
      $i.'[qty]', 'value' => $items['qty'], 'maxlength' => '3', 'size' => '5')); ?> + + + cart->has_options($items['rowid']) == TRUE): ?> + +

      + cart->product_options($items['rowid']) as $option_name => $option_value): ?> + + :
      + + +

      + + + +
      cart->format_number($items['price']); ?>$cart->format_number($items['subtotal']); ?>
       Total$cart->format_number($this->cart->total()); ?>
      + +

      + +Updating The Cart +================= + +To update the information in your cart, you must pass an array +containing the Row ID and one or more pre-defined properties to the +``$this->cart->update()`` method. + +.. note:: If the quantity is set to zero, the item will be removed from + the cart. + +:: + + $data = array( + 'rowid' => 'b99ccdf16028f015540f341130b6d8ec', + 'qty' => 3 + ); + + $this->cart->update($data); + + // Or a multi-dimensional array + + $data = array( + array( + 'rowid' => 'b99ccdf16028f015540f341130b6d8ec', + 'qty' => 3 + ), + array( + 'rowid' => 'xw82g9q3r495893iajdh473990rikw23', + 'qty' => 4 + ), + array( + 'rowid' => 'fh4kdkkkaoe30njgoe92rkdkkobec333', + 'qty' => 2 + ) + ); + + $this->cart->update($data); + +You may also update any property you have previously defined when +inserting the item such as options, price or other custom fields. + +:: + + $data = array( + 'rowid' => 'b99ccdf16028f015540f341130b6d8ec', + 'qty' => 1, + 'price' => 49.95, + 'coupon' => NULL + ); + + $this->cart->update($data); + +What is a Row ID? +***************** + +The row ID is a unique identifier that is generated by the cart code +when an item is added to the cart. The reason a unique ID is created +is so that identical products with different options can be managed +by the cart. + +For example, let's say someone buys two identical t-shirts (same product +ID), but in different sizes. The product ID (and other attributes) will +be identical for both sizes because it's the same shirt. The only +difference will be the size. The cart must therefore have a means of +identifying this difference so that the two sizes of shirts can be +managed independently. It does so by creating a unique "row ID" based on +the product ID and any options associated with it. + +In nearly all cases, updating the cart will be something the user does +via the "view cart" page, so as a developer, it is unlikely that you +will ever have to concern yourself with the "row ID", other than making +sure your "view cart" page contains this information in a hidden form +field, and making sure it gets passed to the ``update()`` method when +the update form is submitted. Please examine the construction of the +"view cart" page above for more information. + + +*************** +Class Reference +*************** + +.. php:class:: CI_Cart + + .. attribute:: $product_id_rules = '\.a-z0-9_-' + + These are the regular expression rules that we use to validate the product + ID - alpha-numeric, dashes, underscores, or periods by default + + .. attribute:: $product_name_rules = '\w \-\.\:' + + These are the regular expression rules that we use to validate the product ID and product name - alpha-numeric, dashes, underscores, colons or periods by + default + + .. attribute:: $product_name_safe = TRUE + + Whether or not to only allow safe product names. Default TRUE. + + + .. php:method:: insert([$items = array()]) + + :param array $items: Items to insert into the cart + :returns: TRUE on success, FALSE on failure + :rtype: bool + + Insert items into the cart and save it to the session table. Returns TRUE + on success and FALSE on failure. + + + .. php:method:: update([$items = array()]) + + :param array $items: Items to update in the cart + :returns: TRUE on success, FALSE on failure + :rtype: bool + + This method permits changing the properties of a given item. + 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 + for each item. + + .. php:method:: remove($rowid) + + :param int $rowid: ID of the item to remove from the cart + :returns: TRUE on success, FALSE on failure + :rtype: bool + + Allows you to remove an item from the shopping cart by passing it the + ``$rowid``. + + .. php:method:: total() + + :returns: Total amount + :rtype: int + + Displays the total amount in the cart. + + + .. php:method:: total_items() + + :returns: Total amount of items in the cart + :rtype: int + + Displays the total number of items in the cart. + + + .. php:method:: contents([$newest_first = FALSE]) + + :param bool $newest_first: Whether to order the array with newest items first + :returns: An array of cart contents + :rtype: array + + Returns an array containing everything in the cart. You can sort the + order by which the array is returned by passing it TRUE where the contents + will be sorted from newest to oldest, otherwise it is sorted from oldest + to newest. + + .. php:method:: get_item($row_id) + + :param int $row_id: Row ID to retrieve + :returns: Array of item data + :rtype: array + + Returns an array containing data for the item matching the specified row + ID, or FALSE if no such item exists. + + .. php:method:: has_options($row_id = '') + + :param int $row_id: Row ID to inspect + :returns: TRUE if options exist, FALSE otherwise + :rtype: bool + + Returns TRUE (boolean) if a particular row in the cart contains options. + This method is designed to be used in a loop with ``contents()``, since + you must pass the rowid to this method, as shown in the Displaying + the Cart example above. + + .. php:method:: product_options([$row_id = '']) + + :param int $row_id: Row ID + :returns: Array of product options + :rtype: array + + Returns an array of options for a particular product. This method is + designed to be used in a loop with ``contents()``, since you + must pass the rowid to this method, as shown in the Displaying the + Cart example above. + + .. php:method:: destroy() + + :rtype: void + + Permits you to destroy the cart. This method will likely be called + when you are finished processing the customer's order. \ No newline at end of file diff --git a/user_guide_src/source/libraries/config.rst b/user_guide_src/source/libraries/config.rst index 2431abf9346..fe2e0a99db6 100644 --- a/user_guide_src/source/libraries/config.rst +++ b/user_guide_src/source/libraries/config.rst @@ -239,3 +239,14 @@ Class Reference This method is normally accessed via the corresponding functions in the :doc:`URL Helper `. + + .. php:method:: system_url() + + :returns: URL pointing at your CI system/ directory + :rtype: string + + This method retrieves the URL to your CodeIgniter system/ directory. + + .. note:: This method is DEPRECATED because it encourages usage of + insecure coding practices. Your *system/* directory shouldn't + be publicly accessible. \ No newline at end of file diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 81ca00e50d0..1be6e2adb1f 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -108,7 +108,7 @@ Preference Default Value Options Descript page. Make sure you don't have any relative links or relative image paths otherwise they will not work. **charset** ``$config['charset']`` Character set (utf-8, iso-8859-1, etc.). -**validate** TRUE TRUE or FALSE (boolean) Whether to validate the email address. +**validate** FALSE TRUE or FALSE (boolean) Whether to validate the email address. **priority** 3 1, 2, 3, 4, 5 Email Priority. 1 = highest. 5 = lowest. 3 = normal. **crlf** \\n "\\r\\n" or "\\n" or "\\r" Newline character. (Use "\\r\\n" to comply with RFC 822). **newline** \\n "\\r\\n" or "\\n" or "\\r" Newline character. (Use "\\r\\n" to comply with RFC 822). @@ -312,18 +312,14 @@ Class Reference This method will automatically clear all parameters if the request was successful. To stop this behaviour pass FALSE:: - if ($this->email->send(FALSE)) - { - // Parameters won't be cleared - } + if ($this->email->send(FALSE)) + { + // Parameters won't be cleared + } .. note:: In order to use the ``print_debugger()`` method, you need to avoid clearing the email parameters. - .. note:: If ``batch_bcc_mode`` is enabled, and there are more than - ``batch_bcc_size`` recipients, this method will always return - boolean ``TRUE``. - .. php:method:: attach($filename[, $disposition = ''[, $newname = NULL[, $mime = '']]]) :param string $filename: File name @@ -406,4 +402,4 @@ Class Reference // Will only print the email headers, excluding the message subject and body $this->email->print_debugger(array('headers')); - .. note:: By default, all of the raw data will be printed. + .. note:: By default, all of the raw data will be printed. \ No newline at end of file diff --git a/user_guide_src/source/libraries/encrypt.rst b/user_guide_src/source/libraries/encrypt.rst index 10893b9012c..67e2a01905c 100644 --- a/user_guide_src/source/libraries/encrypt.rst +++ b/user_guide_src/source/libraries/encrypt.rst @@ -135,7 +135,7 @@ Class Reference $this->encrypt->set_cipher(MCRYPT_BLOWFISH); - Please visit php.net for a list of `available ciphers `_. + Please visit php.net for a list of `available ciphers `_. If you'd like to manually test whether your server supports MCrypt you can use:: @@ -153,7 +153,7 @@ Class Reference $this->encrypt->set_mode(MCRYPT_MODE_CFB); - Please visit php.net for a list of `available modes `_. + Please visit php.net for a list of `available modes `_. .. php:method:: encode_from_legacy($string[, $legacy_mode = MCRYPT_MODE_ECB[, $key = '']]) diff --git a/user_guide_src/source/libraries/encryption.rst b/user_guide_src/source/libraries/encryption.rst index 833a56c093f..b16511d4d3b 100644 --- a/user_guide_src/source/libraries/encryption.rst +++ b/user_guide_src/source/libraries/encryption.rst @@ -5,7 +5,7 @@ Encryption Library .. important:: DO NOT use this or any other *encryption* library for user password storage! Passwords must be *hashed* instead, and you should do that via PHP's own `Password Hashing extension - `_. + `_. The Encryption Library provides two-way data encryption. To do so in a cryptographically secure way, it utilizes PHP extensions that are @@ -13,8 +13,8 @@ unfortunately not always available on all systems. You must meet one of the following dependencies in order to use this library: -- `OpenSSL `_ -- `MCrypt `_ (and `MCRYPT_DEV_URANDOM` availability) +- `OpenSSL `_ +- `MCrypt `_ (and `MCRYPT_DEV_URANDOM` availability) If neither of the above dependencies is met, we simply cannot offer you a good enough implementation to meet the high standards required @@ -63,7 +63,7 @@ encryption and authentication is a bad practice. Because of that, two separate keys are derived from your already configured *encryption_key*: one for encryption and one for authentication. This is done via a technique called `HMAC-based Key Derivation Function -`_ (HKDF). +`_ (HKDF). Setting your encryption_key =========================== @@ -90,7 +90,7 @@ key security so you may want to think carefully before using it for anything that requires high security, like storing credit card numbers. Your encryption key **must** be as long as the encyption algorithm in use -allows. For AES-128, that's 128 bits or 16 bytes (characters) long. +allows. For AES-128, that's 128 bits or 16 bytes (charcters) long. You will find a table below that shows the supported key lengths of different ciphers. @@ -171,7 +171,7 @@ RC4 / ARCFour rc4 40-2048 / 5-256 Stream .. note:: Even though CAST5 supports key lengths lower than 128 bits (16 bytes), in fact they will just be zero-padded to the maximum length, as specified in `RFC 2144 - `_. + `_. .. note:: Blowfish supports key lengths as small as 32 bits (4 bytes), but our tests have shown that only lengths of 128 bits (16 bytes) or @@ -482,7 +482,7 @@ The reason for not including other popular algorithms, such as MD5 or SHA1 is that they are no longer considered secure enough and as such, we don't want to encourage their usage. If you absolutely need to use them, it is easy to do so via PHP's -native `hash_hmac() `_ function. +native `hash_hmac() `_ function. Stronger algorithms of course will be added in the future as they appear and become widely available. @@ -582,4 +582,4 @@ Class Reference 'authentication' ); - // $hmac_key is a pseudo-random key with a length of 64 bytes + // $hmac_key is a pseudo-random key with a length of 64 bytes \ No newline at end of file diff --git a/user_guide_src/source/libraries/file_uploading.rst b/user_guide_src/source/libraries/file_uploading.rst index ce3de5a8a66..babdc04f974 100644 --- a/user_guide_src/source/libraries/file_uploading.rst +++ b/user_guide_src/source/libraries/file_uploading.rst @@ -35,7 +35,7 @@ Creating the Upload Form Using a text editor, create a form called upload_form.php. In it, place this code and save it to your **application/views/** directory:: - + Upload Form @@ -68,7 +68,7 @@ The Success Page Using a text editor, create a form called upload_success.php. In it, place this code and save it to your **application/views/** directory:: - + Upload Form @@ -233,7 +233,7 @@ Preference Default Value Options Descripti unless you have no other option as that would cause a security risk. **mod_mime_fix** TRUE TRUE/FALSE (boolean) If set to TRUE, multiple filename extensions will be suffixed with an underscore in order to avoid triggering `Apache mod_mime - `_. + `_. DO NOT turn off this option if your upload directory is public, as this is a security risk. ============================ ================= ======================= ====================================================================== diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst index 5f30817eb1e..16de42338d9 100644 --- a/user_guide_src/source/libraries/form_validation.rst +++ b/user_guide_src/source/libraries/form_validation.rst @@ -65,7 +65,7 @@ The Form Using a text editor, create a form called myform.php. In it, place this code and save it to your application/views/ folder:: - + My Form @@ -100,7 +100,7 @@ The Success Page Using a text editor, create a form called formsuccess.php. In it, place this code and save it to your application/views/ folder:: - + My Form @@ -359,7 +359,7 @@ function calls!** :: - + My Form @@ -881,24 +881,6 @@ When a rule group is named identically to a controller class/method it will be used automatically when the ``run()`` method is invoked from that class/method. -Accessing validated/processed data -================================== - -By default, validation will be performed directly on the ``$_POST`` array, -and any possible modifications (like trimming whitespace, for example) -would be written back onto it. -However, if you want to keep the original input data intact, or have used -``set_data()`` to pass a custom set of inputs, you would likely want to -fetch the now-modified data. In order to do that, you can pass a variable -as the second parameter to ``run()``:: - - $input = array('name' => ' White Space '); - $output = NULL; - - $this->form_validation->set_rules('name', 'Name', 'required|trim'); - $this->form_validation->run(NULL, $output); - // $output will now contain: array('name' => 'White Space'); - .. _using-arrays-as-field-names: *************************** @@ -1005,7 +987,6 @@ Rule Parameter Description **valid_emails** No Returns FALSE if any value provided in a comma separated list is not a valid email. **valid_ip** Yes Returns FALSE if the supplied IP address is not valid. Accepts an optional parameter of 'ipv4' or 'ipv6' to specify an IP format. -**valid_mac** No Returns FALSE if the supplied MAC address is not valid. **valid_base64** No Returns FALSE if the supplied string contains anything other than valid Base64 characters. ========================= ========== ============================================================================================= ======================= @@ -1028,6 +1009,7 @@ to use: ==================== ========= ============================================================================================================== Name Parameter Description ==================== ========= ============================================================================================================== +**prep_for_form** No DEPRECATED: Converts special characters so that HTML data can be shown in a form field without breaking it. **prep_url** No Adds "\http://" to URLs if missing. **strip_image_tags** No Strips the HTML from image tags leaving the raw URL. **encode_php_tags** No Converts PHP tags to entities. @@ -1045,14 +1027,13 @@ Class Reference .. php:class:: CI_Form_validation - .. php:method:: set_rules($field[, $label = null[, $rules = null[, $errors = array()]]]) + .. php:method:: set_rules($field[, $label = ''[, $rules = ''[, $errors = array()]]]) :param string $field: Field name :param string $label: Field label :param mixed $rules: Validation rules, as a string list separated by a pipe "|", or as an array or rules :param array $errors: A list of custom error messages :returns: CI_Form_validation instance (method chaining) - :throws: BadMethodCallException If $field is not an array and $rules was not used :rtype: CI_Form_validation Permits you to set validation rules, as described in the tutorial @@ -1061,10 +1042,9 @@ Class Reference - :ref:`setting-validation-rules` - :ref:`saving-groups` - .. php:method:: run([$config = NULL[, $data = NULL]]) + .. php:method:: run([$group = '']) :param string $group: The name of the validation group to run - :param mixed $data: Optional variable to assign validated data to :returns: TRUE on success, FALSE if validation failed :rtype: bool diff --git a/user_guide_src/source/libraries/image_lib.rst b/user_guide_src/source/libraries/image_lib.rst index 442541bf675..22407962f71 100644 --- a/user_guide_src/source/libraries/image_lib.rst +++ b/user_guide_src/source/libraries/image_lib.rst @@ -283,7 +283,7 @@ Preference Default Value Options Description **wm_shadow_color** None None The color of the drop shadow, specified in hex. If you leave this blank a drop shadow will not be used. Both the full 6-length (ie, 993300) and the short three character abbreviated version (ie, fff) are supported. -**wm_shadow_distance** 2 None The distance (in pixels) from the font that the drop shadow should +**wm_shadow_distance** 3 None The distance (in pixels) from the font that the drop shadow should appear. ======================= =================== =================== ========================================================================== @@ -408,7 +408,7 @@ Class Reference method is not very useful unless you intend to build such an interface. That's exactly what we did using for the photo gallery module in ExpressionEngine, the CMS we develop. We added a JavaScript UI that - lets the cropping area be selected. (from EllisLab) + lets the cropping area be selected. .. php:method:: rotate() diff --git a/user_guide_src/source/libraries/input.rst b/user_guide_src/source/libraries/input.rst index 730b3a9b093..300f4711209 100644 --- a/user_guide_src/source/libraries/input.rst +++ b/user_guide_src/source/libraries/input.rst @@ -2,8 +2,10 @@ Input Class ########### -The Input Class provides some helper methods for accessing input data -and pre-processing it. +The Input Class serves two purposes: + +#. It pre-processes global input data for security. +#. It provides some helper methods for fetching input data and pre-processing it. .. note:: This class is initialized automatically by the system so there is no need to do it manually. @@ -15,9 +17,49 @@ and pre-processing it.
      -******************** -Accessing input data -******************** +*************** +Input Filtering +*************** + +Security Filtering +================== + +The security filtering method is called automatically when a new +:doc:`controller <../general/controllers>` is invoked. It does the +following: + +- If ``$config['allow_get_array']`` is FALSE (default is TRUE), destroys + the global GET array. +- Destroys all global variables in the event register_globals is + turned on. +- Filters the GET/POST/COOKIE array keys, permitting only alpha-numeric + (and a few other) characters. +- Provides XSS (Cross-site Scripting Hacks) filtering. This can be + enabled globally, or upon request. +- Standardizes newline characters to ``PHP_EOL`` (\\n in UNIX-based OSes, + \\r\\n under Windows). This is configurable. + +XSS Filtering +============= + +The Input class has the ability to filter input automatically to prevent +cross-site scripting attacks. If you want the filter to run +automatically every time it encounters POST or COOKIE data you can +enable it by opening your *application/config/config.php* file and setting +this:: + + $config['global_xss_filtering'] = TRUE; + +Please refer to the :doc:`Security class ` documentation for +information on using XSS Filtering in your application. + +.. important:: The 'global_xss_filtering' setting is DEPRECATED and kept + solely for backwards-compatibility purposes. XSS escaping should + be performed on *output*, not *input*! + +******************* +Accessing form data +******************* Using POST, GET, COOKIE, or SERVER Data ======================================= @@ -88,7 +130,7 @@ Class Reference The property can be read multiple times. - .. php:method:: post([$index = NULL[, $xss_clean = FALSE]]) + .. php:method:: post([$index = NULL[, $xss_clean = NULL]]) :param mixed $index: POST parameter name :param bool $xss_clean: Whether to apply XSS filtering @@ -105,6 +147,7 @@ Class Reference The second optional parameter lets you run the data through the XSS filter. It's enabled by setting the second parameter to boolean TRUE + or by setting your ``$config['global_xss_filtering']`` to TRUE. :: $this->input->post('some_data', TRUE); @@ -130,7 +173,7 @@ Class Reference $this->input->post(array('field1', 'field2'), TRUE); - .. php:method:: get([$index = NULL[, $xss_clean = FALSE]]) + .. php:method:: get([$index = NULL[, $xss_clean = NULL]]) :param mixed $index: GET parameter name :param bool $xss_clean: Whether to apply XSS filtering @@ -163,7 +206,7 @@ Class Reference $this->input->get(array('field1', 'field2'), TRUE); - .. php:method:: post_get($index[, $xss_clean = FALSE]) + .. php:method:: post_get($index[, $xss_clean = NULL]) :param string $index: POST/GET parameter name :param bool $xss_clean: Whether to apply XSS filtering @@ -176,7 +219,7 @@ Class Reference $this->input->post_get('some_data', TRUE); - .. php:method:: get_post($index[, $xss_clean = FALSE]) + .. php:method:: get_post($index[, $xss_clean = NULL]) :param string $index: GET/POST parameter name :param bool $xss_clean: Whether to apply XSS filtering @@ -191,7 +234,7 @@ Class Reference .. note:: This method used to act EXACTLY like ``post_get()``, but it's behavior has changed in CodeIgniter 3.0. - .. php:method:: cookie([$index = NULL[, $xss_clean = FALSE]]) + .. php:method:: cookie([$index = NULL[, $xss_clean = NULL]]) :param mixed $index: COOKIE name :param bool $xss_clean: Whether to apply XSS filtering @@ -214,7 +257,7 @@ Class Reference function :php:func:`get_cookie()`, this method does NOT prepend your configured ``$config['cookie_prefix']`` value. - .. php:method:: server($index[, $xss_clean = FALSE]) + .. php:method:: server($index[, $xss_clean = NULL]) :param mixed $index: Value name :param bool $xss_clean: Whether to apply XSS filtering @@ -232,7 +275,7 @@ Class Reference $this->input->server(array('SERVER_PROTOCOL', 'REQUEST_URI')); - .. php:method:: input_stream([$index = NULL[, $xss_clean = FALSE]]) + .. php:method:: input_stream([$index = NULL[, $xss_clean = NULL]]) :param mixed $index: Key name :param bool $xss_clean: Whether to apply XSS filtering @@ -242,7 +285,7 @@ Class Reference This method is identical to ``get()``, ``post()`` and ``cookie()``, only it fetches the *php://input* stream data. - .. php:method:: set_cookie($name = ''[, $value = ''[, $expire = 0[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]]) + .. php:method:: set_cookie($name = ''[, $value = ''[, $expire = ''[, $domain = ''[, $path = '/'[, $prefix = ''[, $secure = NULL[, $httponly = NULL]]]]]]]) :param mixed $name: Cookie name or an array of parameters :param string $value: Cookie value @@ -267,7 +310,7 @@ Class Reference $cookie = array( 'name' => 'The Cookie Name', 'value' => 'The Value', - 'expire' => 86500, + 'expire' => '86500', 'domain' => '.some-domain.com', 'path' => '/', 'prefix' => 'myprefix_', @@ -278,8 +321,8 @@ Class Reference **Notes** - Only the name and value are required. To delete a cookie set the expiry - time to a negative, or non-numeric value. + Only the name and value are required. To delete a cookie set it with the + expiration blank. The expiration is set in **seconds**, which will be added to the current time. Do not include the time, but rather only the number of seconds @@ -347,7 +390,7 @@ Class Reference Accepts an optional second string parameter of 'ipv4' or 'ipv6' to specify an IP format. The default checks for both formats. - .. php:method:: user_agent([$xss_clean = FALSE]) + .. php:method:: user_agent([$xss_clean = NULL]) :returns: User agent string or NULL if not set :param bool $xss_clean: Whether to apply XSS filtering @@ -370,7 +413,7 @@ Class Reference Returns an array of HTTP request headers. Useful if running in a non-Apache environment where - `apache_request_headers() `_ + `apache_request_headers() `_ will not be supported. :: @@ -397,6 +440,25 @@ Class Reference Checks to see if the HTTP_X_REQUESTED_WITH server header has been set, and returns boolean TRUE if it is or FALSE if not. + .. php:method:: is_cli_request() + + :returns: TRUE if it is a CLI request, FALSE if not + :rtype: bool + + Checks to see if the application was run from the command-line + interface. + + .. note:: This method checks both the PHP SAPI name currently in use + and if the ``STDIN`` constant is defined, which is usually a + failsafe way to see if PHP is being run via the command line. + + :: + + $this->input->is_cli_request() + + .. note:: This method is DEPRECATED and is now just an alias for the + :func:`is_cli()` function. + .. php:method:: method([$upper = FALSE]) :param bool $upper: Whether to return the request method name in upper or lower case diff --git a/user_guide_src/source/libraries/javascript.rst b/user_guide_src/source/libraries/javascript.rst new file mode 100644 index 00000000000..e91b9ad7835 --- /dev/null +++ b/user_guide_src/source/libraries/javascript.rst @@ -0,0 +1,322 @@ +################ +Javascript Class +################ + +CodeIgniter provides a library to help you with certain common functions +that you may want to use with Javascript. Please note that CodeIgniter +does not require the jQuery library to run, and that any scripting +library will work equally well. The jQuery library is simply presented +as a convenience if you choose to use it. + +.. important:: This library is DEPRECATED and should not be used. It has always + been with an 'experimental' status and is now no longer supported. + Currently only kept for backwards compatibility. + +.. contents:: + :local: + +.. raw:: html + +
      + +************************** +Using the Javascript Class +************************** + +Initializing the Class +====================== + +To initialize the Javascript class manually in your controller +constructor, use the ``$this->load->library()`` method. Currently, +the only available library is jQuery, which will automatically be +loaded like this:: + + $this->load->library('javascript'); + +The Javascript class also accepts parameters: + +- js_library_driver (string) *default: 'jquery'* +- autoload (bool) *default: TRUE* + +You may override the defaults by sending an associative array:: + + $this->load->library( + 'javascript', + array( + 'js_library_driver' => 'scripto', + 'autoload' => FALSE + ) + ); + +Again, presently only 'jquery' is available. You may wish to set +autoload to FALSE, though, if you do not want the jQuery library to +automatically include a script tag for the main jQuery script file. This +is useful if you are loading it from a location outside of CodeIgniter, +or already have the script tag in your markup. + +Once loaded, the jQuery library object will be available using: + + $this->javascript + +Setup and Configuration +======================= + +Set these variables in your view +-------------------------------- + +As a Javascript library, your files must be available to your +application. + +As Javascript is a client side language, the library must be able to +write content into your final output. This generally means a view. +You'll need to include the following variables in the ```` +sections of your output. + +:: + + + + + +``$library_src``, is where the actual library file will be loaded, as +well as any subsequent plugin script calls; $script_head is where +specific events, functions and other commands will be rendered. + +Set the path to the librarys with config items +---------------------------------------------- + +There are some configuration items in Javascript library. These can +either be set in *application/config.php*, within its own +*config/javascript.php* file, or within any controller usings the +``set_item()`` function. + +An image to be used as an "ajax loader", or progress indicator. Without +one, the simple text message of "loading" will appear when Ajax calls +need to be made. + +:: + + $config['javascript_location'] = 'http://localhost/codeigniter/themes/js/jquery/'; + $config['javascript_ajax_img'] = 'images/ajax-loader.gif'; + +If you keep your files in the same directories they were downloaded +from, then you need not set this configuration items. + +The jQuery Class +================ + +To initialize the jQuery class manually in your controller constructor, +use the ``$this->load->library()`` method:: + + $this->load->library('javascript/jquery'); + +You may send an optional parameter to determine whether or not a script +tag for the main jQuery file will be automatically included when loading +the library. It will be created by default. To prevent this, load the +library as follows:: + + $this->load->library('javascript/jquery', FALSE); + +Once loaded, the jQuery library object will be available using: + + $this->jquery + +jQuery Events +============= + +Events are set using the following syntax. +:: + + $this->jquery->event('element_path', code_to_run()); + +In the above example: + +- "event" is any of blur, change, click, dblclick, error, focus, hover, + keydown, keyup, load, mousedown, mouseup, mouseover, mouseup, resize, + scroll, or unload. +- "element_path" is any valid `jQuery selector + `_. Due to jQuery's unique + selector syntax, this is usually an element id, or CSS selector. For + example "#notice_area" would effect ``
      ``, and + "#content a.notice" would effect all anchors with a class of "notice" + in the div with id "content". +- "``code_to_run()``" is script your write yourself, or an action such as + an effect from the jQuery library below. + +Effects +======= + +The query library supports a powerful +`Effects `_ repertoire. Before an effect +can be used, it must be loaded:: + + $this->jquery->effect([optional path] plugin name); // for example $this->jquery->effect('bounce'); + + +hide() / show() +--------------- + +Each of this functions will affect the visibility of an item on your +page. hide() will set an item invisible, show() will reveal it. + +:: + + $this->jquery->hide(target, optional speed, optional extra information); + $this->jquery->show(target, optional speed, optional extra information); + + +- "target" will be any valid jQuery selector or selectors. +- "speed" is optional, and is set to either slow, normal, fast, or + alternatively a number of milliseconds. +- "extra information" is optional, and could include a callback, or + other additional information. + +toggle() +-------- + +toggle() will change the visibility of an item to the opposite of its +current state, hiding visible elements, and revealing hidden ones. + +:: + + $this->jquery->toggle(target); + + +- "target" will be any valid jQuery selector or selectors. + +animate() +--------- + +:: + + $this->jquery->animate(target, parameters, optional speed, optional extra information); + + +- "target" will be any valid jQuery selector or selectors. +- "parameters" in jQuery would generally include a series of CSS + properties that you wish to change. +- "speed" is optional, and is set to either slow, normal, fast, or + alternatively a number of milliseconds. +- "extra information" is optional, and could include a callback, or + other additional information. + +For a full summary, see +`http://api.jquery.com/animate/ `_ + +Here is an example of an animate() called on a div with an id of "note", +and triggered by a click using the jQuery library's click() event. + +:: + + $params = array( + 'height' => 80, + 'width' => '50%', + 'marginLeft' => 125 + ); + $this->jquery->click('#trigger', $this->jquery->animate('#note', $params, 'normal')); + +fadeIn() / fadeOut() +-------------------- + +:: + + $this->jquery->fadeIn(target, optional speed, optional extra information); + $this->jquery->fadeOut(target, optional speed, optional extra information); + + +- "target" will be any valid jQuery selector or selectors. +- "speed" is optional, and is set to either slow, normal, fast, or + alternatively a number of milliseconds. +- "extra information" is optional, and could include a callback, or + other additional information. + +toggleClass() +------------- + +This function will add or remove a CSS class to its target. + +:: + + $this->jquery->toggleClass(target, class) + + +- "target" will be any valid jQuery selector or selectors. +- "class" is any CSS classname. Note that this class must be defined + and available in a CSS that is already loaded. + +fadeIn() / fadeOut() +-------------------- + +These effects cause an element(s) to disappear or reappear over time. + +:: + + $this->jquery->fadeIn(target, optional speed, optional extra information); + $this->jquery->fadeOut(target, optional speed, optional extra information); + + +- "target" will be any valid jQuery selector or selectors. +- "speed" is optional, and is set to either slow, normal, fast, or + alternatively a number of milliseconds. +- "extra information" is optional, and could include a callback, or + other additional information. + +slideUp() / slideDown() / slideToggle() +--------------------------------------- + +These effects cause an element(s) to slide. + +:: + + $this->jquery->slideUp(target, optional speed, optional extra information); + $this->jquery->slideDown(target, optional speed, optional extra information); + $this->jquery->slideToggle(target, optional speed, optional extra information); + + +- "target" will be any valid jQuery selector or selectors. +- "speed" is optional, and is set to either slow, normal, fast, or + alternatively a number of milliseconds. +- "extra information" is optional, and could include a callback, or + other additional information. + +Plugins +======= + +Some select jQuery plugins are made available using this library. + +corner() +-------- + +Used to add distinct corners to page elements. For full details see +`http://malsup.com/jquery/corner/ `_ + +:: + + $this->jquery->corner(target, corner_style); + + +- "target" will be any valid jQuery selector or selectors. +- "corner_style" is optional, and can be set to any valid style such + as round, sharp, bevel, bite, dog, etc. Individual corners can be set + by following the style with a space and using "tl" (top left), "tr" + (top right), "bl" (bottom left), or "br" (bottom right). + +:: + + $this->jquery->corner("#note", "cool tl br"); + + +tablesorter() +------------- + +description to come + +modal() +------- + +description to come + +calendar() +---------- + +description to come \ No newline at end of file diff --git a/user_guide_src/source/libraries/language.rst b/user_guide_src/source/libraries/language.rst index 262d9733ab6..de17c82888f 100644 --- a/user_guide_src/source/libraries/language.rst +++ b/user_guide_src/source/libraries/language.rst @@ -92,7 +92,7 @@ Internationalization The Language class in CodeIgniter is meant to provide an easy and lightweight way to support multiplelanguages in your application. It is not meant to be a full implementation of what is commonly called `internationalization and localization -`_. +`_. We use the term "idiom" to refer to a language using its common name, rather than using any of the international standards, such as "en", "en-US", diff --git a/user_guide_src/source/libraries/loader.rst b/user_guide_src/source/libraries/loader.rst index 4d3d512361d..22abb4586db 100644 --- a/user_guide_src/source/libraries/loader.rst +++ b/user_guide_src/source/libraries/loader.rst @@ -238,7 +238,7 @@ Class Reference The second **optional** parameter can take an associative array or an object as input, which it runs through the PHP - `extract() `_ function to convert to variables + `extract() `_ function to convert to variables that can be used in your view files. Again, read the :doc:`Views <../general/views>` page to learn how this might be useful. @@ -259,7 +259,7 @@ Class Reference :rtype: CI_Loader This method takes an associative array as input and generates - variables using the PHP `extract() `_ + variables using the PHP `extract() `_ function. This method produces the same result as using the second parameter of the ``$this->load->view()`` method above. The reason you might want to use this method independently is if you would like to diff --git a/user_guide_src/source/libraries/output.rst b/user_guide_src/source/libraries/output.rst index a24f3cb5201..92060f66a8e 100644 --- a/user_guide_src/source/libraries/output.rst +++ b/user_guide_src/source/libraries/output.rst @@ -163,7 +163,7 @@ Class Reference $this->output->set_status_header(401); // Sets the header as: Unauthorized - `See here `_ for a full list of headers. + `See here `_ for a full list of headers. .. note:: This method is an alias for :doc:`Common function <../general/common_functions>` :func:`set_status_header()`. @@ -207,7 +207,7 @@ Class Reference For more information, please see the :doc:`caching documentation <../general/caching>`. - .. php:method:: _display([$output = NULL]) + .. php:method:: _display([$output = '']) :param string $output: Output data override :returns: void diff --git a/user_guide_src/source/libraries/parser.rst b/user_guide_src/source/libraries/parser.rst index 43ef5ee5682..0b0d4174083 100644 --- a/user_guide_src/source/libraries/parser.rst +++ b/user_guide_src/source/libraries/parser.rst @@ -9,7 +9,7 @@ It can parse simple variables or variable tag pairs. If you've never used a template engine, pseudo-variable names are enclosed in braces, like this:: - + {blog_title} @@ -95,7 +95,7 @@ you would like an entire block of variables to be repeated, with each iteration containing new values? Consider the template example we showed at the top of the page:: - + {blog_title} diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst index f2236c633a6..994dc2e080f 100644 --- a/user_guide_src/source/libraries/sessions.rst +++ b/user_guide_src/source/libraries/sessions.rst @@ -112,7 +112,7 @@ Session data is simply an array associated with a particular session ID (cookie). If you've used sessions in PHP before, you should be familiar with PHP's -`$_SESSION superglobal `_ +`$_SESSION superglobal `_ (if not, please read the content on that link). CodeIgniter gives access to its session data through the same means, as it @@ -391,7 +391,7 @@ Destroying a Session ==================== To clear the current session (for example, during a logout), you may -simply use either PHP's `session_destroy() `_ +simply use either PHP's `session_destroy() `_ function, or the ``sess_destroy()`` method. Both will work in exactly the same way:: @@ -516,7 +516,7 @@ mind that it is in fact not the same code and it has some limitations To be more specific, it doesn't support PHP's `directory level and mode formats used in session.save_path -`_, +`_, and it has most of the options hard-coded for safety. Instead, only absolute paths are supported for ``$config['sess_save_path']``. @@ -554,7 +554,7 @@ increase - which is the time when it matters - the file system will consistently outperform almost all relational database setups. In addition, if performance is your only concern, you may want to look -into using `tmpfs `_, +into using `tmpfs `_, (warning: external resource), which can make your sessions blazing fast. Database Driver @@ -679,7 +679,7 @@ Memcached Driver The 'memcached' driver is very similar to the 'redis' one in all of its properties, except perhaps for availability, because PHP's `Memcached -`_ extension is distributed via PECL and some +`_ extension is distributed via PECL and some Linux distrubutions make it available as an easy to install package. Other than that, and without any intentional bias towards Redis, there's @@ -754,7 +754,7 @@ when creating a session driver for CodeIgniter: - Implement the `SessionHandlerInterface - `_ interface. + `_ interface. .. note:: You may notice that ``SessionHandlerInterface`` is provided by PHP since version 5.4.0. CodeIgniter will automatically declare @@ -1016,7 +1016,7 @@ Class Reference .. note:: This method is just an alias for PHP's native `session_regenerate_id() - `_ function. + `_ function. .. php:method:: sess_destroy() @@ -1030,7 +1030,7 @@ Class Reference .. note:: This method is just an alias for PHP's native `session_destroy() - `_ function. + `_ function. .. php:method:: __get($key) diff --git a/user_guide_src/source/libraries/table.rst b/user_guide_src/source/libraries/table.rst index 06dfe59de09..91ae1ae8dbd 100644 --- a/user_guide_src/source/libraries/table.rst +++ b/user_guide_src/source/libraries/table.rst @@ -275,16 +275,11 @@ Class Reference :returns: CI_Table instance (method chaining) :rtype: CI_Table - Lets you clear the table heading, row data and caption. If - you need to show multiple tables with different data you - should to call this method after each table has been - generated to clear the previous table information. - - Example :: + Lets you clear the table heading and row data. If you need to show multiple tables with different data you should to call this method + after each table has been generated to clear the previous table information. Example:: $this->load->library('table'); - $this->table->set_caption('Preferences'); $this->table->set_heading('Name', 'Color', 'Size'); $this->table->add_row('Fred', 'Blue', 'Small'); $this->table->add_row('Mary', 'Red', 'Large'); @@ -294,7 +289,6 @@ Class Reference $this->table->clear(); - $this->table->set_caption('Shipping'); $this->table->set_heading('Name', 'Day', 'Delivery'); $this->table->add_row('Fred', 'Wednesday', 'Express'); $this->table->add_row('Mary', 'Monday', 'Air'); diff --git a/user_guide_src/source/libraries/trackback.rst b/user_guide_src/source/libraries/trackback.rst index abc608b7dc2..dc4477e9f1e 100644 --- a/user_guide_src/source/libraries/trackback.rst +++ b/user_guide_src/source/libraries/trackback.rst @@ -6,7 +6,7 @@ The Trackback Class provides functions that enable you to send and receive Trackback data. If you are not familiar with Trackbacks you'll find more information -`here `_. +`here `_. .. contents:: :local: diff --git a/user_guide_src/source/libraries/xmlrpc.rst b/user_guide_src/source/libraries/xmlrpc.rst index a9a899d7b31..2fe07c49def 100644 --- a/user_guide_src/source/libraries/xmlrpc.rst +++ b/user_guide_src/source/libraries/xmlrpc.rst @@ -73,7 +73,7 @@ information: - The *request* data (explained below). Here is a basic example that sends a simple Weblogs.com ping to the -`Ping-o-Matic `_ +`Ping-o-Matic `_ :: diff --git a/user_guide_src/source/overview/at_a_glance.rst b/user_guide_src/source/overview/at_a_glance.rst index d5e5bf9291f..742d7bd0e47 100644 --- a/user_guide_src/source/overview/at_a_glance.rst +++ b/user_guide_src/source/overview/at_a_glance.rst @@ -111,4 +111,4 @@ CodeIgniter has a Friendly Community of Users ============================================= Our growing community of users can be seen actively participating in our -`Community Forums `_. +`Community Forums `_. diff --git a/user_guide_src/source/overview/getting_started.rst b/user_guide_src/source/overview/getting_started.rst index a5181d96d9e..04ee50df736 100644 --- a/user_guide_src/source/overview/getting_started.rst +++ b/user_guide_src/source/overview/getting_started.rst @@ -19,6 +19,6 @@ Reference** and **Helper Reference** pages to learn to utilize the native libraries and helper files. Feel free to take advantage of our `Community -Forums `_ if you have questions or +Forums `_ if you have questions or problems, and our `Wiki `_ to see code examples posted by other users. diff --git a/user_guide_src/source/tutorial/conclusion.rst b/user_guide_src/source/tutorial/conclusion.rst index fa41c4492fb..0d90cde6f62 100644 --- a/user_guide_src/source/tutorial/conclusion.rst +++ b/user_guide_src/source/tutorial/conclusion.rst @@ -20,7 +20,7 @@ CodeIgniter within a few days. If you still have questions about the framework or your own CodeIgniter code, you can: -- Check out our `forums `_ +- Check out our `forums `_ - Visit our `IRC chatroom `_ - Explore the `Wiki `_ diff --git a/user_guide_src/source/tutorial/static_pages.rst b/user_guide_src/source/tutorial/static_pages.rst index 8db105555b2..561082a4897 100644 --- a/user_guide_src/source/tutorial/static_pages.rst +++ b/user_guide_src/source/tutorial/static_pages.rst @@ -58,7 +58,7 @@ the following code: :: - + CodeIgniter Tutorial