diff --git a/admin-dev/themes/default/template/footer.tpl b/admin-dev/themes/default/template/footer.tpl index 8caf2c64a..66fefae89 100644 --- a/admin-dev/themes/default/template/footer.tpl +++ b/admin-dev/themes/default/template/footer.tpl @@ -39,7 +39,8 @@ {/if} | {l s='Contact'} | {l s='Bug Tracker'} - | {l s='Forum'} + | {l s='Forum'} + | {l s='Addons'} diff --git a/classes/Employee.php b/classes/Employee.php index 78c0dac5a..3f390d7ca 100644 --- a/classes/Employee.php +++ b/classes/Employee.php @@ -249,7 +249,7 @@ class EmployeeCore extends ObjectModel /* Employee is valid only if it can be load and if cookie password is the same as database one */ Cache::store('isLoggedBack'.$this->id, ( $this->id && Validate::isUnsignedId($this->id) && Employee::checkPassword($this->id, Context::getContext()->cookie->passwd) - && (!isset($this->remote_addr) || $this->remote_addr == ip2long(Tools::getRemoteAddr()) || !Configuration::get('PS_COOKIE_CHECKIP')) + && (!isset(Context::getContext()->cookie->remote_addr) || Context::getContext()->cookie->remote_addr == ip2long(Tools::getRemoteAddr()) || !Configuration::get('PS_COOKIE_CHECKIP')) )); } return Cache::retrieve('isLoggedBack'.$this->id); @@ -261,7 +261,10 @@ class EmployeeCore extends ObjectModel public function logout() { if (isset(Context::getContext()->cookie)) + { Context::getContext()->cookie->logout(); + Context::getContext()->cookie->write(); + } $this->id = null; } diff --git a/classes/Product.php b/classes/Product.php index d2d49913e..404dfc4ab 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -4493,7 +4493,7 @@ class ProductCore extends ObjectModel return true; } - /* + /** * Webservice getter : get virtual field default combination * diff --git a/classes/ProductSale.php b/classes/ProductSale.php index cc1922ef0..2f8166a4d 100644 --- a/classes/ProductSale.php +++ b/classes/ProductSale.php @@ -66,7 +66,10 @@ class ProductSaleCore if ($page_number < 0) $page_number = 0; if ($nb_products < 1) $nb_products = 10; $final_order_by = $order_by; + $order_table = ''; if (is_null($order_by) || $order_by == 'position' || $order_by == 'price') $order_by = 'sales'; + if ($order_by == 'date_add' || $order_by == 'date_upd') + $order_table = 'product_shop'; if (is_null($order_way) || $order_by == 'sales') $order_way = 'DESC'; $groups = FrontController::getCurrentCustomerGroups(); $sql_groups = (count($groups) ? 'IN ('.implode(',', $groups).')' : '= 1'); @@ -108,7 +111,7 @@ class ProductSaleCore WHERE cg.`id_group` '.$sql_groups.' ) GROUP BY product_shop.id_product - ORDER BY '.$prefix.'`'.pSQL($order_by).'` '.pSQL($order_way).' + ORDER BY '.(!empty($order_table) ? '`'.pSQL($order_table).'`.' : '').'`'.pSQL($order_by).'` '.pSQL($order_way).' LIMIT '.(int)($page_number * $nb_products).', '.(int)$nb_products; $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql); diff --git a/classes/Search.php b/classes/Search.php index eb3f0985e..32025f14b 100644 --- a/classes/Search.php +++ b/classes/Search.php @@ -93,8 +93,12 @@ define('PREG_CLASS_CJK', '\x{3041}-\x{30ff}\x{31f0}-\x{31ff}\x{3400}-\x{4db5}\x{ class SearchCore { - public static function sanitize($string, $id_lang, $indexation = false) + public static function sanitize($string, $id_lang, $indexation = false, $iso_code = false) { + $string = trim($string); + if (empty($string)) + return ''; + $string = Tools::strtolower(strip_tags($string)); $string = html_entity_decode($string, ENT_NOQUOTES, 'utf-8'); @@ -138,14 +142,34 @@ class SearchCore if ($indexation) { - $minWordLen = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); - if ($minWordLen > 1) + // If the language is constituted with symbol and there is no "words", then split every chars + if (in_array($iso_code, array('zh', 'tw', 'ja')) && function_exists('mb_strlen')) { - $minWordLen -= 1; - $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}(?=\s)/Su', ' ', $string); - $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}(?=\s)/Su', '', $string); - $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}$/Su', '', $string); - $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + // Cut symbols from letters + $symbols = ''; + $letters = ''; + foreach (explode(' ', $string) as $mb_word) + if (strlen(Tools::replaceAccentedChars($mb_word)) == mb_strlen(Tools::replaceAccentedChars($mb_word))) + $letters .= $mb_word.' '; + else + $symbols .= $mb_word.' '; + + if (preg_match_all('/./u', $symbols, $matches)) + $symbols = implode(' ', $matches[0]); + + $string = $letters.$symbols; + } + else + { + $minWordLen = (int)Configuration::get('PS_SEARCH_MINWORDLEN'); + if ($minWordLen > 1) + { + $minWordLen -= 1; + $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}(?=\s)/Su', ' ', $string); + $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}(?=\s)/Su', '', $string); + $string = preg_replace('/(?<=\s)[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + $string = preg_replace('/^[^\s]{1,'.$minWordLen.'}$/Su', '', $string); + } } } @@ -175,7 +199,7 @@ class SearchCore $intersect_array = array(); $score_array = array(); - $words = explode(' ', Search::sanitize($expr, $id_lang)); + $words = explode(' ', Search::sanitize($expr, $id_lang, false, $context->language->iso_code)); foreach ($words as $key => $word) if (!empty($word) && strlen($word) >= (int)Configuration::get('PS_SEARCH_MINWORDLEN')) @@ -383,7 +407,7 @@ class SearchCore return Db::getInstance()->executeS(' SELECT p.id_product, pl.id_lang, pl.id_shop, pl.name pname, p.reference, p.ean13, p.upc, - pl.description_short, pl.description, cl.name cname, m.name mname + pl.description_short, pl.description, cl.name cname, m.name mname, l.iso_code FROM '._DB_PREFIX_.'product p LEFT JOIN '._DB_PREFIX_.'product_lang pl ON p.id_product = pl.id_product @@ -392,6 +416,8 @@ class SearchCore ON (cl.id_category = product_shop.id_category_default AND pl.id_lang = cl.id_lang AND cl.id_shop = product_shop.id_shop) LEFT JOIN '._DB_PREFIX_.'manufacturer m ON m.id_manufacturer = p.id_manufacturer + LEFT JOIN '._DB_PREFIX_.'lang l + ON l.id_lang = pl.id_lang WHERE product_shop.indexed = 0 AND product_shop.visibility IN ("both", "search") '.($id_product ? 'AND p.id_product = '.(int)$id_product : '').' @@ -482,9 +508,9 @@ class SearchCore // Data must be cleaned of html, bad characters, spaces and anything, then if the resulting words are long enough, they're added to the array $product_array = array(); foreach ($product as $key => $value) - if (strncmp($key, 'id_', 3)) + if (strncmp($key, 'id_', 3) && isset($weight_array[$key])) { - $words = explode(' ', Search::sanitize($value, (int)$product['id_lang'], true)); + $words = explode(' ', Search::sanitize($value, (int)$product['id_lang'], true, $product['iso_code'])); foreach ($words as $word) if (!empty($word)) { diff --git a/classes/controller/AdminController.php b/classes/controller/AdminController.php index e36804246..21abf5180 100644 --- a/classes/controller/AdminController.php +++ b/classes/controller/AdminController.php @@ -1813,7 +1813,11 @@ class AdminControllerCore extends Controller $this->context->employee->logout(); if ($this->controller_name != 'AdminLogin' && (!isset($this->context->employee) || !$this->context->employee->isLoggedBack())) + { + if (isset($this->context->employee)) + $this->context->employee->logout(); Tools::redirectAdmin($this->context->link->getAdminLink('AdminLogin').((!isset($_GET['logout']) && $this->controller_name != 'AdminNotFound') ? '&redirect='.$this->controller_name : '')); + } // Set current index $current_index = 'index.php'.(($controller = Tools::getValue('controller')) ? '?controller='.$controller : ''); diff --git a/classes/controller/FrontController.php b/classes/controller/FrontController.php index 3117d655f..c5ce065ad 100755 --- a/classes/controller/FrontController.php +++ b/classes/controller/FrontController.php @@ -114,21 +114,18 @@ class FrontControllerCore extends Controller $css_files = $this->css_files; $js_files = $this->js_files; - if ($this->ssl && !Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) - { + // If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol + if (Configuration::get('PS_SSL_ENABLED') && ($_SERVER['REQUEST_METHOD'] != 'POST') && $this->ssl != Tools::usingSecureMode()) + { header('HTTP/1.1 301 Moved Permanently'); header('Cache-Control: no-cache'); - header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); + if ($this->ssl) + header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']); + else + header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']); exit(); } - elseif (Configuration::get('PS_SSL_ENABLED') && Tools::usingSecureMode() && !($this->ssl)) - { - header('HTTP/1.1 301 Moved Permanently'); - header('Cache-Control: no-cache'); - header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']); - exit(); - } - + if ($this->ajax) { $this->display_header = false; diff --git a/classes/module/Module.php b/classes/module/Module.php index b323204b6..8fcbddd8c 100644 --- a/classes/module/Module.php +++ b/classes/module/Module.php @@ -292,15 +292,17 @@ abstract class ModuleCore else { if (!$upgrade_detail['number_upgraded']) - $this->_errors[] = $this->l('None upgrades have been applied'); + $this->_errors[] = $this->l('No upgrade has been applied'); else { - $this->_errors[] = $this->l('Upgraded from: ').$upgrade_detail['upgraded_from'].$this->l(' to '). - $upgrade_detail['upgraded_to']; + $this->_errors[] = sprintf($this->l('Upgraded from: %S to %s'), $upgrade_detail['upgraded_from'], $upgrade_detail['upgraded_to']); $this->_errors[] = $upgrade_detail['number_upgrade_left'].' '.$this->l('upgrade left'); } - $this->_errors[] = $this->l('To prevent any problem, this module has been turned off'); + if ($upgrade_detail['duplicate']) + $this->_errors[] = sprintf(Tools::displayError('Module %s cannot be upgraded this time: please refresh this page to update it.'), $this->name); + else + $this->_errors[] = $this->l('To prevent any problem, this module has been turned off'); } } } @@ -348,19 +350,21 @@ abstract class ModuleCore $upgrade = &self::$modules_cache[$this->name]['upgrade']; foreach ($upgrade['upgrade_file_left'] as $num => $file_detail) { - // Default variable required in the included upgrade file need to be set by default there: - // upgrade_version, success_upgrade - $upgrade_result = false; + if (function_exists($file_detail['upgrade_function'])) + { + $upgrade['success'] = false; + $upgrade['duplicate'] = true; + break; + } include($file_detail['file']); // Call the upgrade function if defined + $upgrade['success'] = false; if (function_exists($file_detail['upgrade_function'])) - $upgrade_result = $file_detail['upgrade_function']($this); - - $upgrade['success'] = $upgrade_result; + $upgrade['success'] = $file_detail['upgrade_function']($this); // Set detail when an upgrade succeed or failed - if ($upgrade_result) + if ($upgrade['success']) { $upgrade['number_upgraded'] += 1; $upgrade['upgraded_to'] = $file_detail['version']; @@ -378,6 +382,7 @@ abstract class ModuleCore } $upgrade['number_upgrade_left'] = count($upgrade['upgrade_file_left']); + // Update module version in DB with the last succeed upgrade if ($upgrade['upgraded_to']) Module::upgradeModuleVersion($this->name, $upgrade['upgraded_to']); @@ -396,9 +401,9 @@ abstract class ModuleCore public static function upgradeModuleVersion($name, $version) { return Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'module` m - SET m.version = \''.bqSQL($version).'\' - WHERE m.name = \''.bqSQL($name).'\''); + UPDATE `'._DB_PREFIX_.'module` m + SET m.version = \''.bqSQL($version).'\' + WHERE m.name = \''.bqSQL($name).'\''); } /** diff --git a/classes/pdf/HTMLTemplateOrderSlip.php b/classes/pdf/HTMLTemplateOrderSlip.php index 95d9b9f1f..e84725f57 100644 --- a/classes/pdf/HTMLTemplateOrderSlip.php +++ b/classes/pdf/HTMLTemplateOrderSlip.php @@ -45,7 +45,7 @@ class HTMLTemplateOrderSlipCore extends HTMLTemplateInvoice $this->smarty = $smarty; // header informations - $this->date = Tools::displayDate($this->order->invoice_date, (int)$this->order->id_lang); + $this->date = Tools::displayDate($this->order_slip->date_add, (int)$this->order->id_lang); $this->title = HTMLTemplateOrderSlip::l('Slip #').Configuration::get('PS_CREDIT_SLIP_PREFIX', Context::getContext()->language->id).sprintf('%06d', (int)$this->order_slip->id); // footer informations diff --git a/controllers/admin/AdminCarrierWizardController.php b/controllers/admin/AdminCarrierWizardController.php index 2c85f8c40..c5a331648 100644 --- a/controllers/admin/AdminCarrierWizardController.php +++ b/controllers/admin/AdminCarrierWizardController.php @@ -716,7 +716,8 @@ class AdminCarrierWizardControllerCore extends AdminController if ($logo && !empty($logo['tmp_name']) && $logo['tmp_name'] != 'none' && (!isset($logo['error']) || !$logo['error']) && preg_match('/\.(jpe?g|gif|png)$/', $logo['name']) - && is_uploaded_file($logo['tmp_name'])) + && is_uploaded_file($logo['tmp_name']) + && ImageManager::isRealImage($logo['tmp_name'])) { $file = $logo['tmp_name']; do $tmp_name = uniqid().'.jpg'; diff --git a/controllers/admin/AdminHomeController.php b/controllers/admin/AdminHomeController.php index 6922490a4..45797273e 100644 --- a/controllers/admin/AdminHomeController.php +++ b/controllers/admin/AdminHomeController.php @@ -499,7 +499,7 @@ class AdminHomeControllerCore extends AdminController // DISCOVER PRESTASHOP $result['discover_prestashop'] = '