From ff63adecdcf90189d52752f0457b3741e84a0c30 Mon Sep 17 00:00:00 2001 From: Aaron Gong Date: Mon, 7 Mar 2016 22:26:07 +0800 Subject: [PATCH 1/7] Fix For #339 https://github.com/jekkos/opensourcepos/issues/339 We should also rollout the fixes to develop/2.4 if necessary. This fix was adapted from BootstrapUI which fixed the PHP 7 error regarding classes. --- application/controllers/customers.php | 4 ++-- application/controllers/employees.php | 2 +- application/controllers/suppliers.php | 2 +- application/models/customer.php | 2 +- application/models/employee.php | 2 +- application/models/supplier.php | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/application/controllers/customers.php b/application/controllers/customers.php index 833f012ca..68b431ed1 100644 --- a/application/controllers/customers.php +++ b/application/controllers/customers.php @@ -75,7 +75,7 @@ class Customers extends Person_controller 'company_name'=>$this->input->post('company_name')=='' ? null:$this->input->post('company_name'), 'taxable'=>$this->input->post('taxable')=='' ? 0:1, ); - if($this->Customer->save($person_data,$customer_data,$customer_id)) + if($this->Customer->save_customer($person_data,$customer_data,$customer_id)) { //New customer if($customer_id==-1) @@ -179,7 +179,7 @@ class Customers extends Person_controller $invalidated = $this->Customer->account_number_exists($account_number); } - if($invalidated || !$this->Customer->save($person_data,$customer_data)) + if($invalidated || !$this->Customer->save_customer($person_data,$customer_data)) { $failCodes[] = $i; } diff --git a/application/controllers/employees.php b/application/controllers/employees.php index d9da8e255..0c8bb6be0 100644 --- a/application/controllers/employees.php +++ b/application/controllers/employees.php @@ -87,7 +87,7 @@ class Employees extends Person_controller $employee_data=array('username'=>$this->input->post('username')); } - if($this->Employee->save($person_data,$employee_data,$grants_data,$employee_id)) + if($this->Employee->save_employee($person_data,$employee_data,$grants_data,$employee_id)) { //New employee if($employee_id==-1) diff --git a/application/controllers/suppliers.php b/application/controllers/suppliers.php index f3346008e..a6803634d 100644 --- a/application/controllers/suppliers.php +++ b/application/controllers/suppliers.php @@ -76,7 +76,7 @@ class Suppliers extends Person_controller 'agency_name'=>$this->input->post('agency_name'), 'account_number'=>$this->input->post('account_number')=='' ? null:$this->input->post('account_number'), ); - if($this->Supplier->save($person_data,$supplier_data,$supplier_id)) + if($this->Supplier->save_supplier($person_data,$supplier_data,$supplier_id)) { //New supplier if($supplier_id==-1) diff --git a/application/models/customer.php b/application/models/customer.php index 1422c4508..2c6b2e9ef 100644 --- a/application/models/customer.php +++ b/application/models/customer.php @@ -95,7 +95,7 @@ class Customer extends Person /* Inserts or updates a customer */ - function save(&$person_data, &$customer_data,$customer_id=false) + function save_customer(&$person_data, &$customer_data,$customer_id=false) { $success=false; //Run these queries as a transaction, we want to make sure we do all or nothing diff --git a/application/models/employee.php b/application/models/employee.php index 6429c8069..6b49c0ac4 100644 --- a/application/models/employee.php +++ b/application/models/employee.php @@ -81,7 +81,7 @@ class Employee extends Person /* Inserts or updates an employee */ - function save(&$person_data, &$employee_data,&$grants_data,$employee_id=false) + function save_employee(&$person_data, &$employee_data,&$grants_data,$employee_id=false) { $success=false; diff --git a/application/models/supplier.php b/application/models/supplier.php index ea5894237..aaefeb416 100644 --- a/application/models/supplier.php +++ b/application/models/supplier.php @@ -90,7 +90,7 @@ class Supplier extends Person /* Inserts or updates a suppliers */ - function save(&$person_data, &$supplier_data,$supplier_id=false) + function save_supplier(&$person_data, &$supplier_data,$supplier_id=false) { $success=false; //Run these queries as a transaction, we want to make sure we do all or nothing From 9c39f62b1e6c2cf00bd34eb7c43b25fb2993204c Mon Sep 17 00:00:00 2001 From: jekkos Date: Thu, 10 Mar 2016 08:25:32 +0100 Subject: [PATCH 2/7] Fix sale search form submission on enter (#386) Add php5-apcu to Dockerfile (#320, 284) Fix countrycode parameter for nominatim address lookup --- Dockerfile | 2 +- js/manage_tables.js | 7 +++++-- js/nominatim.autocomplete.js | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index b5258d91b..7fc1af1af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ MAINTAINER jekkos RUN sed -i -e 's/archive.ubuntu.com\|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list RUN apt-get update RUN apt-get -y upgrade -RUN DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-client mysql-server apache2 libapache2-mod-php5 pwgen python-setuptools vim-tiny php5-mysql php5-gd nodejs npm curl +RUN DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-client mysql-server apache2 libapache2-mod-php5 pwgen python-setuptools vim-tiny php5-mysql php5-gd php5-apcu nodejs npm curl RUN easy_install supervisor ADD ./docker/foreground.sh /etc/apache2/foreground.sh ADD ./docker/supervisord.conf /etc/supervisord.conf diff --git a/js/manage_tables.js b/js/manage_tables.js index 13f170e6b..e72b0b098 100644 --- a/js/manage_tables.js +++ b/js/manage_tables.js @@ -33,8 +33,11 @@ function enable_search(options) $("#search").result(function(event, data, formatted) { do_search(true, options.on_complete); - }); - + }).on("keypress", function(event) { + if(event.which == 13) { + do_search(true, options.on_complete); + } + }); attach_search_listener(); $('#search_form').submit(function(event) diff --git a/js/nominatim.autocomplete.js b/js/nominatim.autocomplete.js index 710a271af..2ad826baf 100644 --- a/js/nominatim.autocomplete.js +++ b/js/nominatim.autocomplete.js @@ -78,7 +78,7 @@ format: 'json', limit: 5, addressdetails: 1, - country: window['sessionStorage'] ? sessionStorage['country'] : 'be', + countrycodes: window['sessionStorage'] ? sessionStorage['country'] : 'be', 'accept-language' : language || navigator.language }; result[key || id] = $("#"+id).val(); From d510ab031d140cc71aa5ead48941a0516b8a03c6 Mon Sep 17 00:00:00 2001 From: jekkos Date: Thu, 10 Mar 2016 08:36:17 +0100 Subject: [PATCH 3/7] Update README.md with FAQ and answer to common setup problem (#387, #97, --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ed669759e..752887620 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,10 @@ username: admin password:pointofsale 9. Enjoy +FAQ +--- +If an blank page (HTTP status 500) shows after search completion or receipt generation, then double check php5-gd presence in your php installation. On windows check in php.ini whether the lib is installed. On Ubuntu issue `sudo apt-get install php5-gd`. Also have a look at the Dockerfile for a complete list of recommended packages. + 13/01/2016: Install using Docker ------------------------------- From now on ospos can be deployed using Docker on Linux, Mac or Windows. This setup dramatically reduces the number of possible issues as all setup is now done in a Dockerfile. Docker runs natively on mac and linux, but will require more overhead on windows. Please refer to the docker documentation for instructions on how to set it up on your platform. From 0bd5bbec77915fbe5463d3f4b9418a5b3d203083 Mon Sep 17 00:00:00 2001 From: FrancescoUK Date: Sun, 13 Mar 2016 10:52:32 +0000 Subject: [PATCH 4/7] remove encode/decode base64 causing issues with web hosting providers (#374) --- application/libraries/Receiving_lib.php | 6 +++--- application/libraries/Sale_lib.php | 6 +++--- application/models/Receiving.php | 5 ++--- application/models/Sale.php | 2 +- application/models/Sale_suspended.php | 2 +- application/views/receivings/receipt.php | 2 +- application/views/receivings/receiving.php | 10 +++++----- application/views/sales/invoice.php | 2 +- application/views/sales/receipt.php | 4 ++-- application/views/sales/register.php | 10 +++++----- 10 files changed, 24 insertions(+), 25 deletions(-) diff --git a/application/libraries/Receiving_lib.php b/application/libraries/Receiving_lib.php index c4b0be7c9..44d57b8a6 100644 --- a/application/libraries/Receiving_lib.php +++ b/application/libraries/Receiving_lib.php @@ -200,8 +200,8 @@ class Receiving_lib 'item_location'=>$item_location, 'stock_name'=>$this->CI->Stock_location->get_location_name($item_location), 'line'=>$insertkey, - 'name'=>base64_encode($item_info->name), - 'description'=>base64_encode($description!=null ? $description: $item_info->description), + 'name'=>$item_info->name, + 'description'=>$description!=null ? $description: $item_info->description, 'serialnumber'=>$serialnumber!=null ? $serialnumber: '', 'allow_alt_description'=>$item_info->allow_alt_description, 'is_serialized'=>$item_info->is_serialized, @@ -236,7 +236,7 @@ class Receiving_lib if(isset($items[$line])) { $line = &$items[$line]; - $line['description'] = base64_encode($description); + $line['description'] = $description; $line['serialnumber'] = $serialnumber; $line['quantity'] = $quantity; $line['discount'] = $discount; diff --git a/application/libraries/Sale_lib.php b/application/libraries/Sale_lib.php index 8861238b9..e6ba00a18 100644 --- a/application/libraries/Sale_lib.php +++ b/application/libraries/Sale_lib.php @@ -305,9 +305,9 @@ class Sale_lib 'item_location'=>$item_location, 'stock_name'=>$this->CI->Stock_location->get_location_name($item_location), 'line'=>$insertkey, - 'name'=>base64_encode($item_info->name), + 'name'=>$item_info->name, 'item_number'=>$item_info->item_number, - 'description'=>base64_encode($description!=null ? $description: $item_info->description), + 'description'=>$description!=null ? $description: $item_info->description, 'serialnumber'=>$serialnumber!=null ? $serialnumber: '', 'allow_alt_description'=>$item_info->allow_alt_description, 'is_serialized'=>$item_info->is_serialized, @@ -395,7 +395,7 @@ class Sale_lib if(isset($items[$line])) { $line = &$items[$line]; - $line['description'] = base64_encode($description); + $line['description'] = $description; $line['serialnumber'] = $serialnumber; $line['quantity'] = $quantity; $line['discount'] = $discount; diff --git a/application/models/Receiving.php b/application/models/Receiving.php index 905d4396c..2de3f5230 100644 --- a/application/models/Receiving.php +++ b/application/models/Receiving.php @@ -76,12 +76,11 @@ class Receiving extends CI_Model $cur_item_info = $this->Item->get_info($item['item_id']); - $receivings_items_data = array - ( + $receivings_items_data = array( 'receiving_id'=>$receiving_id, 'item_id'=>$item['item_id'], 'line'=>$item['line'], - 'description'=>base64_decode($item['description']), + 'description'=>$item['description'], 'serialnumber'=>$item['serialnumber'], 'quantity_purchased'=>$item['quantity'], 'receiving_quantity'=>$item['receiving_quantity'], diff --git a/application/models/Sale.php b/application/models/Sale.php index 0a30adc3e..56a6a1e00 100644 --- a/application/models/Sale.php +++ b/application/models/Sale.php @@ -296,7 +296,7 @@ class Sale extends CI_Model 'sale_id'=>$sale_id, 'item_id'=>$item['item_id'], 'line'=>$item['line'], - 'description'=>character_limiter(base64_decode($item['description']), 30), + 'description'=>character_limiter($item['description'], 30), 'serialnumber'=>character_limiter($item['serialnumber'], 30), 'quantity_purchased'=>$item['quantity'], 'discount_percent'=>$item['discount'], diff --git a/application/models/Sale_suspended.php b/application/models/Sale_suspended.php index 993e81e71..df3324616 100644 --- a/application/models/Sale_suspended.php +++ b/application/models/Sale_suspended.php @@ -86,7 +86,7 @@ class Sale_suspended extends CI_Model 'sale_id'=>$sale_id, 'item_id'=>$item['item_id'], 'line'=>$item['line'], - 'description'=>character_limiter(base64_decode($item['description']), 30), + 'description'=>character_limiter($item['description'], 30), 'serialnumber'=>character_limiter($item['serialnumber'], 30), 'quantity_purchased'=>$item['quantity'], 'discount_percent'=>$item['discount'], diff --git a/application/views/receivings/receipt.php b/application/views/receivings/receipt.php index eca4b8149..5e11b0308 100644 --- a/application/views/receivings/receipt.php +++ b/application/views/receivings/receipt.php @@ -61,7 +61,7 @@ if (isset($error_message)) { ?> - + lang->line('common_delete').']');?> -
[ in ] +
[ in ] 'description','value'=>base64_decode($item['description']),'size'=>'20')); + echo form_input(array('name'=>'description','value'=>$item['description'],'size'=>'20')); } else { - if (base64_decode($item['description'])!='') + if ($item['description']!='') { - echo base64_decode($item['description']); - echo form_hidden('description',base64_decode($item['description'])); + echo $item['description']; + echo form_hidden('description',$item['description']); } else { diff --git a/application/views/sales/invoice.php b/application/views/sales/invoice.php index 2d6f1142b..7e462cbcd 100755 --- a/application/views/sales/invoice.php +++ b/application/views/sales/invoice.php @@ -75,7 +75,7 @@ if (isset($error_message)) ?> - + diff --git a/application/views/sales/receipt.php b/application/views/sales/receipt.php index ccba2159b..02d4e27c3 100644 --- a/application/views/sales/receipt.php +++ b/application/views/sales/receipt.php @@ -61,7 +61,7 @@ if (isset($error_message)) { ?> - + @@ -71,7 +71,7 @@ if (isset($error_message))
Appconfig->get('show_total_discount') ? 'total' : 'discounted_total')]); ?>
- + 0) : ?> diff --git a/application/views/sales/register.php b/application/views/sales/register.php index aea880ecd..411fba4f9 100644 --- a/application/views/sales/register.php +++ b/application/views/sales/register.php @@ -108,7 +108,7 @@ if (isset($success)) lang->line('common_delete').']');?> -
[ in ] +
[ in ] @@ -159,14 +159,14 @@ if (isset($success)) 'description','value'=>base64_decode($item['description']),'size'=>'20')); + echo form_input(array('name'=>'description','value'=>$item['description'],'size'=>'20')); } else { - if (base64_decode($item['description'])!='') + if ($item['description']!='') { - echo base64_decode($item['description']); - echo form_hidden('description',base64_decode($item['description'])); + echo $item['description']; + echo form_hidden('description',$item['description']); } else { From 4ad0d62f42b1a7f72555ef06435dcfb88004a7d6 Mon Sep 17 00:00:00 2001 From: FrancescoUK Date: Sun, 13 Mar 2016 11:26:51 +0000 Subject: [PATCH 5/7] Upgrade to CI3.0.5 (#292) --- system/core/CodeIgniter.php | 4 +- system/core/Loader.php | 26 ++- system/core/Log.php | 27 ++- system/core/Output.php | 2 +- system/core/Security.php | 9 +- system/database/DB_driver.php | 10 +- system/database/DB_query_builder.php | 154 +++++++++++------- .../database/drivers/ibase/ibase_driver.php | 2 +- system/helpers/captcha_helper.php | 53 +++--- system/helpers/form_helper.php | 4 +- system/helpers/inflector_helper.php | 2 +- system/helpers/text_helper.php | 21 ++- system/libraries/Cache/drivers/Cache_apc.php | 27 ++- .../Cache/drivers/Cache_memcached.php | 1 + .../libraries/Cache/drivers/Cache_redis.php | 6 + .../Cache/drivers/Cache_wincache.php | 27 ++- system/libraries/Email.php | 18 +- system/libraries/Form_validation.php | 74 +++++---- system/libraries/Pagination.php | 12 +- system/libraries/Profiler.php | 44 ++--- system/libraries/Session/Session.php | 2 +- system/libraries/Session/Session_driver.php | 20 +++ .../drivers/Session_database_driver.php | 21 ++- .../drivers/Session_memcached_driver.php | 57 ++++--- .../Session/drivers/Session_redis_driver.php | 41 +++-- system/libraries/Upload.php | 6 + 26 files changed, 423 insertions(+), 247 deletions(-) diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 053510334..94d34c3fd 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -55,7 +55,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); * @var string * */ - define('CI_VERSION', '3.0.4'); + define('CI_VERSION', '3.0.5'); /* * ------------------------------------------------------ @@ -359,7 +359,7 @@ if ( ! is_php('5.4')) * * Returns current CI instance object * - * @return object + * @return CI_Controller */ function &get_instance() { diff --git a/system/core/Loader.php b/system/core/Loader.php index 37d1ecaf9..c742ae71a 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -321,7 +321,7 @@ class CI_Loader { } $model = ucfirst($model); - if ( ! class_exists($model)) + if ( ! class_exists($model, FALSE)) { foreach ($this->_ci_model_paths as $mod_path) { @@ -718,9 +718,16 @@ class CI_Loader { { if (is_array($library)) { - foreach ($library as $driver) + foreach ($library as $key => $value) { - $this->driver($driver); + if (is_int($key)) + { + $this->driver($value, $params); + } + else + { + $this->driver($key, $params, $value); + } } return $this; @@ -929,6 +936,14 @@ class CI_Loader { */ if (is_array($_ci_vars)) { + foreach (array_keys($_ci_vars) as $key) + { + if (strncmp($key, '_ci_', 4) === 0) + { + unset($_ci_vars[$key]); + } + } + $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars); } extract($this->_ci_cached_vars); @@ -1334,10 +1349,7 @@ class CI_Loader { // Autoload drivers if (isset($autoload['drivers'])) { - foreach ($autoload['drivers'] as $item) - { - $this->driver($item); - } + $this->driver($autoload['drivers']); } // Load libraries diff --git a/system/core/Log.php b/system/core/Log.php index 72d3cfbae..1abdaa00e 100644 --- a/system/core/Log.php +++ b/system/core/Log.php @@ -154,8 +154,8 @@ class CI_Log { * * Generally this function will be called using the global log_message() function * - * @param string the error level: 'error', 'debug' or 'info' - * @param string the error message + * @param string $level The error level: 'error', 'debug' or 'info' + * @param string $msg The error message * @return bool */ public function write_log($level, $msg) @@ -191,6 +191,8 @@ class CI_Log { return FALSE; } + flock($fp, LOCK_EX); + // Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format if (strpos($this->_date_fmt, 'u') !== FALSE) { @@ -204,9 +206,7 @@ class CI_Log { $date = date($this->_date_fmt); } - $message .= $level.' - '.$date.' --> '.$msg."\n"; - - flock($fp, LOCK_EX); + $message .= $this->_format_line($level, $date, $msg); for ($written = 0, $length = strlen($message); $written < $length; $written += $result) { @@ -227,4 +227,21 @@ class CI_Log { return is_int($result); } + // -------------------------------------------------------------------- + + /** + * Format the log line. + * + * This is for extensibility of log formatting + * If you want to change the log format, extend the CI_Log class and override this method + * + * @param string $level The error level + * @param string $date Formatted date string + * @param string $msg The log message + * @return string Formatted log line with a new line character '\n' at the end + */ + protected function _format_line($level, $date, $message) + { + return $level.' - '.$date.' --> '.$message."\n"; + } } diff --git a/system/core/Output.php b/system/core/Output.php index ad87f8545..ec9c21b91 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -377,7 +377,7 @@ class CI_Output { /** * Set Cache * - * @param int $time Cache expiration time in seconds + * @param int $time Cache expiration time in minutes * @return CI_Output */ public function cache($time) diff --git a/system/core/Security.php b/system/core/Security.php index bad511dd3..d5305d1ca 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -762,7 +762,14 @@ class CI_Security { */ public function strip_image_tags($str) { - return preg_replace(array('##', '##'), '\\1', $str); + return preg_replace( + array( + '##i', + '#`]+)).*?\>#i' + ), + '\\2', + $str + ); } // ---------------------------------------------------------------- diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index df0ce6a9b..848516adc 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -1566,11 +1566,11 @@ abstract class CI_DB_driver { '\s*>\s*', // > '\s+IS NULL', // IS NULL '\s+IS NOT NULL', // IS NOT NULL - '\s+EXISTS\s*\([^\)]+\)', // EXISTS(sql) - '\s+NOT EXISTS\s*\([^\)]+\)', // NOT EXISTS(sql) + '\s+EXISTS\s*\(.*\)', // EXISTS(sql) + '\s+NOT EXISTS\s*\(.*\)', // NOT EXISTS(sql) '\s+BETWEEN\s+', // BETWEEN value AND value - '\s+IN\s*\([^\)]+\)', // IN(list) - '\s+NOT IN\s*\([^\)]+\)', // NOT IN (list) + '\s+IN\s*\(.*\)', // IN(list) + '\s+NOT IN\s*\(.*\)', // NOT IN (list) '\s+LIKE\s+\S.*('.$_les.')?', // LIKE 'expr'[ ESCAPE '%s'] '\s+NOT LIKE\s+\S.*('.$_les.')?' // NOT LIKE 'expr'[ ESCAPE '%s'] ); @@ -1793,7 +1793,7 @@ abstract class CI_DB_driver { * the table prefix onto it. Some logic is necessary in order to deal with * column names that include the path. Consider a query like this: * - * SELECT * FROM hostname.database.table.column AS c FROM hostname.database.table + * SELECT hostname.database.table.column AS c FROM hostname.database.table * * Or a query with aliasing: * diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index e92c57091..c862d937d 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -531,40 +531,47 @@ abstract class CI_DB_query_builder extends CI_DB_driver { is_bool($escape) OR $escape = $this->_protect_identifiers; - // Split multiple conditions - if ($escape === TRUE && preg_match_all('/\sAND\s|\sOR\s/i', $cond, $m, PREG_OFFSET_CAPTURE)) - { - $newcond = ''; - $m[0][] = array('', strlen($cond)); - - for ($i = 0, $c = count($m[0]), $s = 0; - $i < $c; - $s = $m[0][$i][1] + strlen($m[0][$i][0]), $i++) - { - $temp = substr($cond, $s, ($m[0][$i][1] - $s)); - - $newcond .= preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $temp, $match) - ? $this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]) - : $temp; - - $newcond .= $m[0][$i][0]; - } - - $cond = ' ON '.$newcond; - } - // Split apart the condition and protect the identifiers - elseif ($escape === TRUE && preg_match("/([\[\]\w\.'-]+)(\s*[^\"\[`'\w]+\s*)(.+)/i", $cond, $match)) - { - $cond = ' ON '.$this->protect_identifiers($match[1]).$match[2].$this->protect_identifiers($match[3]); - } - elseif ( ! $this->_has_operator($cond)) + if ( ! $this->_has_operator($cond)) { $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')'; } - else + elseif ($escape === FALSE) { $cond = ' ON '.$cond; } + else + { + // Split multiple conditions + if (preg_match_all('/\sAND\s|\sOR\s/i', $cond, $joints, PREG_OFFSET_CAPTURE)) + { + $conditions = array(); + $joints = $joints[0]; + array_unshift($joints, array('', 0)); + + for ($i = count($joints) - 1, $pos = strlen($cond); $i >= 0; $i--) + { + $joints[$i][1] += strlen($joints[$i][0]); // offset + $conditions[$i] = substr($cond, $joints[$i][1], $pos - $joints[$i][1]); + $pos = $joints[$i][1] - strlen($joints[$i][0]); + $joints[$i] = $joints[$i][0]; + } + } + else + { + $conditions = array($cond); + $joints = array(''); + } + + $cond = ' ON '; + for ($i = 0, $c = count($conditions); $i < $c; $i++) + { + $operator = $this->_get_operator($conditions[$i]); + $cond .= $joints[$i]; + $cond .= preg_match("/(\(*)?([\[\]\w\.'-]+)".preg_quote($operator)."(.*)/i", $conditions[$i], $match) + ? $match[1].$this->protect_identifiers($match[2]).$operator.$this->protect_identifiers($match[3]) + : $conditions[$i]; + } + } // Do we want to escape the table name? if ($escape === TRUE) @@ -1138,7 +1145,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string $key * @param string $value * @param bool $escape - * @return object + * @return CI_DB_query_builder */ public function having($key, $value = NULL, $escape = NULL) { @@ -1155,7 +1162,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string $key * @param string $value * @param bool $escape - * @return object + * @return CI_DB_query_builder */ public function or_having($key, $value = NULL, $escape = NULL) { @@ -1339,7 +1346,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string the table * @param string the limit clause * @param string the offset clause - * @return object + * @return CI_DB_result */ public function get($table = '', $limit = NULL, $offset = NULL) { @@ -1379,7 +1386,16 @@ abstract class CI_DB_query_builder extends CI_DB_driver { $this->from($table); } - $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_orderby)) + // ORDER BY usage is often problematic here (most notably + // on Microsoft SQL Server) and ultimately unnecessary + // for selecting COUNT(*) ... + if ( ! empty($this->qb_orderby)) + { + $orderby = $this->qb_orderby; + $this->qb_orderby = NULL; + } + + $result = ($this->qb_distinct === TRUE) ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results") : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); @@ -1387,6 +1403,11 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { $this->_reset_select(); } + // If we've previously reset the qb_orderby values, get them back + elseif ( ! isset($this->qb_orderby)) + { + $this->qb_orderby = $orderby; + } if ($result->num_rows() === 0) { @@ -1408,7 +1429,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string $where * @param int $limit * @param int $offset - * @return object + * @return CI_DB_result */ public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL) { @@ -1444,20 +1465,26 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param bool $escape Whether to escape values and identifiers * @return int Number of rows inserted or FALSE on failure */ - public function insert_batch($table = '', $set = NULL, $escape = NULL) + public function insert_batch($table, $set = NULL, $escape = NULL, $batch_size = 100) { - if ($set !== NULL) + if ($set === NULL) { + if (empty($this->qb_set)) + { + return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; + } + } + else + { + if (empty($set)) + { + return ($this->db_debug) ? $this->display_error('insert_batch() called with no data') : FALSE; + } + $this->set_insert_batch($set, '', $escape); } - if (count($this->qb_set) === 0) - { - // No valid data array. Folds in cases where keys and values did not match up - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - - if ($table === '') + if (strlen($table) === 0) { if ( ! isset($this->qb_from[0])) { @@ -1469,9 +1496,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // Batch this baby $affected_rows = 0; - for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) + for ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size) { - $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, 100))); + $this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, $batch_size))); $affected_rows += $this->affected_rows(); } @@ -1598,7 +1625,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string the table to insert data into * @param array an associative array of insert values * @param bool $escape Whether to escape values and identifiers - * @return object + * @return bool TRUE on success, FALSE on failure */ public function insert($table = '', $set = NULL, $escape = NULL) { @@ -1664,7 +1691,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @param string the table to replace data into * @param array an associative array of insert values - * @return object + * @return bool TRUE on success, FALSE on failure */ public function replace($table = '', $set = NULL) { @@ -1770,7 +1797,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param array $set An associative array of update values * @param mixed $where * @param int $limit - * @return object + * @return bool TRUE on success, FALSE on failure */ public function update($table = '', $set = NULL, $where = NULL, $limit = NULL) { @@ -1845,7 +1872,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * @param string the where key * @return int number of rows affected or FALSE on failure */ - public function update_batch($table = '', $set = NULL, $index = NULL) + public function update_batch($table, $set = NULL, $index = NULL, $batch_size = 100) { // Combine any cached components with the current statements $this->_merge_cache(); @@ -1855,17 +1882,24 @@ abstract class CI_DB_query_builder extends CI_DB_driver { return ($this->db_debug) ? $this->display_error('db_must_use_index') : FALSE; } - if ($set !== NULL) + if ($set === NULL) { + if (empty($this->qb_set)) + { + return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; + } + } + else + { + if (empty($set)) + { + return ($this->db_debug) ? $this->display_error('update_batch() called with no data') : FALSE; + } + $this->set_update_batch($set, $index); } - if (count($this->qb_set) === 0) - { - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - - if ($table === '') + if (strlen($table) === 0) { if ( ! isset($this->qb_from[0])) { @@ -1877,9 +1911,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { // Batch this baby $affected_rows = 0; - for ($i = 0, $total = count($this->qb_set); $i < $total; $i += 100) + for ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size) { - $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index))); + $this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, $batch_size), $this->protect_identifiers($index))); $affected_rows += $this->affected_rows(); $this->qb_where = array(); } @@ -1983,7 +2017,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * Compiles a delete string and runs "DELETE FROM table" * * @param string the table to empty - * @return object + * @return bool TRUE on success, FALSE on failure */ public function empty_table($table = '') { @@ -2016,7 +2050,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * This function maps to "DELETE FROM table" * * @param string the table to truncate - * @return object + * @return bool TRUE on success, FALSE on failure */ public function truncate($table = '') { @@ -2316,7 +2350,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * Escapes identifiers in WHERE and HAVING statements at execution time. * - * Required so that aliases are tracked properly, regardless of wether + * Required so that aliases are tracked properly, regardless of whether * where(), or_where(), having(), or_having are called prior to from(), * join() and dbprefix is added only if needed. * diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php index cbc1022ff..c1055c1e6 100644 --- a/system/database/drivers/ibase/ibase_driver.php +++ b/system/database/drivers/ibase/ibase_driver.php @@ -126,7 +126,7 @@ class CI_DB_ibase_driver extends CI_DB { */ protected function _execute($sql) { - return ibase_query($this->conn_id, $sql); + return ibase_query(isset($this->_ibase_trans) ? $this->_ibase_trans : $this->conn_id, $sql); } // -------------------------------------------------------------------- diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php index fd1b8f1ed..3c1e006f8 100644 --- a/system/helpers/captcha_helper.php +++ b/system/helpers/captcha_helper.php @@ -171,35 +171,36 @@ if ( ! function_exists('create_captcha')) $byte_index = $word_index = 0; while ($word_index < $word_length) { + // Do we have more random data to use? + // It could be exhausted by previous iterations + // ignoring bytes higher than $rand_max. + if ($byte_index === $pool_length) + { + // No failures should be possible if the + // first get_random_bytes() call didn't + // return FALSE, but still ... + for ($i = 0; $i < 5; $i++) + { + if (($bytes = $security->get_random_bytes($pool_length)) === FALSE) + { + continue; + } + + $byte_index = 0; + break; + } + + if ($bytes === FALSE) + { + // Sadly, this means fallback to mt_rand() + $word = ''; + break; + } + } + list(, $rand_index) = unpack('C', $bytes[$byte_index++]); if ($rand_index > $rand_max) { - // Was this the last byte we have? - // If so, try to fetch more. - if ($byte_index === $pool_length) - { - // No failures should be possible if - // the first get_random_bytes() call - // didn't return FALSE, but still ... - for ($i = 0; $i < 5; $i++) - { - if (($bytes = $security->get_random_bytes($pool_length)) === FALSE) - { - continue; - } - - $byte_index = 0; - break; - } - - if ($bytes === FALSE) - { - // Sadly, this means fallback to mt_rand() - $word = ''; - break; - } - } - continue; } diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php index 04778b084..3e1039525 100644 --- a/system/helpers/form_helper.php +++ b/system/helpers/form_helper.php @@ -791,7 +791,7 @@ if ( ! function_exists('set_checkbox')) // Unchecked checkbox and radio inputs are not even submitted by browsers ... if ($CI->input->method() === 'post') { - return ($input === 'value') ? ' checked="checked"' : ''; + return ($input === $value) ? ' checked="checked"' : ''; } return ($default === TRUE) ? ' checked="checked"' : ''; @@ -843,7 +843,7 @@ if ( ! function_exists('set_radio')) // Unchecked checkbox and radio inputs are not even submitted by browsers ... if ($CI->input->method() === 'post') { - return ($input === 'value') ? ' checked="checked"' : ''; + return ($input === $value) ? ' checked="checked"' : ''; } return ($default === TRUE) ? ' checked="checked"' : ''; diff --git a/system/helpers/inflector_helper.php b/system/helpers/inflector_helper.php index 96b723c8d..c064d8de4 100644 --- a/system/helpers/inflector_helper.php +++ b/system/helpers/inflector_helper.php @@ -219,7 +219,7 @@ if ( ! function_exists('humanize')) */ function humanize($str, $separator = '_') { - return ucwords(preg_replace('/['.$separator.']+/', ' ', trim(MB_ENABLED ? mb_strtolower($str) : strtolower($str)))); + return ucwords(preg_replace('/['.preg_quote($separator).']+/', ' ', trim(MB_ENABLED ? mb_strtolower($str) : strtolower($str)))); } } diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php index 1fdbedda5..4f9210f2d 100644 --- a/system/helpers/text_helper.php +++ b/system/helpers/text_helper.php @@ -275,13 +275,28 @@ if ( ! function_exists('word_censor')) foreach ($censored as $badword) { + $badword = str_replace('\*', '\w*?', preg_quote($badword, '/')); if ($replacement !== '') { - $str = preg_replace("/({$delim})(".str_replace('\*', '\w*?', preg_quote($badword, '/')).")({$delim})/i", "\\1{$replacement}\\3", $str); + $str = preg_replace( + "/({$delim})(".$badword.")({$delim})/i", + "\\1{$replacement}\\3", + $str + ); } - else + elseif (preg_match_all("/{$delim}(".$badword."){$delim}/i", $str, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE)) { - $str = preg_replace("/({$delim})(".str_replace('\*', '\w*?', preg_quote($badword, '/')).")({$delim})/ie", "'\\1'.str_repeat('#', strlen('\\2')).'\\3'", $str); + $matches = $matches[1]; + for ($i = count($matches) - 1; $i >= 0; $i--) + { + $length = strlen($matches[$i][0]); + $str = substr_replace( + $str, + str_repeat('#', $length), + $matches[$i][1], + $length + ); + } } } diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php index dd18e7bc8..07ea8f474 100644 --- a/system/libraries/Cache/drivers/Cache_apc.php +++ b/system/libraries/Cache/drivers/Cache_apc.php @@ -48,6 +48,24 @@ defined('BASEPATH') OR exit('No direct script access allowed'); */ class CI_Cache_apc extends CI_Driver { + /** + * Class constructor + * + * Only present so that an error message is logged + * if APC is not available. + * + * @return void + */ + public function __construct() + { + if ( ! $this->is_supported()) + { + log_message('error', 'Cache: Failed to initialize APC; extension not loaded/enabled?'); + } + } + + // ------------------------------------------------------------------------ + /** * Get * @@ -198,13 +216,6 @@ class CI_Cache_apc extends CI_Driver { */ public function is_supported() { - if ( ! extension_loaded('apc') OR ! ini_get('apc.enabled')) - { - log_message('debug', 'The APC PHP extension must be loaded to use APC Cache.'); - return FALSE; - } - - return TRUE; + return (extension_loaded('apc') && ini_get('apc.enabled')); } - } diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php index c44958b97..7e67fc40f 100644 --- a/system/libraries/Cache/drivers/Cache_memcached.php +++ b/system/libraries/Cache/drivers/Cache_memcached.php @@ -107,6 +107,7 @@ class CI_Cache_memcached extends CI_Driver { else { log_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?'); + return; } foreach ($this->_memcache_conf as $cache_server) diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php index 81b49e2fc..e9194a499 100644 --- a/system/libraries/Cache/drivers/Cache_redis.php +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -91,6 +91,12 @@ class CI_Cache_redis extends CI_Driver */ public function __construct() { + if ( ! $this->is_supported()) + { + log_message('error', 'Cache: Failed to create Redis object; extension not loaded?'); + return; + } + $config = array(); $CI =& get_instance(); diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php index f66080514..d6a0d4fb6 100644 --- a/system/libraries/Cache/drivers/Cache_wincache.php +++ b/system/libraries/Cache/drivers/Cache_wincache.php @@ -51,6 +51,24 @@ defined('BASEPATH') OR exit('No direct script access allowed'); */ class CI_Cache_wincache extends CI_Driver { + /** + * Class constructor + * + * Only present so that an error message is logged + * if APC is not available. + * + * @return void + */ + public function __construct() + { + if ( ! $this->is_supported()) + { + log_message('error', 'Cache: Failed to initialize Wincache; extension not loaded/enabled?'); + } + } + + // ------------------------------------------------------------------------ + /** * Get * @@ -194,13 +212,6 @@ class CI_Cache_wincache extends CI_Driver { */ public function is_supported() { - if ( ! extension_loaded('wincache') OR ! ini_get('wincache.ucenabled')) - { - log_message('debug', 'The Wincache PHP extension must be loaded to use Wincache Cache.'); - return FALSE; - } - - return TRUE; + return (extension_loaded('wincache') && ini_get('wincache.ucenabled')); } - } diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 007f9b431..ed6f737a1 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -574,14 +574,18 @@ class CI_Email { $this->validate_email($this->_str_to_array($replyto)); } - if ($name === '') + if ($name !== '') { - $name = $replyto; - } - - if (strpos($name, '"') !== 0) - { - $name = '"'.$name.'"'; + // only use Q encoding if there are characters that would require it + if ( ! preg_match('/[\200-\377]/', $name)) + { + // add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes + $name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"'; + } + else + { + $name = $this->_prep_q_encoding($name); + } } $this->set_header('Reply-To', $name.' <'.$replyto.'>'); diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php index 31632762d..296ddb92a 100644 --- a/system/libraries/Form_validation.php +++ b/system/libraries/Form_validation.php @@ -637,21 +637,7 @@ class CI_Form_validation { // Set the message type $type = in_array('required', $rules) ? 'required' : 'isset'; - // Check if a custom message is defined - if (isset($this->_field_data[$row['field']]['errors'][$type])) - { - $line = $this->_field_data[$row['field']]['errors'][$type]; - } - elseif (isset($this->_error_messages[$type])) - { - $line = $this->_error_messages[$type]; - } - elseif (FALSE === ($line = $this->CI->lang->line('form_validation_'.$type)) - // DEPRECATED support for non-prefixed keys - && FALSE === ($line = $this->CI->lang->line($type, FALSE))) - { - $line = 'The field was not set'; - } + $line = $this->_get_error_message($type, $row['field']); // Build the error message $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label'])); @@ -820,23 +806,9 @@ class CI_Form_validation { { $line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)'; } - // Check if a custom message is defined - elseif (isset($this->_field_data[$row['field']]['errors'][$rule])) - { - $line = $this->_field_data[$row['field']]['errors'][$rule]; - } - elseif ( ! isset($this->_error_messages[$rule])) - { - if (FALSE === ($line = $this->CI->lang->line('form_validation_'.$rule)) - // DEPRECATED support for non-prefixed keys - && FALSE === ($line = $this->CI->lang->line($rule, FALSE))) - { - $line = $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')'; - } - } else { - $line = $this->_error_messages[$rule]; + $line = $this->_get_error_message($rule, $row['field']); } // Is the parameter we are inserting into the error message the name @@ -864,6 +836,40 @@ class CI_Form_validation { // -------------------------------------------------------------------- + /** + * Get the error message for the rule + * + * @param string $rule The rule name + * @param string $field The field name + * @return string + */ + protected function _get_error_message($rule, $field) + { + // check if a custom message is defined through validation config row. + if (isset($this->_field_data[$field]['errors'][$rule])) + { + return $this->_field_data[$field]['errors'][$rule]; + } + // check if a custom message has been set using the set_message() function + elseif (isset($this->_error_messages[$rule])) + { + return $this->_error_messages[$rule]; + } + elseif (FALSE !== ($line = $this->CI->lang->line('form_validation_'.$rule))) + { + return $line; + } + // DEPRECATED support for non-prefixed keys, lang file again + elseif (FALSE !== ($line = $this->CI->lang->line($rule, FALSE))) + { + return $line; + } + + return $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')'; + } + + // -------------------------------------------------------------------- + /** * Translate a field name * @@ -1214,6 +1220,14 @@ class CI_Form_validation { $str = $matches[2]; } + // PHP 7 accepts IPv6 addresses within square brackets as hostnames, + // but it appears that the PR that came in with https://bugs.php.net/bug.php?id=68039 + // was never merged into a PHP 5 branch ... https://3v4l.org/8PsSN + if (preg_match('/^\[([^\]]+)\]/', $str, $matches) && ! is_php('7') && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE) + { + $str = 'ipv6.host'.substr($str, strlen($matches[1]) + 2); + } + $str = 'http://'.$str; // There's a bug affecting PHP 5.2.13, 5.3.2 that considers the diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index 9a0db9664..44f848fe0 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -497,7 +497,7 @@ class CI_Pagination { { $this->cur_page = $this->CI->input->get($this->query_string_segment); } - else if (!$this->cur_page) + elseif (empty($this->cur_page)) { // Default to the last segment number if one hasn't been defined. if ($this->uri_segment === 0) @@ -512,16 +512,18 @@ class CI_Pagination { { $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page); } - } else { - $this->cur_page = (string) $this->cur_page; - } + } + else + { + $this->cur_page = (string) $this->cur_page; + } // If something isn't quite right, back to the default base page. if ( ! ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0)) { $this->cur_page = $base_page; } - elseif (empty($this->cur_page)) + else { // Make sure we're using integers for comparisons later. $this->cur_page = (int) $this->cur_page; diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index cc7641436..cf455d3da 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -314,12 +314,14 @@ class CI_Profiler { foreach ($_GET as $key => $val) { - is_int($key) OR $key = "'".$key."'"; + is_int($key) OR $key = "'".htmlspecialchars($key, ENT_QUOTES, config_item('charset'))."'"; + $val = (is_array($val) OR is_object($val)) + ? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))
+					: htmlspecialchars($val, ENT_QUOTES, config_item('charset'));
 
 				$output .= '$_GET['
 					.$key.']   '
-					.((is_array($val) OR is_object($val)) ? '
'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'
' : htmlspecialchars(stripslashes($val))) - ."\n"; + .$val."\n"; } $output .= "\n"; @@ -352,36 +354,26 @@ class CI_Profiler { foreach ($_POST as $key => $val) { - is_int($key) OR $key = "'".$key."'"; + is_int($key) OR $key = "'".htmlspecialchars($key, ENT_QUOTES, config_item('charset'))."'"; + $val = (is_array($val) OR is_object($val)) + ? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))
+					: htmlspecialchars($val, ENT_QUOTES, config_item('charset'));
 
 				$output .= '$_POST['
-					.$key.']   ';
-
-				if (is_array($val) OR is_object($val))
-				{
-					$output .= '
'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'
'; - } - else - { - $output .= htmlspecialchars(stripslashes($val)); - } - - $output .= "\n"; + .$key.']   ' + .$val."\n"; } foreach ($_FILES as $key => $val) { - is_int($key) OR $key = "'".$key."'"; + is_int($key) OR $key = "'".htmlspecialchars($key, ENT_QUOTES, config_item('charset'))."'"; + $val = (is_array($val) OR is_object($val)) + ? '
'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))
+					: htmlspecialchars($val, ENT_QUOTES, config_item('charset'));
 
 				$output .= '$_FILES['
-					.$key.']   ';
-
-				if (is_array($val) OR is_object($val))
-				{
-					$output .= '
'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'
'; - } - - $output .= "\n"; + .$key.']   ' + .$val."\n"; } $output .= "\n"; @@ -465,7 +457,7 @@ class CI_Profiler { foreach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR', 'HTTP_DNT') as $header) { - $val = isset($_SERVER[$header]) ? $_SERVER[$header] : ''; + $val = isset($_SERVER[$header]) ? htmlspecialchars($_SERVER[$header], ENT_QUOTES, config_item('charset')) : ''; $output .= '' .$header.'  '.$val."\n"; } diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index b93c00c15..77c56ae70 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -231,7 +231,7 @@ class CI_Session { } } - if ( ! class_exists($prefix.$class) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php')) + if ( ! class_exists($prefix.$class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php')) { require_once($file_path); if (class_exists($prefix.$class, FALSE)) diff --git a/system/libraries/Session/Session_driver.php b/system/libraries/Session/Session_driver.php index 98fc897e3..55ddb25e0 100644 --- a/system/libraries/Session/Session_driver.php +++ b/system/libraries/Session/Session_driver.php @@ -168,4 +168,24 @@ abstract class CI_Session_driver implements SessionHandlerInterface { return TRUE; } + // ------------------------------------------------------------------------ + + /** + * Fail + * + * Drivers other than the 'files' one don't (need to) use the + * session.save_path INI setting, but that leads to confusing + * error messages emitted by PHP when open() or write() fail, + * as the message contains session.save_path ... + * To work around the problem, the drivers will call this method + * so that the INI is set just in time for the error message to + * be properly generated. + * + * @return mixed + */ + protected function _fail() + { + ini_set('session.save_path', config_item('sess_save_path')); + return $this->_failure; + } } diff --git a/system/libraries/Session/drivers/Session_database_driver.php b/system/libraries/Session/drivers/Session_database_driver.php index 3ba9d3d36..317bd7d4d 100644 --- a/system/libraries/Session/drivers/Session_database_driver.php +++ b/system/libraries/Session/drivers/Session_database_driver.php @@ -127,7 +127,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan { if (empty($this->_db->conn_id) && ! $this->_db->db_connect()) { - return $this->_failure; + return $this->_fail(); } return $this->_success; @@ -163,7 +163,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan $this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']); } - if (($result = $this->_db->get()->row()) === NULL) + if ( ! ($result = $this->_db->get()) OR ($result = $result->row()) === NULL) { // PHP7 will reuse the same SessionHandler object after // ID regeneration, so we need to explicitly set this to @@ -210,7 +210,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return $this->_failure; + return $this->_fail(); } $this->_row_exists = FALSE; @@ -218,7 +218,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan } elseif ($this->_lock === FALSE) { - return $this->_failure; + return $this->_fail(); } if ($this->_row_exists === FALSE) @@ -237,7 +237,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return $this->_success; } - return $this->_failure; + return $this->_fail(); } $this->_db->where('id', $session_id); @@ -260,7 +260,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return $this->_success; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -275,7 +275,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan public function close() { return ($this->_lock && ! $this->_release_lock()) - ? $this->_failure + ? $this->_fail() : $this->_success; } @@ -304,7 +304,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan if ( ! $this->_db->delete($this->_config['save_path'])) { - return $this->_failure; + return $this->_fail(); } } @@ -314,7 +314,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return $this->_success; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -334,7 +334,7 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return ($this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime))) ? $this->_success - : $this->_failure; + : $this->_fail(); } // ------------------------------------------------------------------------ @@ -414,5 +414,4 @@ class CI_Session_database_driver extends CI_Session_driver implements SessionHan return parent::_release_lock(); } - } \ No newline at end of file diff --git a/system/libraries/Session/drivers/Session_memcached_driver.php b/system/libraries/Session/drivers/Session_memcached_driver.php index d017dfb2f..88eb4b3a6 100644 --- a/system/libraries/Session/drivers/Session_memcached_driver.php +++ b/system/libraries/Session/drivers/Session_memcached_driver.php @@ -117,7 +117,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { $this->_memcached = NULL; log_message('error', 'Session: Invalid Memcached save path format: '.$this->_config['save_path']); - return $this->_failure; + return $this->_fail(); } foreach ($matches as $match) @@ -142,7 +142,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if (empty($server_list)) { log_message('error', 'Session: Memcached server pool is empty.'); - return $this->_failure; + return $this->_fail(); } return $this->_success; @@ -170,7 +170,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $session_data; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -188,14 +188,14 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { if ( ! isset($this->_memcached)) { - return $this->_failure; + return $this->_fail(); } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return $this->_failure; + return $this->_fail(); } $this->_fingerprint = md5(''); @@ -204,24 +204,33 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if (isset($this->_lock_key)) { + $key = $this->_key_prefix.$session_id; + $this->_memcached->replace($this->_lock_key, time(), 300); if ($this->_fingerprint !== ($fingerprint = md5($session_data))) { - if ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration'])) + if ( + $this->_memcached->replace($key, $session_data, $this->_config['expiration']) + OR ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND && $this->_memcached->set($key, $session_data, $this->_config['expiration'])) + ) { $this->_fingerprint = $fingerprint; return $this->_success; } - return $this->_failure; + return $this->_fail(); } - return $this->_memcached->touch($this->_key_prefix.$session_id, $this->_config['expiration']) - ? $this->_success - : $this->_failure; + if ( + $this->_memcached->touch($key, $this->_config['expiration']) + OR ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND && $this->_memcached->set($key, $session_data, $this->_config['expiration'])) + ) + { + return $this->_success; + } } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -237,17 +246,17 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa { if (isset($this->_memcached)) { - isset($this->_lock_key) && $this->_memcached->delete($this->_lock_key); + $this->_release_lock(); if ( ! $this->_memcached->quit()) { - return $this->_failure; + return $this->_fail(); } $this->_memcached = NULL; return $this->_success; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -269,7 +278,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return $this->_success; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -305,9 +314,12 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa // correct session ID. if ($this->_lock_key === $this->_key_prefix.$session_id.':lock') { - return ($this->_memcached->replace($this->_lock_key, time(), 300)) - ? $this->_success - : $this->_failure; + if ( ! $this->_memcached->replace($this->_lock_key, time(), 300)) + { + return ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND) + ? $this->_memcached->set($this->_lock_key, time(), 300) + : FALSE; + } } // 30 attempts to obtain a lock, in case another request already has it @@ -324,7 +336,7 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if ( ! $this->_memcached->set($lock_key, time(), 300)) { log_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id); - return $this->_failure; + return FALSE; } $this->_lock_key = $lock_key; @@ -335,11 +347,11 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa if ($attempt === 30) { log_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.'); - return $this->_failure; + return FALSE; } $this->_lock = TRUE; - return $this->_success; + return TRUE; } // ------------------------------------------------------------------------ @@ -367,5 +379,4 @@ class CI_Session_memcached_driver extends CI_Session_driver implements SessionHa return TRUE; } - -} +} \ No newline at end of file diff --git a/system/libraries/Session/drivers/Session_redis_driver.php b/system/libraries/Session/drivers/Session_redis_driver.php index 46b8fa1c2..e4e09fe0d 100644 --- a/system/libraries/Session/drivers/Session_redis_driver.php +++ b/system/libraries/Session/drivers/Session_redis_driver.php @@ -69,6 +69,13 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle */ protected $_lock_key; + /** + * Key exists flag + * + * @var bool + */ + protected $_key_exists = FALSE; + // ------------------------------------------------------------------------ /** @@ -124,7 +131,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if (empty($this->_config['save_path'])) { - return $this->_failure; + return $this->_fail(); } $redis = new Redis(); @@ -146,7 +153,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle return $this->_success; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -166,12 +173,17 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle // Needed by write() to detect session_regenerate_id() calls $this->_session_id = $session_id; - $session_data = (string) $this->_redis->get($this->_key_prefix.$session_id); + $session_data = $this->_redis->get($this->_key_prefix.$session_id); + + is_string($session_data) + ? $this->_key_exists = TRUE + : $session_data = ''; + $this->_fingerprint = md5($session_data); return $session_data; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -189,40 +201,41 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle { if ( ! isset($this->_redis)) { - return $this->_failure; + return $this->_fail(); } // Was the ID regenerated? elseif ($session_id !== $this->_session_id) { if ( ! $this->_release_lock() OR ! $this->_get_lock($session_id)) { - return $this->_failure; + return $this->_fail(); } - $this->_fingerprint = md5(''); + $this->_key_exists = FALSE; $this->_session_id = $session_id; } if (isset($this->_lock_key)) { $this->_redis->setTimeout($this->_lock_key, 300); - if ($this->_fingerprint !== ($fingerprint = md5($session_data))) + if ($this->_fingerprint !== ($fingerprint = md5($session_data)) OR $this->_key_exists === FALSE) { if ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration'])) { $this->_fingerprint = $fingerprint; + $this->_key_exists = TRUE; return $this->_success; } - return $this->_failure; + return $this->_fail(); } return ($this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration'])) ? $this->_success - : $this->_failure; + : $this->_fail(); } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ @@ -241,10 +254,10 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle try { if ($this->_redis->ping() === '+PONG') { - isset($this->_lock_key) && $this->_redis->delete($this->_lock_key); + $this->_release_lock(); if ($this->_redis->close() === $this->_failure) { - return $this->_failure; + return $this->_fail(); } } } @@ -283,7 +296,7 @@ class CI_Session_redis_driver extends CI_Session_driver implements SessionHandle return $this->_success; } - return $this->_failure; + return $this->_fail(); } // ------------------------------------------------------------------------ diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index 15caebebe..f2418378b 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -526,6 +526,12 @@ class CI_Upload { $this->file_name = preg_replace('/\s+/', '_', $this->file_name); } + if ($this->file_ext_tolower && ($ext_length = strlen($this->file_ext))) + { + // file_ext was previously lower-cased by a get_extension() call + $this->file_name = substr($this->file_name, 0, -$ext_length).$this->file_ext; + } + /* * Validate the file name * This function appends an number onto the end of From 6208569c7e58838ee4e269a5780e30d3ac464ba8 Mon Sep 17 00:00:00 2001 From: Aaron Gong Date: Sun, 13 Mar 2016 22:04:39 +0800 Subject: [PATCH 6/7] Fix for issue 160 https://github.com/jekkos/opensourcepos/issues/160 I try to interfere as little as possible --- application/helpers/table_helper.php | 4 ++-- application/views/sales/manage.php | 10 +++++----- css/ospos_print.css | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/application/helpers/table_helper.php b/application/helpers/table_helper.php index b20adba85..743e7f0d4 100644 --- a/application/helpers/table_helper.php +++ b/application/helpers/table_helper.php @@ -67,7 +67,7 @@ function get_sales_manage_sale_data_row($sale, $controller) $width = $controller->get_form_width(); $table_data_row=''; - $table_data_row.=''; + $table_data_row.=''; $table_data_row.=''.'POS ' . $sale['sale_id'] . ''; $table_data_row.=''.date( $CI->config->item('dateformat') . ' ' . $CI->config->item('timeformat'), strtotime($sale['sale_time']) ).''; $table_data_row.=''.character_limiter( $sale['customer_name'], 25).''; @@ -76,7 +76,7 @@ function get_sales_manage_sale_data_row($sale, $controller) $table_data_row.=''.to_currency( $sale['change_due'] ).''; $table_data_row.=''.$sale['payment_type'].''; $table_data_row.=''.$sale['invoice_number'].''; - $table_data_row.=''; + $table_data_row.=''; $table_data_row.=anchor($controller_name."/edit/" . $sale['sale_id'] . "/width:$width", $CI->lang->line('common_edit'),array('class'=>'thickbox','title'=>$CI->lang->line($controller_name.'_update'))); $table_data_row.='    '; $table_data_row.='' . $CI->lang->line('sales_show_receipt') . ''; diff --git a/application/views/sales/manage.php b/application/views/sales/manage.php index 77e03e022..439e95e03 100755 --- a/application/views/sales/manage.php +++ b/application/views/sales/manage.php @@ -170,17 +170,17 @@ function init_table_sorting()
lang->line('common_list_of').' '.$this->lang->line('sales_receipt_number'); ?>
-
+ 'search_form')); ?> -
+ -
+