From f2a8a516aa44a7862a80e9d75c5df12fcfc2badb Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 23 Feb 2014 11:52:37 +0100 Subject: Requiert PHP 5.3.4 pour l'authentification par formulaire MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/marienfressinaud/FreshRSS/issues/432 En attendant de voir si on peut trouver une meilleure solution, si nécessaire, ou une meilleure documentation --- p/i/install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p/i/install.php') diff --git a/p/i/install.php b/p/i/install.php index 90ee0b8a9..dd38fab1f 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -837,7 +837,7 @@ function printStep2 () { - + -- cgit v1.2.3 From db120b4ed41584c7e33bfe63015f948e6230f1ab Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 23 Feb 2014 12:16:23 +0100 Subject: Test si crypt() fonctionne pour PHP 5.3.3 https://github.com/marienfressinaud/FreshRSS/issues/432 --- README.md | 2 +- app/views/configure/users.phtml | 2 +- lib/lib_rss.php | 11 +++++++++++ p/i/install.php | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'p/i/install.php') diff --git a/README.md b/README.md index 519db7e76..2b54ff9d5 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Privilégiez pour cela des demandes sur GitHub # Contrôle d’accès Il est requis pour le mode multi-utilisateur, et recommandé dans tous les cas, de limiter l’accès à votre FreshRSS. Au choix : -* En utilisant l’identification par formulaire (requiert PHP 5.3.4+ et JavaScript) +* En utilisant l’identification par formulaire (requiert JavaScript, et PHP 5.3.7+ recommandé – fonctionne avec certaines versions de PHP5.3.3+) * En utilisant l’identification par [Mozilla Persona](https://login.persona.org/about) incluse dans FreshRSS * En utilisant un contrôle d’accès HTTP défini par votre serveur Web * Voir par exemple la [documentation d’Apache sur l’authentification](http://httpd.apache.org/docs/trunk/howto/auth.html) diff --git a/app/views/configure/users.phtml b/app/views/configure/users.phtml index 18e4dd091..0677db881 100644 --- a/app/views/configure/users.phtml +++ b/app/views/configure/users.phtml @@ -52,7 +52,7 @@ - + diff --git a/lib/lib_rss.php b/lib/lib_rss.php index a13d9e951..8c6fb5543 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -233,3 +233,14 @@ function listUsers() { function httpAuthUser() { return isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : ''; } + +function cryptAvailable() { + if (version_compare(PHP_VERSION, '5.3.3', '>=')) { + try { + $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; + return $hash === @crypt('password', $hash); + } catch (Exception $e) { + } + } + return false; +} diff --git a/p/i/install.php b/p/i/install.php index dd38fab1f..720813323 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -837,7 +837,7 @@ function printStep2 () { - + -- cgit v1.2.3 From b07f9157b18bffdb28833ed1363284571be3644e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 2 Mar 2014 13:35:09 +0100 Subject: New unsafe autologin mode https://github.com/marienfressinaud/FreshRSS/issues/440 --- app/Controllers/indexController.php | 26 ++++++++++++++++++++++++++ lib/Minz/Configuration.php | 14 ++++++++++++++ p/i/install.php | 3 +++ 3 files changed, 43 insertions(+) (limited to 'p/i/install.php') diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index c83c5b630..0905e591a 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -352,6 +352,32 @@ class FreshRSS_index_Controller extends Minz_ActionController { } $this->view->_useLayout(false); Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); + } elseif (Minz_Configuration::unsafeAutologinEnabled() && isset($_GET['u']) && isset($_GET['p'])) { + Minz_Session::_param('currentUser'); + Minz_Session::_param('mail'); + Minz_Session::_param('passwordHash'); + $username = ctype_alnum($_GET['u']) ? $_GET['u'] : ''; + $passwordPlain = $_GET['p']; + Minz_Request::_param('p'); //Discard plain-text password ASAP + $_GET['p'] = ''; + if (!function_exists('password_verify')) { + include_once(LIB_PATH . '/password_compat.php'); + } + try { + $conf = new FreshRSS_Configuration($username); + $s = $conf->passwordHash; + $ok = password_verify($passwordPlain, $s); + unset($passwordPlain); + if ($ok) { + Minz_Session::_param('currentUser', $username); + Minz_Session::_param('passwordHash', $s); + } else { + Minz_Log::record('Unsafe password mismatch for user ' . $username, Minz_Log::WARNING); + } + } catch (Minz_Exception $me) { + Minz_Log::record('Unsafe login failure: ' . $me->getMessage(), Minz_Log::WARNING); + } + Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); } elseif (!Minz_Configuration::canLogIn()) { Minz_Error::error ( 403, diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index ff71d747c..324aae881 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -55,6 +55,7 @@ class Minz_Configuration { private static $allow_anonymous_refresh = false; private static $auth_type = 'none'; private static $api_enabled = false; + private static $unsafe_autologin_enabled = false; private static $db = array ( 'type' => 'mysql', @@ -135,6 +136,9 @@ class Minz_Configuration { public static function apiEnabled() { return self::$api_enabled; } + public static function unsafeAutologinEnabled() { + return self::$unsafe_autologin_enabled; + } public static function _allowAnonymous($allow = false) { self::$allow_anonymous = ((bool)$allow) && self::canLogIn(); @@ -158,6 +162,9 @@ class Minz_Configuration { public static function _enableApi($value = false) { self::$api_enabled = (bool)$value; } + public static function _enableAutologin($value = false) { + self::$unsafe_autologin_enabled = (bool)$value; + } /** * Initialise les variables de configuration @@ -188,6 +195,7 @@ class Minz_Configuration { 'allow_anonymous_refresh' => self::$allow_anonymous_refresh, 'auth_type' => self::$auth_type, 'api_enabled' => self::$api_enabled, + 'unsafe_autologin_enabled' => self::$unsafe_autologin_enabled, ), 'db' => self::$db, ); @@ -310,6 +318,12 @@ class Minz_Configuration { ($general['api_enabled'] !== 'no') ); } + if (isset ($general['unsafe_autologin_enabled'])) { + self::$unsafe_autologin_enabled = ( + ((bool)($general['unsafe_autologin_enabled'])) && + ($general['unsafe_autologin_enabled'] !== 'no') + ); + } // Base de données if (isset ($ini_array['db'])) { diff --git a/p/i/install.php b/p/i/install.php index 720813323..a7563d5ee 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -235,6 +235,9 @@ function saveStep3 () { 'default_user' => $_SESSION['default_user'], 'auth_type' => $_SESSION['auth_type'], 'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false, + 'allow_anonymous_refresh' => false, + 'unsafe_autologin_enabled' => false, + 'api_enabled' => false, ), 'db' => array( 'type' => $_SESSION['bd_type'], -- cgit v1.2.3 From c8aa451c768a3d4dfce3d19648f3c8420dedb74c Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 24 Mar 2014 20:55:18 +0100 Subject: Minz: remove url_rewriting As suggested https://github.com/marienfressinaud/FreshRSS/issues/163#issuecomment-38478669 At the same time, removes a bunch of (almost) dead code such as Minz_Router (the few remaining lines being moved to Minz_FrontController to avoid a class) Contributes to https://github.com/marienfressinaud/FreshRSS/issues/303 --- lib/Minz/ActionController.php | 6 +- lib/Minz/Configuration.php | 9 -- lib/Minz/Dispatcher.php | 16 +-- lib/Minz/FrontController.php | 43 ++++++-- lib/Minz/RouteNotFoundException.php | 16 --- lib/Minz/Router.php | 209 ------------------------------------ lib/Minz/Url.php | 13 +-- p/i/install.php | 1 - 8 files changed, 40 insertions(+), 273 deletions(-) delete mode 100644 lib/Minz/RouteNotFoundException.php delete mode 100644 lib/Minz/Router.php (limited to 'p/i/install.php') diff --git a/lib/Minz/ActionController.php b/lib/Minz/ActionController.php index 409d9611f..b47c54554 100644 --- a/lib/Minz/ActionController.php +++ b/lib/Minz/ActionController.php @@ -8,16 +8,12 @@ * La classe ActionController représente le contrôleur de l'application */ class Minz_ActionController { - protected $router; protected $view; /** * Constructeur - * @param $controller nom du controller - * @param $action nom de l'action à lancer */ - public function __construct ($router) { - $this->router = $router; + public function __construct () { $this->view = new Minz_View (); $this->view->attributeParams (); } diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index d905f6ddd..16c8eb727 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -30,7 +30,6 @@ class Minz_Configuration { * définition des variables de configuration * $salt une chaîne de caractères aléatoires (obligatoire) * $environment gère le niveau d'affichage pour log et erreurs - * $use_url_rewriting indique si on utilise l'url_rewriting * $base_url le chemin de base pour accéder à l'application * $title le nom de l'application * $language la langue par défaut de l'application @@ -43,7 +42,6 @@ class Minz_Configuration { private static $salt = ''; private static $environment = Minz_Configuration::PRODUCTION; private static $base_url = ''; - private static $use_url_rewriting = false; private static $title = ''; private static $language = 'en'; private static $default_user = ''; @@ -90,9 +88,6 @@ class Minz_Configuration { public static function baseUrl () { return self::$base_url; } - public static function useUrlRewriting () { - return self::$use_url_rewriting; - } public static function title () { return self::$title; } @@ -176,7 +171,6 @@ class Minz_Configuration { $ini_array = array( 'general' => array( 'environment' => self::environment(true), - 'use_url_rewriting' => self::$use_url_rewriting, 'salt' => self::$salt, 'base_url' => self::$base_url, 'title' => self::$title, @@ -262,9 +256,6 @@ class Minz_Configuration { if (isset ($general['base_url'])) { self::$base_url = $general['base_url']; } - if (isset ($general['use_url_rewriting'])) { - self::$use_url_rewriting = $general['use_url_rewriting']; - } if (isset ($general['title'])) { self::$title = $general['title']; diff --git a/lib/Minz/Dispatcher.php b/lib/Minz/Dispatcher.php index ca1fd1f5c..f62a92911 100644 --- a/lib/Minz/Dispatcher.php +++ b/lib/Minz/Dispatcher.php @@ -16,26 +16,18 @@ class Minz_Dispatcher { private static $instance = null; private static $needsReset; - private $router; private $controller; /** * Récupère l'instance du Dispatcher */ - public static function getInstance ($router) { + public static function getInstance () { if (self::$instance === null) { - self::$instance = new Minz_Dispatcher ($router); + self::$instance = new Minz_Dispatcher (); } return self::$instance; } - /** - * Constructeur - */ - private function __construct ($router) { - $this->router = $router; - } - /** * Lance le controller indiqué dans Request * Remplit le body de Response à partir de la Vue @@ -58,7 +50,7 @@ class Minz_Dispatcher { $this->controller->lastAction (); if (!self::$needsReset) { - echo $this->controller->view ()->build (); + $this->controller->view ()->build (); } } catch (Minz_Exception $e) { throw $e; @@ -90,7 +82,7 @@ class Minz_Dispatcher { Minz_Exception::ERROR ); } - $this->controller = new $controller_name ($this->router); + $this->controller = new $controller_name (); if (! ($this->controller instanceof Minz_ActionController)) { throw new Minz_ControllerNotActionControllerException ( diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php index 3e50db1cf..f13882801 100644 --- a/lib/Minz/FrontController.php +++ b/lib/Minz/FrontController.php @@ -24,11 +24,10 @@ */ class Minz_FrontController { protected $dispatcher; - protected $router; /** * Constructeur - * Initialise le router et le dispatcher + * Initialise le dispatcher, met à jour la Request */ public function __construct () { if (LOG_PATH === false) { @@ -40,24 +39,46 @@ class Minz_FrontController { Minz_Request::init (); - $this->router = new Minz_Router (); - $this->router->init (); - } catch (Minz_RouteNotFoundException $e) { - Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); - Minz_Error::error ( - 404, - array ('error' => array ($e->getMessage ())) + $url = $this->buildUrl(); + $url['params'] = array_merge ( + $url['params'], + Minz_Request::fetchPOST () ); + Minz_Request::forward ($url); } catch (Minz_Exception $e) { Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); $this->killApp ($e->getMessage ()); } - $this->dispatcher = Minz_Dispatcher::getInstance ($this->router); + $this->dispatcher = Minz_Dispatcher::getInstance(); + } + + /** + * Retourne un tableau représentant l'url passée par la barre d'adresses + * @return tableau représentant l'url + */ + private function buildUrl() { + $url = array (); + + $url['c'] = Minz_Request::fetchGET ( + 'c', + Minz_Request::defaultControllerName () + ); + $url['a'] = Minz_Request::fetchGET ( + 'a', + Minz_Request::defaultActionName () + ); + $url['params'] = Minz_Request::fetchGET (); + + // post-traitement + unset ($url['params']['c']); + unset ($url['params']['a']); + + return $url; } /** - * Démarre l'application (lance le dispatcher et renvoie la réponse + * Démarre l'application (lance le dispatcher et renvoie la réponse) */ public function run () { try { diff --git a/lib/Minz/RouteNotFoundException.php b/lib/Minz/RouteNotFoundException.php deleted file mode 100644 index dc4f6fbad..000000000 --- a/lib/Minz/RouteNotFoundException.php +++ /dev/null @@ -1,16 +0,0 @@ -route = $route; - - $message = 'Route `' . $route . '` not found'; - - parent::__construct ($message, $code); - } - - public function route () { - return $this->route; - } -} diff --git a/lib/Minz/Router.php b/lib/Minz/Router.php deleted file mode 100644 index 1ccd72597..000000000 --- a/lib/Minz/Router.php +++ /dev/null @@ -1,209 +0,0 @@ - -*/ - -/** - * La classe Router gère le routage de l'application - * Les routes sont définies dans APP_PATH.'/configuration/routes.php' - */ -class Minz_Router { - const ROUTES_PATH_NAME = '/configuration/routes.php'; - - private $routes = array (); - - /** - * Constructeur - * @exception FileNotExistException si ROUTES_PATH_NAME n'existe pas - * et que l'on utilise l'url rewriting - */ - public function __construct () { - if (Minz_Configuration::useUrlRewriting ()) { - if (file_exists (APP_PATH . self::ROUTES_PATH_NAME)) { - $routes = include ( - APP_PATH . self::ROUTES_PATH_NAME - ); - - if (!is_array ($routes)) { - $routes = array (); - } - - $this->routes = array_map ( - array ('Url', 'checkUrl'), - $routes - ); - } else { - throw new Minz_FileNotExistException ( - self::ROUTES_PATH_NAME, - Minz_Exception::ERROR - ); - } - } - } - - /** - * Initialise le Router en déterminant le couple Controller / Action - * Mets à jour la Request - * @exception RouteNotFoundException si l'uri n'est pas présente dans - * > la table de routage - */ - public function init () { - $url = array (); - - if (Minz_Configuration::useUrlRewriting ()) { - try { - $url = $this->buildWithRewriting (); - } catch (Minz_RouteNotFoundException $e) { - throw $e; - } - } else { - $url = $this->buildWithoutRewriting (); - } - - $url['params'] = array_merge ( - $url['params'], - Minz_Request::fetchPOST () - ); - - Minz_Request::forward ($url); - } - - /** - * Retourne un tableau représentant l'url passée par la barre d'adresses - * Ne se base PAS sur la table de routage - * @return tableau représentant l'url - */ - public function buildWithoutRewriting () { - $url = array (); - - $url['c'] = Minz_Request::fetchGET ( - 'c', - Minz_Request::defaultControllerName () - ); - $url['a'] = Minz_Request::fetchGET ( - 'a', - Minz_Request::defaultActionName () - ); - $url['params'] = Minz_Request::fetchGET (); - - // post-traitement - unset ($url['params']['c']); - unset ($url['params']['a']); - - return $url; - } - - /** - * Retourne un tableau représentant l'url passée par la barre d'adresses - * Se base sur la table de routage - * @return tableau représentant l'url - * @exception RouteNotFoundException si l'uri n'est pas présente dans - * > la table de routage - */ - public function buildWithRewriting () { - $url = array (); - $uri = Minz_Request::getURI (); - $find = false; - - foreach ($this->routes as $route) { - $regex = '*^' . $route['route'] . '$*'; - if (preg_match ($regex, $uri, $matches)) { - $url['c'] = $route['controller']; - $url['a'] = $route['action']; - $url['params'] = $this->getParams ( - $route['params'], - $matches - ); - $find = true; - break; - } - } - - if (!$find && $uri != '/') { - throw new Minz_RouteNotFoundException ( - $uri, - Minz_Exception::ERROR - ); - } - - // post-traitement - $url = Minz_Url::checkUrl ($url); - - return $url; - } - - /** - * Retourne l'uri d'une url en se basant sur la table de routage - * @param l'url sous forme de tableau - * @return l'uri formatée (string) selon une route trouvée - */ - public function printUriRewrited ($url) { - $route = $this->searchRoute ($url); - - if ($route !== false) { - return $this->replaceParams ($route, $url['params']); - } - - return ''; - } - - /** - * Recherche la route correspondante à une url - * @param l'url sous forme de tableau - * @return la route telle que spécifiée dans la table de routage, - * false si pas trouvée - */ - public function searchRoute ($url) { - foreach ($this->routes as $route) { - if ($route['controller'] == $url['c'] - && $route['action'] == $url['a']) { - // calcule la différence des tableaux de params - $params = array_flip ($route['params']); - $difference_params = array_diff_key ( - $params, - $url['params'] - ); - - // vérifie que pas de différence - // et le cas où $params est vide et pas $url['params'] - if (empty ($difference_params) - && (!empty ($params) || empty ($url['params']))) { - return $route; - } - } - } - - return false; - } - - /** - * Récupère un tableau dont - * - les clés sont définies dans $params_route - * - les valeurs sont situées dans $matches - * Le tableau $matches est décalé de +1 par rapport à $params_route - */ - private function getParams($params_route, $matches) { - $params = array (); - - for ($i = 0; $i < count ($params_route); $i++) { - $param = $params_route[$i]; - $params[$param] = $matches[$i + 1]; - } - - return $params; - } - - /** - * Remplace les éléments de la route par les valeurs contenues dans $params - */ - private function replaceParams ($route, $params_replace) { - $uri = $route['route']; - $params = array(); - foreach($route['params'] as $param) { - $uri = preg_replace('#\((.+)\)#U', $params_replace[$param], $uri, 1); - } - - return stripslashes($uri); - } -} diff --git a/lib/Minz/Url.php b/lib/Minz/Url.php index 17f1ddece..af48f00f5 100644 --- a/lib/Minz/Url.php +++ b/lib/Minz/Url.php @@ -5,8 +5,7 @@ */ class Minz_Url { /** - * Affiche une Url formatée selon que l'on utilise l'url_rewriting ou non - * si oui, on cherche dans la table de routage la correspondance pour formater + * Affiche une Url formatée * @param $url l'url à formater définie comme un tableau : * $url['c'] = controller * $url['a'] = action @@ -39,13 +38,7 @@ class Minz_Url { } if ($isArray) { - $router = new Minz_Router (); - - if (Minz_Configuration::useUrlRewriting ()) { - $url_string .= $router->printUriRewrited ($url); - } else { - $url_string .= self::printUri ($url, $encodage); - } + $url_string .= self::printUri ($url, $encodage); } else { $url_string .= $url; } @@ -54,7 +47,7 @@ class Minz_Url { } /** - * Construit l'URI d'une URL sans url rewriting + * Construit l'URI d'une URL * @param l'url sous forme de tableau * @param $encodage pour indiquer comment encoder les & (& ou & pour html) * @return l'uri sous la forme ?key=value&key2=value2 diff --git a/p/i/install.php b/p/i/install.php index a7563d5ee..f97f95d37 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -228,7 +228,6 @@ function saveStep3 () { $ini_array = array( 'general' => array( 'environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], - 'use_url_rewriting' => false, 'salt' => $_SESSION['salt'], 'base_url' => '', 'title' => $_SESSION['title'], -- cgit v1.2.3 From 6aadb7e59a1c8e70cfa42457e1898e94fd854fb0 Mon Sep 17 00:00:00 2001 From: Nicolas ELIE Date: Fri, 9 May 2014 09:53:46 +0200 Subject: Username regexp is too strict Username can contains more characters that the regexp allows. For example, on a raspberry pi, the default user for web server is 'www-data'. --- p/i/install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p/i/install.php') diff --git a/p/i/install.php b/p/i/install.php index f97f95d37..365d0696c 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -913,7 +913,7 @@ function printStep3 () {
- +
-- cgit v1.2.3 From 8c132b2acd6fa5771237cce5b890c7ad534c375a Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Fri, 13 Jun 2014 18:14:44 +0200 Subject: Fix theme paths for install.php --- app/views/configure/users.phtml | 6 +++--- p/i/install.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'p/i/install.php') diff --git a/app/views/configure/users.phtml b/app/views/configure/users.phtml index 87aac6198..272896fb2 100644 --- a/app/views/configure/users.phtml +++ b/app/views/configure/users.phtml @@ -22,7 +22,7 @@
/> - +
@@ -34,7 +34,7 @@
/> - +
@@ -184,7 +184,7 @@
- +
diff --git a/p/i/install.php b/p/i/install.php index 365d0696c..bc9483f73 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -1028,8 +1028,8 @@ case 6: <?php echo _t ('freshrss_installation'); ?> - - + + -- cgit v1.2.3 From 8a5050289ef695dc4d388eecee692ad9d83e00ce Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 3 Jul 2014 21:20:11 +0200 Subject: New install logic Now the install.php is kept in ./app/ and the trigger is ./data/do-install.php There is no need anymore to have write access in ./p/i/ --- app/i18n/install.en.php | 2 +- app/i18n/install.fr.php | 2 +- app/install.php | 1115 +++++++++++++++++++++++++++++++++++++++++++++++ data/do-install.txt | 0 p/i/index.php | 16 +- p/i/install.php | 1084 --------------------------------------------- 6 files changed, 1125 insertions(+), 1094 deletions(-) create mode 100644 app/install.php create mode 100644 data/do-install.txt delete mode 100644 p/i/install.php (limited to 'p/i/install.php') diff --git a/app/i18n/install.en.php b/app/i18n/install.en.php index 0311ee9a4..553a79921 100644 --- a/app/i18n/install.en.php +++ b/app/i18n/install.en.php @@ -61,7 +61,7 @@ return array ( 'update_end' => 'Update process is completed, now you can go to the final step.', - 'installation_is_ok' => 'The installation process was successful.
The final step will now attempt to delete the ./p/i/install.php file and any database backup created during the update process.
You may choose to skip this step and delete ./p/i/install.php manually.', + 'installation_is_ok' => 'The installation process was successful.
The final step will now attempt to delete any file and database backup created during the update process.
You may choose to skip this step by deleting ./data/do-install.txt manually.', 'finish_installation' => 'Complete installation', 'install_not_deleted' => 'Something went wrong; you must delete the file %s manually.', ); diff --git a/app/i18n/install.fr.php b/app/i18n/install.fr.php index bb183642f..470d83e1a 100644 --- a/app/i18n/install.fr.php +++ b/app/i18n/install.fr.php @@ -60,7 +60,7 @@ return array ( 'update_long' => 'Ce processus peut prendre longtemps, selon la taille de votre base de données. Vous aurez peut-être à attendre que cette page dépasse son temps maximum d’exécution (~5 minutes) puis à la recharger.', 'update_end' => 'La mise à jour est terminée, vous pouvez maintenant passer à l’étape finale.', - 'installation_is_ok' => 'L’installation s’est bien passée.
La dernière étape va maintenant tenter de supprimer le fichier ./p/i/install.php, ainsi que d’éventuelles copies de base de données créées durant le processus de mise à jour.
Vous pouvez choisir de sauter cette étape et de supprimer ./p/i/install.php manuellement.', + 'installation_is_ok' => 'L’installation s’est bien passée.
La dernière étape va maintenant tenter de supprimer les fichiers ainsi que d’éventuelles copies de base de données créés durant le processus de mise à jour.
Vous pouvez choisir de sauter cette étape en supprimant ./data/do-install.txt manuellement.', 'finish_installation' => 'Terminer l’installation', 'install_not_deleted' => 'Quelque chose s’est mal passé, vous devez supprimer le fichier %s à la main.', ); diff --git a/app/install.php b/app/install.php new file mode 100644 index 000000000..9863dd556 --- /dev/null +++ b/app/install.php @@ -0,0 +1,1115 @@ + +define('SQL_BACKUP006', 'RENAME TABLE `%1$scategory` TO `%1$scategory006`, `%1$sfeed` TO `%1$sfeed006`, `%1$sentry` TO `%1$sentry006`;'); + +define('SQL_SHOW_COLUMNS_UPDATEv006', 'SHOW columns FROM `%1$sentry006` LIKE "id2";'); + +define('SQL_UPDATEv006', ' +ALTER TABLE `%1$scategory006` ADD id2 SMALLINT; + +SET @i = 0; +UPDATE `%1$scategory006` SET id2=(@i:=@i+1) ORDER BY id; + +ALTER TABLE `%1$sfeed006` ADD id2 SMALLINT, ADD category2 SMALLINT; + +SET @i = 0; +UPDATE `%1$sfeed006` SET id2=(@i:=@i+1) ORDER BY name; + +UPDATE `%1$sfeed006` f +INNER JOIN `%1$scategory006` c ON f.category = c.id +SET f.category2 = c.id2; + +INSERT IGNORE INTO `%2$scategory` (name) +SELECT name +FROM `%1$scategory006` +ORDER BY id2; + +INSERT IGNORE INTO `%2$sfeed` (url, category, name, website, description, priority, pathEntries, httpAuth, keep_history) +SELECT url, category2, name, website, description, priority, pathEntries, httpAuth, IF(keep_history = 1, -1, -2) +FROM `%1$sfeed006` +ORDER BY id2; + +ALTER TABLE `%1$sentry006` ADD id2 bigint; + +UPDATE `%1$sentry006` SET id2 = ((date * 1000000) + (rand() * 100000000)); + +INSERT IGNORE INTO `%2$sentry` (id, guid, title, author, link, date, is_read, is_favorite, id_feed, tags) +SELECT e0.id2, e0.guid, e0.title, e0.author, e0.link, e0.date, e0.is_read, e0.is_favorite, f0.id2, e0.tags +FROM `%1$sentry006` e0 +INNER JOIN `%1$sfeed006` f0 ON e0.id_feed = f0.id; +'); + +define('SQL_CONVERT_SELECTv006', ' +SELECT e0.id2, e0.content +FROM `%1$sentry006` e0 +INNER JOIN `%2$sentry` e1 ON e0.id2 = e1.id +WHERE e1.content_bin IS NULL'); + +define('SQL_CONVERT_UPDATEv006', 'UPDATE `%1$sentry` SET ' + . (isset($_SESSION['bd_type']) && $_SESSION['bd_type'] === 'mysql' ? 'content_bin=COMPRESS(?)' : 'content=?') + . ' WHERE id=?;'); + +define('SQL_DROP_BACKUPv006', 'DROP TABLE IF EXISTS `%1$sentry006`, `%1$sfeed006`, `%1$scategory006`;'); + +define('SQL_UPDATE_CACHED_VALUES', ' +UPDATE `%1$sfeed` f +INNER JOIN ( + SELECT e.id_feed, + COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, + COUNT(e.id) AS nbEntries + FROM `%1$sentry` e + GROUP BY e.id_feed +) x ON x.id_feed=f.id +SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads +'); + +define('SQL_UPDATE_HISTORYv007b', 'UPDATE `%1$sfeed` SET keep_history = CASE WHEN keep_history = 0 THEN -2 WHEN keep_history = 1 THEN -1 ELSE keep_history END;'); + +define('SQL_GET_FEEDS', 'SELECT id, url, website FROM `%1$sfeed`;'); +// + +// gestion internationalisation +$translates = array (); +$actual = 'en'; +function initTranslate () { + global $translates; + global $actual; + + $actual = isset($_SESSION['language']) ? $_SESSION['language'] : getBetterLanguage('en'); + + $file = APP_PATH . '/i18n/' . $actual . '.php'; + if (file_exists($file)) { + $translates = array_merge($translates, include($file)); + } + + $file = APP_PATH . '/i18n/install.' . $actual . '.php'; + if (file_exists($file)) { + $translates = array_merge($translates, include($file)); + } +} + +function getBetterLanguage ($fallback) { + $available = availableLanguages (); + $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + $language = strtolower (substr ($accept, 0, 2)); + + if (isset ($available[$language])) { + return $language; + } else { + return $fallback; + } +} +function availableLanguages () { + return array ( + 'en' => 'English', + 'fr' => 'Français' + ); +} +function _t ($key) { + global $translates; + $translate = $key; + if (isset ($translates[$key])) { + $translate = $translates[$key]; + } + + $args = func_get_args (); + unset($args[0]); + + return vsprintf ($translate, $args); +} + +/*** SAUVEGARDES ***/ +function saveLanguage () { + if (!empty ($_POST)) { + if (!isset ($_POST['language'])) { + return false; + } + + $_SESSION['language'] = $_POST['language']; + + header ('Location: index.php?step=1'); + } +} +function saveStep2 () { + if (!empty ($_POST)) { + if (empty ($_POST['title']) || + empty ($_POST['old_entries']) || + empty ($_POST['auth_type']) || + empty ($_POST['default_user'])) { + return false; + } + + $_SESSION['salt'] = sha1(uniqid(mt_rand(), true).implode('', stat(__FILE__))); + $_SESSION['title'] = substr(trim($_POST['title']), 0, 25); + $_SESSION['old_entries'] = $_POST['old_entries']; + if ((!ctype_digit($_SESSION['old_entries'])) || ($_SESSION['old_entries'] < 1)) { + $_SESSION['old_entries'] = 3; + } + $_SESSION['mail_login'] = filter_var($_POST['mail_login'], FILTER_VALIDATE_EMAIL); + $_SESSION['default_user'] = substr(preg_replace('/[^a-zA-Z0-9]/', '', $_POST['default_user']), 0, 16); + $_SESSION['auth_type'] = $_POST['auth_type']; + if (!empty($_POST['passwordPlain'])) { + if (!function_exists('password_hash')) { + include_once(LIB_PATH . '/password_compat.php'); + } + $passwordHash = password_hash($_POST['passwordPlain'], PASSWORD_BCRYPT, array('cost' => BCRYPT_COST)); + $passwordHash = preg_replace('/^\$2[xy]\$/', '\$2a\$', $passwordHash); //Compatibility with bcrypt.js + $_SESSION['passwordHash'] = $passwordHash; + } + + $token = ''; + if ($_SESSION['mail_login']) { + $token = sha1($_SESSION['salt'] . $_SESSION['mail_login']); + } + + $config_array = array ( + 'language' => $_SESSION['language'], + 'theme' => $_SESSION['theme'], + 'old_entries' => $_SESSION['old_entries'], + 'mail_login' => $_SESSION['mail_login'], + 'passwordHash' => $_SESSION['passwordHash'], + 'token' => $token, + ); + + $configPath = DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'; + @unlink($configPath); //To avoid access-rights problems + file_put_contents($configPath, " array( + 'environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], + 'salt' => $_SESSION['salt'], + 'base_url' => '', + 'title' => $_SESSION['title'], + 'default_user' => $_SESSION['default_user'], + 'auth_type' => $_SESSION['auth_type'], + 'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false, + 'allow_anonymous_refresh' => false, + 'unsafe_autologin_enabled' => false, + 'api_enabled' => false, + ), + 'db' => array( + 'type' => $_SESSION['bd_type'], + 'host' => $_SESSION['bd_host'], + 'user' => $_SESSION['bd_user'], + 'password' => $_SESSION['bd_password'], + 'base' => $_SESSION['bd_base'], + 'prefix' => $_SESSION['bd_prefix'], + ), + ); + + @unlink(DATA_PATH . '/config.php'); //To avoid access-rights problems + file_put_contents(DATA_PATH . '/config.php', " 'SET NAMES utf8', + ); + break; + case 'sqlite': + return false; //No update for SQLite needed so far + default: + return false; + } + + $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + + $stm = $c->prepare(SQL_SHOW_TABLES); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + if (!in_array($_SESSION['bd_prefix'] . 'entry006', $res)) { + return false; + } + + $sql = sprintf(SQL_SHOW_COLUMNS_UPDATEv006, $_SESSION['bd_prefix']); + $stm = $c->prepare($sql); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + if (!in_array('id2', $res)) { + if (!$perform) { + return true; + } + $sql = sprintf(SQL_UPDATEv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true)); + $stm->execute(); + } + + $sql = sprintf(SQL_CONVERT_SELECTv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']); + if (!$perform) { + $sql .= ' LIMIT 1'; + } + $stm = $c->prepare($sql); + $stm->execute(); + if (!$perform) { + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + return count($res) > 0; + } else { + @set_time_limit(300); + } + + $c2 = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + $sql = sprintf(SQL_CONVERT_UPDATEv006, $_SESSION['bd_prefix_user']); + $stm2 = $c2->prepare($sql); + while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { + $id = $row['id2']; + $content = unserialize(gzinflate(base64_decode($row['content']))); + $stm2->execute(array($content, $id)); + } + + return true; + } catch (PDOException $e) { + return false; + } + return false; +} + +function newPdo() { + switch ($_SESSION['bd_type']) { + case 'mysql': + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', + ); + break; + case 'sqlite': + $str = 'sqlite:' . DATA_PATH . '/' . $_SESSION['bd_base'] . '.sqlite'; + $driver_options = array( + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + ); + break; + default: + return false; + } + return new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); +} + +function postUpdate() { + $c = newPdo(); + + if ($_SESSION['bd_type'] !== 'sqlite') { //No update for SQLite needed yet + $sql = sprintf(SQL_UPDATE_HISTORYv007b, $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql); + $stm->execute(); + + $sql = sprintf(SQL_UPDATE_CACHED_VALUES, $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql); + $stm->execute(); + } + + // + $sql = sprintf(SQL_GET_FEEDS, $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_ASSOC); + foreach ($res as $feed) { + if (empty($feed['url'])) { + continue; + } + $hash = hash('crc32b', $_SESSION['salt'] . $feed['url']); + @file_put_contents(DATA_PATH . '/favicons/' . $hash . '.txt', + empty($feed['website']) ? $feed['url'] : $feed['website']); + } + // +} + +function deleteInstall () { + $res = unlink (DATA_PATH . 'do-install.txt'); + if ($res) { + header ('Location: index.php'); + } + + $needs = array('bd_type', 'bd_host', 'bd_base', 'bd_user', 'bd_password', 'bd_prefix'); + foreach ($needs as $need) { + if (!isset($_SESSION[$need])) { + return false; + } + } + + try { + $c = newPdo(); + $sql = sprintf(SQL_DROP_BACKUPv006, $_SESSION['bd_prefix']); + $stm = $c->prepare($sql); + $stm->execute(); + + return true; + } catch (PDOException $e) { + return false; + } + return false; +} + +function moveOldFiles() { + $mvs = array( + '/app/configuration/application.ini' => '/data/application.ini', //v0.6 + '/public/data/Configuration.array.php' => '/data/Configuration.array.php', //v0.6 + ); + $ok = true; + foreach ($mvs as $fFrom => $fTo) { + if (file_exists(FRESHRSS_PATH . $fFrom)) { + if (copy(FRESHRSS_PATH . $fFrom, FRESHRSS_PATH . $fTo)) { + @unlink(FRESHRSS_PATH . $fFrom); + } else { + $ok = false; + } + } + } + return $ok; +} + +function delTree($dir) { //http://php.net/rmdir#110489 + if (!is_dir($dir)) { + return true; + } + $files = array_diff(scandir($dir), array('.', '..')); + foreach ($files as $file) { + $f = $dir . '/' . $file; + if (is_dir($f)) { + @chmod($f, 0777); + delTree($f); + } + else unlink($f); + } + return rmdir($dir); +} + +/*** VÉRIFICATIONS ***/ +function checkStep () { + $s0 = checkStep0 (); + $s1 = checkStep1 (); + $s2 = checkStep2 (); + $s3 = checkStep3 (); + if (STEP > 0 && $s0['all'] != 'ok') { + header ('Location: index.php?step=0'); + } elseif (STEP > 1 && $s1['all'] != 'ok') { + header ('Location: index.php?step=1'); + } elseif (STEP > 2 && $s2['all'] != 'ok') { + header ('Location: index.php?step=2'); + } elseif (STEP > 3 && $s3['all'] != 'ok') { + header ('Location: index.php?step=3'); + } + $_SESSION['actualize_feeds'] = true; +} +function checkStep0 () { + moveOldFiles(); + + if (file_exists(DATA_PATH . '/config.php')) { + $ini_array = include(DATA_PATH . '/config.php'); + } elseif (file_exists(DATA_PATH . '/application.ini')) { //v0.6 + $ini_array = parse_ini_file(DATA_PATH . '/application.ini', true); + $ini_array['general']['title'] = empty($ini_array['general']['title']) ? '' : stripslashes($ini_array['general']['title']); + } else { + $ini_array = null; + } + + if ($ini_array) { + $ini_general = isset($ini_array['general']) ? $ini_array['general'] : null; + if ($ini_general) { + $keys = array('environment', 'salt', 'title', 'default_user', 'allow_anonymous', 'auth_type'); + foreach ($keys as $key) { + if ((empty($_SESSION[$key])) && isset($ini_general[$key])) { + $_SESSION[$key] = $ini_general[$key]; + } + } + } + $ini_db = isset($ini_array['db']) ? $ini_array['db'] : null; + if ($ini_db) { + $keys = array('type', 'host', 'user', 'password', 'base', 'prefix'); + foreach ($keys as $key) { + if ((!isset($_SESSION['bd_' . $key])) && isset($ini_db[$key])) { + $_SESSION['bd_' . $key] = $ini_db[$key]; + } + } + } + } + + if (isset($_SESSION['default_user']) && file_exists(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php')) { + $userConfig = include(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'); + } elseif (file_exists(DATA_PATH . '/Configuration.array.php')) { + $userConfig = include(DATA_PATH . '/Configuration.array.php'); //v0.6 + if (empty($_SESSION['auth_type'])) { + $_SESSION['auth_type'] = empty($userConfig['mail_login']) ? 'none' : 'persona'; + } + if (!isset($_SESSION['allow_anonymous'])) { + $_SESSION['allow_anonymous'] = empty($userConfig['anon_access']) ? false : ($userConfig['anon_access'] === 'yes'); + } + } else { + $userConfig = array(); + } + if (empty($_SESSION['auth_type'])) { //v0.7b + $_SESSION['auth_type'] = ''; + } + + $keys = array('language', 'theme', 'old_entries', 'mail_login', 'passwordHash'); + foreach ($keys as $key) { + if ((!isset($_SESSION[$key])) && isset($userConfig[$key])) { + $_SESSION[$key] = $userConfig[$key]; + } + } + + $languages = availableLanguages (); + $language = isset ($_SESSION['language']) && + isset ($languages[$_SESSION['language']]); + + if (empty($_SESSION['passwordHash'])) { //v0.7b + $_SESSION['passwordHash'] = ''; + } + if (empty($_SESSION['theme'])) { + $_SESSION['theme'] = 'Origine'; + } else { + switch (strtolower($_SESSION['theme'])) { + case 'default': //v0.7b + $_SESSION['theme'] = 'Origine'; + break; + case 'flat-design': //v0.7b + $_SESSION['theme'] = 'Flat'; + break; + case 'default_dark': //v0.7b + $_SESSION['theme'] = 'Dark'; + break; + } + } + + return array ( + 'language' => $language ? 'ok' : 'ko', + 'all' => $language ? 'ok' : 'ko' + ); +} + +function checkStep1 () { + $php = version_compare (PHP_VERSION, '5.2.1') >= 0; + $minz = file_exists (LIB_PATH . '/Minz'); + $curl = extension_loaded ('curl'); + $pdo = extension_loaded ('pdo_mysql'); + $pcre = extension_loaded ('pcre'); + $ctype = extension_loaded ('ctype'); + $dom = class_exists('DOMDocument'); + $data = DATA_PATH && is_writable (DATA_PATH); + $cache = CACHE_PATH && is_writable (CACHE_PATH); + $log = LOG_PATH && is_writable (LOG_PATH); + $favicons = is_writable (DATA_PATH . '/favicons'); + $persona = is_writable (DATA_PATH . '/persona'); + + return array ( + 'php' => $php ? 'ok' : 'ko', + 'minz' => $minz ? 'ok' : 'ko', + 'curl' => $curl ? 'ok' : 'ko', + 'pdo-mysql' => $pdo ? 'ok' : 'ko', + 'pcre' => $pcre ? 'ok' : 'ko', + 'ctype' => $ctype ? 'ok' : 'ko', + 'dom' => $dom ? 'ok' : 'ko', + 'data' => $data ? 'ok' : 'ko', + 'cache' => $cache ? 'ok' : 'ko', + 'log' => $log ? 'ok' : 'ko', + 'favicons' => $favicons ? 'ok' : 'ko', + 'persona' => $persona ? 'ok' : 'ko', + 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $dom && $data && $cache && $log && $favicons && $persona ? 'ok' : 'ko' + ); +} + +function checkStep2 () { + $conf = !empty($_SESSION['salt']) && + !empty($_SESSION['title']) && + !empty($_SESSION['old_entries']) && + isset($_SESSION['mail_login']) && + !empty($_SESSION['default_user']); + $defaultUser = empty($_POST['default_user']) ? null : $_POST['default_user']; + if ($defaultUser === null) { + $defaultUser = empty($_SESSION['default_user']) ? '' : $_SESSION['default_user']; + } + $data = is_writable(DATA_PATH . '/' . $defaultUser . '_user.php'); + if ($data) { + @unlink(DATA_PATH . '/Configuration.array.php'); //v0.6 + } + + return array ( + 'conf' => $conf ? 'ok' : 'ko', + 'data' => $data ? 'ok' : 'ko', + 'all' => $conf && $data ? 'ok' : 'ko' + ); +} +function checkStep3 () { + $conf = is_writable(DATA_PATH . '/config.php'); + + $bd = isset ($_SESSION['bd_type']) && + isset ($_SESSION['bd_host']) && + isset ($_SESSION['bd_user']) && + isset ($_SESSION['bd_password']) && + isset ($_SESSION['bd_base']) && + isset ($_SESSION['bd_prefix']) && + isset ($_SESSION['bd_error']); + $conn = empty($_SESSION['bd_error']); + + return array ( + 'bd' => $bd ? 'ok' : 'ko', + 'conn' => $conn ? 'ok' : 'ko', + 'conf' => $conf ? 'ok' : 'ko', + 'all' => $bd && $conn && $conf ? 'ok' : 'ko' + ); +} + +function checkBD () { + $ok = false; + + try { + $str = ''; + $driver_options = null; + switch ($_SESSION['bd_type']) { + case 'mysql': + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' + ); + + try { // on ouvre une connexion juste pour créer la base si elle n'existe pas + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';'; + $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + $sql = sprintf (SQL_CREATE_DB, $_SESSION['bd_base']); + $res = $c->query ($sql); + } catch (PDOException $e) { + } + + // on écrase la précédente connexion en sélectionnant la nouvelle BDD + $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; + break; + case 'sqlite': + $str = 'sqlite:' . DATA_PATH . '/' . $_SESSION['bd_base'] . '.sqlite'; + $driver_options = array( + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + ); + break; + default: + return false; + } + + $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); + + if ($_SESSION['bd_type'] !== 'sqlite') { //No SQL backup for SQLite + $stm = $c->prepare(SQL_SHOW_TABLES); + $stm->execute(); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + if (in_array($_SESSION['bd_prefix'] . 'entry', $res) && !in_array($_SESSION['bd_prefix'] . 'entry006', $res)) { + $sql = sprintf(SQL_BACKUP006, $_SESSION['bd_prefix']); //v0.6 + $res = $c->query($sql); //Backup tables + } + } + + if (defined('SQL_CREATE_TABLES')) { + $sql = sprintf(SQL_CREATE_TABLES, $_SESSION['bd_prefix_user'], _t('default_category')); + $stm = $c->prepare($sql); + $ok = $stm->execute(); + } else { + global $SQL_CREATE_TABLES; + if (is_array($SQL_CREATE_TABLES)) { + $ok = true; + foreach ($SQL_CREATE_TABLES as $instruction) { + $sql = sprintf($instruction, $_SESSION['bd_prefix_user'], _t('default_category')); + $stm = $c->prepare($sql); + $ok &= $stm->execute(); + } + } + } + } catch (PDOException $e) { + $ok = false; + $_SESSION['bd_error'] = $e->getMessage(); + } + + if (!$ok) { + @unlink(DATA_PATH . '/config.php'); + } + + return $ok; +} + +/*** AFFICHAGE ***/ +function printStep0 () { + global $actual; +?> + +

+ + +
+ +
+ +
+ +
+
+ +
+
+ + + + + +
+
+
+ + + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + + + +

+ + + +

+ + +
+ + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+
+ + + + + +
+
+
+ + +

+ +

+ + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ + + + + +
+
+
+ +
+ + + +

+ +
+
+ + +
+
+ + +

+ +
+
+ +
+
+ +
+ +

+ + +

+ + + + + + + <?php echo _t ('freshrss_installation'); ?> + + + + + +
+
+

+

+
+
+ +
+ + +
+ +
+
+ + diff --git a/data/do-install.txt b/data/do-install.txt new file mode 100644 index 000000000..e69de29bb diff --git a/p/i/index.php b/p/i/index.php index 4afffb3dd..7b34eefd1 100755 --- a/p/i/index.php +++ b/p/i/index.php @@ -18,12 +18,12 @@ # # ***** END LICENSE BLOCK ***** -if (file_exists ('install.php')) { - require('install.php'); -} else { - require('../../constants.php'); - require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader +require('../../constants.php'); +require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader +if (file_exists(DATA_PATH . '/do-install.txt')) { + require(APP_PATH . '/install.php'); +} else { session_cache_limiter(''); Minz_Session::init('FreshRSS'); Minz_Session::_param('keepAlive', 1); //For Persona @@ -42,11 +42,11 @@ if (file_exists ('install.php')) { try { $front_controller = new FreshRSS(); - $front_controller->init (); - $front_controller->run (); + $front_controller->init(); + $front_controller->run(); } catch (Exception $e) { echo '### Fatal error! ###
', "\n"; - Minz_Log::record ($e->getMessage (), Minz_Log::ERROR); + Minz_Log::record($e->getMessage(), Minz_Log::ERROR); echo 'See logs files.'; } } diff --git a/p/i/install.php b/p/i/install.php deleted file mode 100644 index bc9483f73..000000000 --- a/p/i/install.php +++ /dev/null @@ -1,1084 +0,0 @@ - -define('SQL_SHOW_TABLES', 'SHOW tables;'); - -define('SQL_BACKUP006', 'RENAME TABLE `%1$scategory` TO `%1$scategory006`, `%1$sfeed` TO `%1$sfeed006`, `%1$sentry` TO `%1$sentry006`;'); - -define('SQL_SHOW_COLUMNS_UPDATEv006', 'SHOW columns FROM `%1$sentry006` LIKE "id2";'); - -define('SQL_UPDATEv006', ' -ALTER TABLE `%1$scategory006` ADD id2 SMALLINT; - -SET @i = 0; -UPDATE `%1$scategory006` SET id2=(@i:=@i+1) ORDER BY id; - -ALTER TABLE `%1$sfeed006` ADD id2 SMALLINT, ADD category2 SMALLINT; - -SET @i = 0; -UPDATE `%1$sfeed006` SET id2=(@i:=@i+1) ORDER BY name; - -UPDATE `%1$sfeed006` f -INNER JOIN `%1$scategory006` c ON f.category = c.id -SET f.category2 = c.id2; - -INSERT IGNORE INTO `%2$scategory` (name) -SELECT name -FROM `%1$scategory006` -ORDER BY id2; - -INSERT IGNORE INTO `%2$sfeed` (url, category, name, website, description, priority, pathEntries, httpAuth, keep_history) -SELECT url, category2, name, website, description, priority, pathEntries, httpAuth, IF(keep_history = 1, -1, -2) -FROM `%1$sfeed006` -ORDER BY id2; - -ALTER TABLE `%1$sentry006` ADD id2 bigint; - -UPDATE `%1$sentry006` SET id2 = ((date * 1000000) + (rand() * 100000000)); - -INSERT IGNORE INTO `%2$sentry` (id, guid, title, author, link, date, is_read, is_favorite, id_feed, tags) -SELECT e0.id2, e0.guid, e0.title, e0.author, e0.link, e0.date, e0.is_read, e0.is_favorite, f0.id2, e0.tags -FROM `%1$sentry006` e0 -INNER JOIN `%1$sfeed006` f0 ON e0.id_feed = f0.id; -'); - -define('SQL_CONVERT_SELECTv006', ' -SELECT e0.id2, e0.content -FROM `%1$sentry006` e0 -INNER JOIN `%2$sentry` e1 ON e0.id2 = e1.id -WHERE e1.content_bin IS NULL'); - -define('SQL_CONVERT_UPDATEv006', 'UPDATE `%1$sentry` SET content_bin=COMPRESS(?) WHERE id=?;'); - -define('SQL_DROP_BACKUPv006', 'DROP TABLE IF EXISTS `%1$sentry006`, `%1$sfeed006`, `%1$scategory006`;'); - -define('SQL_UPDATE_CACHED_VALUES', ' -UPDATE `%1$sfeed` f -INNER JOIN ( - SELECT e.id_feed, - COUNT(CASE WHEN e.is_read = 0 THEN 1 END) AS nbUnreads, - COUNT(e.id) AS nbEntries - FROM `%1$sentry` e - GROUP BY e.id_feed -) x ON x.id_feed=f.id -SET f.cache_nbEntries=x.nbEntries, f.cache_nbUnreads=x.nbUnreads -'); - -define('SQL_UPDATE_HISTORYv007b', 'UPDATE `%1$sfeed` SET keep_history = CASE WHEN keep_history = 0 THEN -2 WHEN keep_history = 1 THEN -1 ELSE keep_history END;'); - -define('SQL_GET_FEEDS', 'SELECT id, url, website FROM `%1$sfeed`;'); -// - -// gestion internationalisation -$translates = array (); -$actual = 'en'; -function initTranslate () { - global $translates; - global $actual; - - $actual = isset($_SESSION['language']) ? $_SESSION['language'] : getBetterLanguage('en'); - - $file = APP_PATH . '/i18n/' . $actual . '.php'; - if (file_exists($file)) { - $translates = array_merge($translates, include($file)); - } - - $file = APP_PATH . '/i18n/install.' . $actual . '.php'; - if (file_exists($file)) { - $translates = array_merge($translates, include($file)); - } -} - -function getBetterLanguage ($fallback) { - $available = availableLanguages (); - $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE']; - $language = strtolower (substr ($accept, 0, 2)); - - if (isset ($available[$language])) { - return $language; - } else { - return $fallback; - } -} -function availableLanguages () { - return array ( - 'en' => 'English', - 'fr' => 'Français' - ); -} -function _t ($key) { - global $translates; - $translate = $key; - if (isset ($translates[$key])) { - $translate = $translates[$key]; - } - - $args = func_get_args (); - unset($args[0]); - - return vsprintf ($translate, $args); -} - -/*** SAUVEGARDES ***/ -function saveLanguage () { - if (!empty ($_POST)) { - if (!isset ($_POST['language'])) { - return false; - } - - $_SESSION['language'] = $_POST['language']; - - header ('Location: index.php?step=1'); - } -} -function saveStep2 () { - if (!empty ($_POST)) { - if (empty ($_POST['title']) || - empty ($_POST['old_entries']) || - empty ($_POST['auth_type']) || - empty ($_POST['default_user'])) { - return false; - } - - $_SESSION['salt'] = sha1(uniqid(mt_rand(), true).implode('', stat(__FILE__))); - $_SESSION['title'] = substr(trim($_POST['title']), 0, 25); - $_SESSION['old_entries'] = $_POST['old_entries']; - if ((!ctype_digit($_SESSION['old_entries'])) || ($_SESSION['old_entries'] < 1)) { - $_SESSION['old_entries'] = 3; - } - $_SESSION['mail_login'] = filter_var($_POST['mail_login'], FILTER_VALIDATE_EMAIL); - $_SESSION['default_user'] = substr(preg_replace('/[^a-zA-Z0-9]/', '', $_POST['default_user']), 0, 16); - $_SESSION['auth_type'] = $_POST['auth_type']; - if (!empty($_POST['passwordPlain'])) { - if (!function_exists('password_hash')) { - include_once(LIB_PATH . '/password_compat.php'); - } - $passwordHash = password_hash($_POST['passwordPlain'], PASSWORD_BCRYPT, array('cost' => BCRYPT_COST)); - $passwordHash = preg_replace('/^\$2[xy]\$/', '\$2a\$', $passwordHash); //Compatibility with bcrypt.js - $_SESSION['passwordHash'] = $passwordHash; - } - - $token = ''; - if ($_SESSION['mail_login']) { - $token = sha1($_SESSION['salt'] . $_SESSION['mail_login']); - } - - $config_array = array ( - 'language' => $_SESSION['language'], - 'theme' => $_SESSION['theme'], - 'old_entries' => $_SESSION['old_entries'], - 'mail_login' => $_SESSION['mail_login'], - 'passwordHash' => $_SESSION['passwordHash'], - 'token' => $token, - ); - - $configPath = DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'; - @unlink($configPath); //To avoid access-rights problems - file_put_contents($configPath, " array( - 'environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], - 'salt' => $_SESSION['salt'], - 'base_url' => '', - 'title' => $_SESSION['title'], - 'default_user' => $_SESSION['default_user'], - 'auth_type' => $_SESSION['auth_type'], - 'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false, - 'allow_anonymous_refresh' => false, - 'unsafe_autologin_enabled' => false, - 'api_enabled' => false, - ), - 'db' => array( - 'type' => $_SESSION['bd_type'], - 'host' => $_SESSION['bd_host'], - 'user' => $_SESSION['bd_user'], - 'password' => $_SESSION['bd_password'], - 'base' => $_SESSION['bd_base'], - 'prefix' => $_SESSION['bd_prefix'], - ), - ); - - @unlink(DATA_PATH . '/config.php'); //To avoid access-rights problems - file_put_contents(DATA_PATH . '/config.php', " 'SET NAMES utf8', - ); - break; - case 'sqlite': - $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_base'] . '.sqlite'; - $driver_options = null; - break; - default: - return false; - } - - $c = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); - - $stm = $c->prepare(SQL_SHOW_TABLES); - $stm->execute(); - $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); - if (!in_array($_SESSION['bd_prefix'] . 'entry006', $res)) { - return false; - } - - $sql = sprintf(SQL_SHOW_COLUMNS_UPDATEv006, $_SESSION['bd_prefix']); - $stm = $c->prepare($sql); - $stm->execute(); - $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); - if (!in_array('id2', $res)) { - if (!$perform) { - return true; - } - $sql = sprintf(SQL_UPDATEv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']); - $stm = $c->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true)); - $stm->execute(); - } - - $sql = sprintf(SQL_CONVERT_SELECTv006, $_SESSION['bd_prefix'], $_SESSION['bd_prefix_user']); - if (!$perform) { - $sql .= ' LIMIT 1'; - } - $stm = $c->prepare($sql); - $stm->execute(); - if (!$perform) { - $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); - return count($res) > 0; - } else { - @set_time_limit(300); - } - - $c2 = new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); - $sql = sprintf(SQL_CONVERT_UPDATEv006, $_SESSION['bd_prefix_user']); - $stm2 = $c2->prepare($sql); - while ($row = $stm->fetch(PDO::FETCH_ASSOC)) { - $id = $row['id2']; - $content = unserialize(gzinflate(base64_decode($row['content']))); - $stm2->execute(array($content, $id)); - } - - return true; - } catch (PDOException $e) { - return false; - } - return false; -} - -function newPdo() { - switch ($_SESSION['bd_type']) { - case 'mysql': - $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; - $driver_options = array( - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', - ); - break; - case 'sqlite': - $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_base'] . '.sqlite'; - $driver_options = null; - break; - default: - return false; - } - return new PDO($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); -} - -function postUpdate() { - $c = newPdo(); - - $sql = sprintf(SQL_UPDATE_HISTORYv007b, $_SESSION['bd_prefix_user']); - $stm = $c->prepare($sql); - $stm->execute(); - - $sql = sprintf(SQL_UPDATE_CACHED_VALUES, $_SESSION['bd_prefix_user']); - $stm = $c->prepare($sql); - $stm->execute(); - - // - $sql = sprintf(SQL_GET_FEEDS, $_SESSION['bd_prefix_user']); - $stm = $c->prepare($sql); - $stm->execute(); - $res = $stm->fetchAll(PDO::FETCH_ASSOC); - foreach ($res as $feed) { - if (empty($feed['url'])) { - continue; - } - $hash = hash('crc32b', $_SESSION['salt'] . $feed['url']); - @file_put_contents(DATA_PATH . '/favicons/' . $hash . '.txt', - empty($feed['website']) ? $feed['url'] : $feed['website']); - } - // -} - -function deleteInstall () { - $res = unlink (INDEX_PATH . '/install.php'); - if ($res) { - header ('Location: index.php'); - } - - $needs = array('bd_type', 'bd_host', 'bd_base', 'bd_user', 'bd_password', 'bd_prefix'); - foreach ($needs as $need) { - if (!isset($_SESSION[$need])) { - return false; - } - } - - try { - $c = newPdo(); - $sql = sprintf(SQL_DROP_BACKUPv006, $_SESSION['bd_prefix']); - $stm = $c->prepare($sql); - $stm->execute(); - - return true; - } catch (PDOException $e) { - return false; - } - return false; -} - -function moveOldFiles() { - $mvs = array( - '/app/configuration/application.ini' => '/data/application.ini', //v0.6 - '/public/data/Configuration.array.php' => '/data/Configuration.array.php', //v0.6 - ); - $ok = true; - foreach ($mvs as $fFrom => $fTo) { - if (file_exists(FRESHRSS_PATH . $fFrom)) { - if (copy(FRESHRSS_PATH . $fFrom, FRESHRSS_PATH . $fTo)) { - @unlink(FRESHRSS_PATH . $fFrom); - } else { - $ok = false; - } - } - } - return $ok; -} - -function delTree($dir) { //http://php.net/rmdir#110489 - if (!is_dir($dir)) { - return true; - } - $files = array_diff(scandir($dir), array('.', '..')); - foreach ($files as $file) { - $f = $dir . '/' . $file; - if (is_dir($f)) { - @chmod($f, 0777); - delTree($f); - } - else unlink($f); - } - return rmdir($dir); -} - -/*** VÉRIFICATIONS ***/ -function checkStep () { - $s0 = checkStep0 (); - $s1 = checkStep1 (); - $s2 = checkStep2 (); - $s3 = checkStep3 (); - if (STEP > 0 && $s0['all'] != 'ok') { - header ('Location: index.php?step=0'); - } elseif (STEP > 1 && $s1['all'] != 'ok') { - header ('Location: index.php?step=1'); - } elseif (STEP > 2 && $s2['all'] != 'ok') { - header ('Location: index.php?step=2'); - } elseif (STEP > 3 && $s3['all'] != 'ok') { - header ('Location: index.php?step=3'); - } - $_SESSION['actualize_feeds'] = true; -} -function checkStep0 () { - moveOldFiles(); - - if (file_exists(DATA_PATH . '/config.php')) { - $ini_array = include(DATA_PATH . '/config.php'); - } elseif (file_exists(DATA_PATH . '/application.ini')) { //v0.6 - $ini_array = parse_ini_file(DATA_PATH . '/application.ini', true); - $ini_array['general']['title'] = empty($ini_array['general']['title']) ? '' : stripslashes($ini_array['general']['title']); - } else { - $ini_array = null; - } - - if ($ini_array) { - $ini_general = isset($ini_array['general']) ? $ini_array['general'] : null; - if ($ini_general) { - $keys = array('environment', 'salt', 'title', 'default_user', 'allow_anonymous', 'auth_type'); - foreach ($keys as $key) { - if ((empty($_SESSION[$key])) && isset($ini_general[$key])) { - $_SESSION[$key] = $ini_general[$key]; - } - } - } - $ini_db = isset($ini_array['db']) ? $ini_array['db'] : null; - if ($ini_db) { - $keys = array('type', 'host', 'user', 'password', 'base', 'prefix'); - foreach ($keys as $key) { - if ((!isset($_SESSION['bd_' . $key])) && isset($ini_db[$key])) { - $_SESSION['bd_' . $key] = $ini_db[$key]; - } - } - } - } - - if (isset($_SESSION['default_user']) && file_exists(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php')) { - $userConfig = include(DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'); - } elseif (file_exists(DATA_PATH . '/Configuration.array.php')) { - $userConfig = include(DATA_PATH . '/Configuration.array.php'); //v0.6 - if (empty($_SESSION['auth_type'])) { - $_SESSION['auth_type'] = empty($userConfig['mail_login']) ? 'none' : 'persona'; - } - if (!isset($_SESSION['allow_anonymous'])) { - $_SESSION['allow_anonymous'] = empty($userConfig['anon_access']) ? false : ($userConfig['anon_access'] === 'yes'); - } - } else { - $userConfig = array(); - } - if (empty($_SESSION['auth_type'])) { //v0.7b - $_SESSION['auth_type'] = ''; - } - - $keys = array('language', 'theme', 'old_entries', 'mail_login', 'passwordHash'); - foreach ($keys as $key) { - if ((!isset($_SESSION[$key])) && isset($userConfig[$key])) { - $_SESSION[$key] = $userConfig[$key]; - } - } - - $languages = availableLanguages (); - $language = isset ($_SESSION['language']) && - isset ($languages[$_SESSION['language']]); - - if (empty($_SESSION['passwordHash'])) { //v0.7b - $_SESSION['passwordHash'] = ''; - } - if (empty($_SESSION['theme'])) { - $_SESSION['theme'] = 'Origine'; - } else { - switch (strtolower($_SESSION['theme'])) { - case 'default': //v0.7b - $_SESSION['theme'] = 'Origine'; - break; - case 'flat-design': //v0.7b - $_SESSION['theme'] = 'Flat'; - break; - case 'default_dark': //v0.7b - $_SESSION['theme'] = 'Dark'; - break; - } - } - - return array ( - 'language' => $language ? 'ok' : 'ko', - 'all' => $language ? 'ok' : 'ko' - ); -} - -function checkStep1 () { - $php = version_compare (PHP_VERSION, '5.2.1') >= 0; - $minz = file_exists (LIB_PATH . '/Minz'); - $curl = extension_loaded ('curl'); - $pdo = extension_loaded ('pdo_mysql'); - $pcre = extension_loaded ('pcre'); - $ctype = extension_loaded ('ctype'); - $dom = class_exists('DOMDocument'); - $data = DATA_PATH && is_writable (DATA_PATH); - $cache = CACHE_PATH && is_writable (CACHE_PATH); - $log = LOG_PATH && is_writable (LOG_PATH); - $favicons = is_writable (DATA_PATH . '/favicons'); - $persona = is_writable (DATA_PATH . '/persona'); - - return array ( - 'php' => $php ? 'ok' : 'ko', - 'minz' => $minz ? 'ok' : 'ko', - 'curl' => $curl ? 'ok' : 'ko', - 'pdo-mysql' => $pdo ? 'ok' : 'ko', - 'pcre' => $pcre ? 'ok' : 'ko', - 'ctype' => $ctype ? 'ok' : 'ko', - 'dom' => $dom ? 'ok' : 'ko', - 'data' => $data ? 'ok' : 'ko', - 'cache' => $cache ? 'ok' : 'ko', - 'log' => $log ? 'ok' : 'ko', - 'favicons' => $favicons ? 'ok' : 'ko', - 'persona' => $persona ? 'ok' : 'ko', - 'all' => $php && $minz && $curl && $pdo && $pcre && $ctype && $dom && $data && $cache && $log && $favicons && $persona ? 'ok' : 'ko' - ); -} - -function checkStep2 () { - $conf = !empty($_SESSION['salt']) && - !empty($_SESSION['title']) && - !empty($_SESSION['old_entries']) && - isset($_SESSION['mail_login']) && - !empty($_SESSION['default_user']); - $defaultUser = empty($_POST['default_user']) ? null : $_POST['default_user']; - if ($defaultUser === null) { - $defaultUser = empty($_SESSION['default_user']) ? '' : $_SESSION['default_user']; - } - $data = is_writable(DATA_PATH . '/' . $defaultUser . '_user.php'); - if ($data) { - @unlink(DATA_PATH . '/Configuration.array.php'); //v0.6 - } - - return array ( - 'conf' => $conf ? 'ok' : 'ko', - 'data' => $data ? 'ok' : 'ko', - 'all' => $conf && $data ? 'ok' : 'ko' - ); -} -function checkStep3 () { - $conf = is_writable(DATA_PATH . '/config.php'); - - $bd = isset ($_SESSION['bd_type']) && - isset ($_SESSION['bd_host']) && - isset ($_SESSION['bd_user']) && - isset ($_SESSION['bd_password']) && - isset ($_SESSION['bd_base']) && - isset ($_SESSION['bd_prefix']) && - isset ($_SESSION['bd_error']); - $conn = empty($_SESSION['bd_error']); - - return array ( - 'bd' => $bd ? 'ok' : 'ko', - 'conn' => $conn ? 'ok' : 'ko', - 'conf' => $conf ? 'ok' : 'ko', - 'all' => $bd && $conn && $conf ? 'ok' : 'ko' - ); -} - -function checkBD () { - $ok = false; - - try { - $str = ''; - $driver_options = null; - switch ($_SESSION['bd_type']) { - case 'mysql': - $driver_options = array( - PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' - ); - - try { // on ouvre une connexion juste pour créer la base si elle n'existe pas - $str = 'mysql:host=' . $_SESSION['bd_host'] . ';'; - $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); - $sql = sprintf (SQL_CREATE_DB, $_SESSION['bd_base']); - $res = $c->query ($sql); - } catch (PDOException $e) { - } - - // on écrase la précédente connexion en sélectionnant la nouvelle BDD - $str = 'mysql:host=' . $_SESSION['bd_host'] . ';dbname=' . $_SESSION['bd_base']; - break; - case 'sqlite': - $str = 'sqlite:' . DATA_PATH . $_SESSION['bd_base'] . '.sqlite'; - break; - default: - return false; - } - - $c = new PDO ($str, $_SESSION['bd_user'], $_SESSION['bd_password'], $driver_options); - - $stm = $c->prepare(SQL_SHOW_TABLES); - $stm->execute(); - $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); - if (in_array($_SESSION['bd_prefix'] . 'entry', $res) && !in_array($_SESSION['bd_prefix'] . 'entry006', $res)) { - $sql = sprintf(SQL_BACKUP006, $_SESSION['bd_prefix']); //v0.6 - $res = $c->query($sql); //Backup tables - } - - $sql = sprintf(SQL_CREATE_TABLES, $_SESSION['bd_prefix_user']); - $stm = $c->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true)); - $values = array( - 'catName' => _t('default_category'), - ); - $ok = $stm->execute($values); - } catch (PDOException $e) { - $ok = false; - $_SESSION['bd_error'] = $e->getMessage(); - } - - if (!$ok) { - @unlink(DATA_PATH . '/config.php'); - } - - return $ok; -} - -/*** AFFICHAGE ***/ -function printStep0 () { - global $actual; -?> - -

- - -
- -
- -
- -
-
- -
-
- - - - - -
-
-
- - - - -

- -

- - - -

- -

- - - -

- -

- - - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - -

- -

- - - - - -

- - - -

- - -
- - -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- - -
-
- -
- -
- - -
-
- -
-
- - - - - -
-
-
- - -

- -

- - -
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
-
- - - - - -
-
-
- -
- - - -

- -
-
- - -
-
- - -

- -
-
- -
-
- -
- -

- - -

- - - - - - - <?php echo _t ('freshrss_installation'); ?> - - - - - -
-
-

-

-
-
- -
- - -
- -
-
- - -- cgit v1.2.3