diff --git a/admin-dev/themes/template/products/input_text_lang.tpl b/admin-dev/themes/template/products/input_text_lang.tpl index 62ec5c0f5..67182a2eb 100644 --- a/admin-dev/themes/template/products/input_text_lang.tpl +++ b/admin-dev/themes/template/products/input_text_lang.tpl @@ -30,7 +30,8 @@ + onchange="updateFriendlyURL();" + onkeyup="if (isArrowKey(event)) return ;updateFriendlyURL();"/> {/foreach} diff --git a/classes/Dispatcher.php b/classes/Dispatcher.php index 1dfd94334..8cde151fb 100644 --- a/classes/Dispatcher.php +++ b/classes/Dispatcher.php @@ -44,16 +44,16 @@ class DispatcherCore 'rule' => '{category:/}{id}-{rewrite}{-:ean13}.html', 'keywords' => array( 'id' => array('regexp' => '[0-9]+', 'param' => 'id_product'), - 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), - 'ean13' => array('regexp' => '[a-zA-Z0-9-]*'), - 'category' => array('regexp' => '[a-zA-Z0-9-]*'), - 'reference' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), - 'manufacturer' => array('regexp' => '[a-zA-Z0-9-]*'), - 'supplier' => array('regexp' => '[a-zA-Z0-9-]*'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'ean13' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'category' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'reference' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'manufacturer' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'supplier' => array('regexp' => '[a-zA-Z0-9-\pL]*'), 'price' => array('regexp' => '[0-9\.,]*'), - 'tags' => array('regexp' => '[a-zA-Z0-9-]*'), + 'tags' => array('regexp' => '[a-zA-Z0-9-\pL]*'), ), ), 'category_rule' => array( @@ -61,9 +61,9 @@ class DispatcherCore 'rule' => '{id}-{rewrite}', 'keywords' => array( 'id' => array('regexp' => '[0-9]+', 'param' => 'id_category'), - 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-\pL]*'), ), ), 'supplier_rule' => array( @@ -71,9 +71,9 @@ class DispatcherCore 'rule' => '{id}__{rewrite}', 'keywords' => array( 'id' => array('regexp' => '[0-9]+', 'param' => 'id_supplier'), - 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-\pL]*'), ), ), 'manufacturer_rule' => array( @@ -81,9 +81,9 @@ class DispatcherCore 'rule' => '{id}_{rewrite}', 'keywords' => array( 'id' => array('regexp' => '[0-9]+', 'param' => 'id_manufacturer'), - 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-\pL]*'), ), ), 'cms_rule' => array( @@ -91,9 +91,9 @@ class DispatcherCore 'rule' => 'content/{id}-{rewrite}', 'keywords' => array( 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms'), - 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-\pL]*'), ), ), 'cms_category_rule' => array( @@ -101,9 +101,9 @@ class DispatcherCore 'rule' => 'content/category/{id}-{rewrite}', 'keywords' => array( 'id' => array('regexp' => '[0-9]+', 'param' => 'id_cms_category'), - 'rewrite' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-]*'), - 'meta_title' => array('regexp' => '[a-zA-Z0-9-]*'), + 'rewrite' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_keywords' => array('regexp' => '[a-zA-Z0-9-\pL]*'), + 'meta_title' => array('regexp' => '[a-zA-Z0-9-\pL]*'), ), ), 'module' => array( @@ -183,6 +183,7 @@ class DispatcherCore $this->request_uri = $_SERVER['REQUEST_URI']; else if (isset($_SERVER['HTTP_X_REWRITE_URL'])) $this->request_uri = $_SERVER['HTTP_X_REWRITE_URL']; + $this->request_uri = rawurldecode($this->request_uri); } /** @@ -227,7 +228,10 @@ class DispatcherCore if (!Validate::isTabName($name)) return false; - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('SELECT id_tab, class_name, module FROM `'._DB_PREFIX_.'tab` WHERE LOWER(class_name) = \''.pSQL($name).'\''); + $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + SELECT id_tab, class_name, module + FROM `'._DB_PREFIX_.'tab` + WHERE LOWER(class_name) = \''.pSQL($name).'\''); return $row; } @@ -301,7 +305,7 @@ class DispatcherCore if (!empty($controller_row['module'])) $controller_type = self::includeModuleClass($controller_row['module'], $controller_class); // If it is an AdminTab, include it - elseif (file_exists(_PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php')) + else if (file_exists(_PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php')) { include(_PS_ADMIN_DIR_.'/tabs/'.$controller_class.'.php'); $controller_type = 'tab'; @@ -310,8 +314,8 @@ class DispatcherCore if (isset($controller_type) && $controller_type == 'tab') { require_once(_PS_ADMIN_DIR_.'/functions.php'); - $ajaxMode = !empty($_REQUEST['ajaxMode']); - runAdminTab($controller_class, $ajaxMode); + $ajax_mode = !empty($_REQUEST['ajaxMode']); + runAdminTab($controller_class, $ajax_mode); return; } @@ -399,7 +403,7 @@ class DispatcherCore $keywords = $transform_keywords; } - $regexp = '#^/'.$regexp.'#'; + $regexp = '#^/'.$regexp.'#u'; $this->routes[$route_id] = array( 'rule' => $rule, 'regexp' => $regexp, @@ -488,9 +492,9 @@ class DispatcherCore $replace = $route['keywords'][$key]['prepend'].$params[$key].$route['keywords'][$key]['append']; else $replace = ''; - $url = preg_replace('#\{([^{}]+:)?'.$key.'(:[^{}])?\}#', $replace, $url); + $url = preg_replace('#(*UTF8)\{([^{}]+:)?'.$key.'(:[^{}])?\}#', $replace, $url); } - $url = preg_replace('#\{([^{}]+:)?[a-z0-9_]+?(:[^{}])?\}#', '', $url); + $url = preg_replace('#(*UTF8)\{([^{}]+:)?[a-z0-9_]+?(:[^{}])?\}#', '', $url); } // Build a classic url index.php?controller=foo&... else diff --git a/classes/Tools.php b/classes/Tools.php index 5b7ad5f4e..8bef1f23b 100644 --- a/classes/Tools.php +++ b/classes/Tools.php @@ -1039,7 +1039,7 @@ class ToolsCore $str = self::replaceAccentedChars($str); // Remove all non-whitelist chars. - $str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]-]/','', $str); + $str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]-\pL]/u','', $str); $str = preg_replace('/[\s\'\:\/\[\]-]+/',' ', $str); $str = preg_replace('/[ ]/','-', $str); $str = preg_replace('/[\/]/','-', $str); @@ -1556,8 +1556,8 @@ class ToolsCore fwrite($write_fd, "# Images\n"); if (Configuration::get('PS_LEGACY_IMAGES')) { - fwrite($write_fd, 'RewriteRule ^([a-z0-9]+)\-([a-z0-9]+)(\-[_a-zA-Z0-9-]*)/[_a-zA-Z0-9-]*\.jpg$ '._PS_PROD_IMG_.'$1-$2$3.jpg [L]'."\n"); - fwrite($write_fd, 'RewriteRule ^([0-9]+)\-([0-9]+)/[_a-zA-Z0-9-]*\.jpg$ '._PS_PROD_IMG_.'$1-$2.jpg [L]'."\n"); + fwrite($write_fd, 'RewriteRule (*UTF8)^([a-z0-9]+)\-([a-z0-9]+)(\-[_a-zA-Z0-9-]*)/[_a-zA-Z0-9-\pL]*\.jpg$ '._PS_PROD_IMG_.'$1-$2$3.jpg [L]'."\n"); + fwrite($write_fd, 'RewriteRule (*UTF8)^([0-9]+)\-([0-9]+)/[_a-zA-Z0-9-\pL]*\.jpg$ '._PS_PROD_IMG_.'$1-$2.jpg [L]'."\n"); } // Rewrite product images < 100 millions @@ -1570,10 +1570,10 @@ class ToolsCore $img_name .= '$'.$j; } $img_name .= '$'.$j; - fwrite($write_fd, 'RewriteRule ^'.str_repeat('([0-9])', $i).'(\-[_a-zA-Z0-9-]*)?/[_a-zA-Z0-9-]*\.jpg$ '._PS_PROD_IMG_.$img_path.$img_name.".jpg [L]\n"); + fwrite($write_fd, 'RewriteRule (*UTF8)^'.str_repeat('([0-9])', $i).'(\-[_a-zA-Z0-9-]*)?/[_a-zA-Z0-9-\pL]*\.jpg$ '._PS_PROD_IMG_.$img_path.$img_name.".jpg [L]\n"); } - fwrite($write_fd, 'RewriteRule ^c/([0-9]+)(\-[_a-zA-Z0-9-]*)/[_a-zA-Z0-9-]*\.jpg$ img/c/$1$2.jpg [L]'."\n"); - fwrite($write_fd, 'RewriteRule ^c/([a-zA-Z-]+)/[a-zA-Z0-9-]+\.jpg$ img/c/$1.jpg [L]'."\n"); + fwrite($write_fd, 'RewriteRule (*UTF8)^c/([0-9]+)(\-[_a-zA-Z0-9-\pL]*)/[_a-zA-Z0-9-]*\.jpg$ img/c/$1$2.jpg [L]'."\n"); + fwrite($write_fd, 'RewriteRule (*UTF8)^c/([a-zA-Z-]+)/[a-zA-Z0-9-\pL]+\.jpg$ img/c/$1.jpg [L]'."\n"); } // Redirections to dispatcher diff --git a/classes/Validate.php b/classes/Validate.php index a02c98e21..487b46459 100644 --- a/classes/Validate.php +++ b/classes/Validate.php @@ -311,7 +311,7 @@ class ValidateCore */ public static function isLinkRewrite($link) { - return (boolean)preg_match('/^[_a-zA-Z0-9-]+$/', $link); + return preg_match("/^[a-zA-Z0-9\s\-\pL]+$/u", $link); } /** diff --git a/js/admin.js b/js/admin.js index b384fe6b6..a8d4d9a5d 100644 --- a/js/admin.js +++ b/js/admin.js @@ -51,7 +51,7 @@ function str2url(str,encoding,ucfirst) str = str.replace(/[\u013E\u013A]/g,'l'); str = str.replace(/[\u0155]/g,'r'); - str = str.replace(/[^a-z0-9\s\'\:\/\[\]-]/g,''); + str = str.replace(/[^a-z0-9\s\'\:\/\[\]-]\\u00A1-\\uFFFF/g,''); str = str.replace(/[\s\'\:\/\[\]-]+/g,' '); str = str.replace(/[ ]/g,'-'); str = str.replace(/[\/]/g,'-'); @@ -86,7 +86,7 @@ function strToAltImgAttr(str,encoding,ucfirst) str = str.replace(/[\u013E\u013A]/g,'l'); str = str.replace(/[\u0155]/g,'r'); - str = str.replace(/[^a-zA-Z0-9\s\'\:\/\[\]-]/g,''); + str = str.replace(/[^a-zA-Z0-9\s\'\:\/\[\]-]\\u00A1-\\uFFFF/g,''); str = str.replace(/[\s\'\:\/\[\]-]+/g,' '); if (ucfirst == 1) {