From 878e96202e8a22e4857b98e29b0a1fce68eccbc9 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 15 Dec 2013 03:30:24 +0100 Subject: Grosse refactorisation pour permettre le chargement automatique des classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C'est parti de changements pour https://github.com/marienfressinaud/FreshRSS/issues/255 et finalement j'ai continué la refactorisation... Ajout de préfixes FreshRSS_ et Minz_ sur le modèle de SimplePie_. Toutes les classes sont maintenant en chargement automatique (devrait améliorer les performances en évitant de charger plein de classes inutilisées, et faciliter la maintenance). Suppression de set_include_path(). Si souhaité, certaines classes de Minz pourraient être déplacées dans un sous-répertoire, par exemple les exceptions. Tests et relecture nécessaires. --- lib/Minz/ModelPdo.php | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 lib/Minz/ModelPdo.php (limited to 'lib/Minz/ModelPdo.php') diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php new file mode 100644 index 000000000..9655539b2 --- /dev/null +++ b/lib/Minz/ModelPdo.php @@ -0,0 +1,111 @@ + +*/ + +/** + * La classe Model_sql représente le modèle interragissant avec les bases de données + * Seul la connexion MySQL est prise en charge pour le moment + */ +class Minz_ModelPdo { + + /** + * Partage la connexion à la base de données entre toutes les instances. + */ + public static $useSharedBd = true; + private static $sharedBd = null; + private static $sharedPrefix; + + /** + * $bd variable représentant la base de données + */ + protected $bd; + + protected $prefix; + + /** + * Créé la connexion à la base de données à l'aide des variables + * HOST, BASE, USER et PASS définies dans le fichier de configuration + */ + public function __construct () { + if (self::$useSharedBd && self::$sharedBd != null) { + $this->bd = self::$sharedBd; + $this->prefix = self::$sharedPrefix; + return; + } + + $db = Minz_Configuration::dataBase (); + $driver_options = null; + + try { + $type = $db['type']; + if($type == 'mysql') { + $string = $type + . ':host=' . $db['host'] + . ';dbname=' . $db['base'] + . ';charset=utf8'; + $driver_options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8' + ); + } elseif($type == 'sqlite') { + $string = $type . ':/' . DATA_PATH . $db['base'] . '.sqlite'; //TODO: DEBUG UTF-8 http://www.siteduzero.com/forum/sujet/sqlite-connexion-utf-8-18797 + } + + $this->bd = new FreshPDO ( + $string, + $db['user'], + $db['password'], + $driver_options + ); + self::$sharedBd = $this->bd; + + $userPrefix = Minz_Configuration::currentUser (); + $this->prefix = $db['prefix'] . (empty($userPrefix) ? '' : ($userPrefix . '_')); + self::$sharedPrefix = $this->prefix; + } catch (Exception $e) { + throw new Minz_PDOConnectionException ( + $string, + $db['user'], Minz_Exception::ERROR + ); + } + } + + public function beginTransaction() { + $this->bd->beginTransaction(); + } + public function commit() { + $this->bd->commit(); + } + public function rollBack() { + $this->bd->rollBack(); + } + + public function size() { + $db = Minz_Configuration::dataBase (); + $sql = 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = ?'; + $stm = $this->bd->prepare ($sql); + $values = array ($db['base']); + $stm->execute ($values); + $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); + return $res[0]; + } +} + +class FreshPDO extends PDO { + private static function check($statement) { + if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { + invalidateHttpCache(); + } + } + + public function prepare ($statement, $driver_options = array()) { + FreshPDO::check($statement); + return parent::prepare($statement, $driver_options); + } + + public function exec ($statement) { + FreshPDO::check($statement); + return parent::exec($statement); + } +} -- cgit v1.2.3 From bd5d7a7bcb16cff1c01f4445ceee765fc11e3b50 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 30 Dec 2013 15:00:41 +0100 Subject: Cache HTTP compatible multi-utilisateur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contribue à https://github.com/marienfressinaud/FreshRSS/issues/126 --- app/Controllers/configureController.php | 2 +- app/Controllers/indexController.php | 4 +-- app/FreshRSS.php | 51 ++++++++++++++++++++++++--------- app/Models/LogDAO.php | 8 ++++-- app/actualize_script.php | 12 +++++--- app/views/configure/users.phtml | 6 ++-- lib/Minz/Configuration.php | 13 ++------- lib/Minz/Log.php | 2 +- lib/Minz/ModelPdo.php | 3 +- lib/Minz/Session.php | 10 ++----- lib/lib_rss.php | 9 ++---- p/i/index.php | 13 +++++---- 12 files changed, 73 insertions(+), 60 deletions(-) (limited to 'lib/Minz/ModelPdo.php') diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 656e2ac89..2260e978b 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -322,7 +322,7 @@ class FreshRSS_configure_Controller extends Minz_ActionController { Minz_Session::_param('mail', $this->view->conf->mail_login); - if (Minz_Configuration::isAdmin()) { + if (Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { $anon = Minz_Request::param('anon_access', false); $anon = ((bool)$anon) && ($anon !== 'no'); $auth_type = Minz_Request::param('auth_type', 'none'); diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index cc851a1fa..7309169a6 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -218,10 +218,10 @@ class FreshRSS_index_Controller extends Minz_ActionController { Minz_View::prependTitle (Minz_Translate::t ('logs') . ' - '); if (Minz_Request::isPost ()) { - file_put_contents(LOG_PATH . '/' . Minz_Configuration::currentUser() . '.log', ''); //Truncate + FreshRSS_LogDAO::truncate(); } - $logs = FreshRSS_LogDAO::lines(Minz_Configuration::currentUser()); //TODO: ask only the necessary lines + $logs = FreshRSS_LogDAO::lines(); //TODO: ask only the necessary lines //gestion pagination $page = Minz_Request::param ('page', 1); diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 10f362717..0e166cc3b 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -1,22 +1,24 @@ accessControl($currentUser); + public function init() { + if (!isset($_SESSION)) { + Minz_Session::init('FreshRSS'); + } + $this->accessControl(Minz_Session::param('currentUser', '')); $this->loadParamsView(); $this->loadStylesAndScripts(); $this->loadNotifications(); } private function accessControl($currentUser) { - if ($currentUser === null) { + if ($currentUser == '') { switch (Minz_Configuration::authType()) { case 'http_auth': $currentUser = httpAuthUser(); $loginOk = $currentUser != ''; break; case 'persona': - $currentUser = Minz_Configuration::defaultUser(); + $currentUser = Minz_Configuration::defaultUser(); //TODO: Make Persona compatible with multi-user $loginOk = Minz_Session::param('mail') != ''; break; case 'none': @@ -24,28 +26,49 @@ class FreshRSS extends Minz_FrontController { $loginOk = true; break; default: + $currentUser = Minz_Configuration::defaultUser(); $loginOk = false; break; } - } elseif ((PHP_SAPI === 'cli') && (Minz_Request::actionName() === 'actualize')) { //Command line - Minz_Configuration::_authType('none'); + } else { $loginOk = true; } - if (!$loginOk || !isValidUser($currentUser)) { - $currentUser = Minz_Configuration::defaultUser(); - $loginOk = false; + if (!ctype_alnum($currentUser)) { + Minz_Session::_param('currentUser', ''); + die('Invalid username [' . $currentUser . ']!'); } - Minz_Configuration::_currentUser($currentUser); - Minz_View::_param ('loginOk', $loginOk); try { $this->conf = new FreshRSS_Configuration($currentUser); } catch (Minz_Exception $e) { - // Permission denied or conf file does not exist - die($e->getMessage()); + Minz_Session::_param('currentUser', ''); + die('Invalid configuration for user [' . $currentUser . ']! ' . $e->getMessage()); //Permission denied or conf file does not exist } Minz_View::_param ('conf', $this->conf); + Minz_Session::_param('currentUser', $currentUser); + + if ($loginOk) { + switch (Minz_Configuration::authType()) { + case 'http_auth': + $loginOk = $currentUser === httpAuthUser(); + break; + case 'persona': + $loginOk = Minz_Session::param('mail') === $this->conf->mail_login; + break; + case 'none': + $loginOk = true; + break; + default: + $loginOk = false; + break; + } + if ((!$loginOk) && (PHP_SAPI === 'cli') && (Minz_Request::actionName() === 'actualize')) { //Command line + Minz_Configuration::_authType('none'); + $loginOk = true; + } + } + Minz_View::_param ('loginOk', $loginOk); } private function loadParamsView () { diff --git a/app/Models/LogDAO.php b/app/Models/LogDAO.php index 6205468bd..d1e515200 100644 --- a/app/Models/LogDAO.php +++ b/app/Models/LogDAO.php @@ -1,9 +1,9 @@ init($user); - $front_controller->run(); - invalidateHttpCache($user); + Minz_Session::init('FreshRSS'); + Minz_Session::_param('currentUser', $user); + $freshRSS->init(); + $freshRSS->run(); + //invalidateHttpCache(); + touch(LOG_PATH . '/' . $user . '.log'); + Minz_Session::unset_session(true); } diff --git a/app/views/configure/users.phtml b/app/views/configure/users.phtml index db57448f6..cb6579a6b 100644 --- a/app/views/configure/users.phtml +++ b/app/views/configure/users.phtml @@ -9,10 +9,10 @@
- + $_SERVER['REMOTE_USER'] =
@@ -34,7 +34,7 @@
- + diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index e6d7ae471..1513af6d0 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -51,7 +51,6 @@ class Minz_Configuration { private static $cache_enabled = false; private static $delay_cache = 3600; private static $default_user = ''; - private static $current_user = ''; private static $allow_anonymous = false; private static $auth_type = 'none'; @@ -95,11 +94,8 @@ class Minz_Configuration { public static function defaultUser () { return self::$default_user; } - public static function currentUser () { - return self::$current_user; - } - public static function isAdmin () { - return self::$current_user === self::$default_user; + public static function isAdmin($currentUser) { + return $currentUser === self::$default_user; } public static function allowAnonymous() { return self::$allow_anonymous; @@ -127,10 +123,6 @@ class Minz_Configuration { break; } } - public static function _currentUser($user) { - self::$current_user = $user; - } - /** * Initialise les variables de configuration @@ -255,7 +247,6 @@ class Minz_Configuration { } if (isset ($general['default_user'])) { self::$default_user = $general['default_user']; - self::$current_user = self::$default_user; } if (isset ($general['allow_anonymous'])) { self::$allow_anonymous = ((bool)($general['allow_anonymous'])) && ($general['allow_anonymous'] !== 'no'); diff --git a/lib/Minz/Log.php b/lib/Minz/Log.php index 968301c81..e710aad4a 100644 --- a/lib/Minz/Log.php +++ b/lib/Minz/Log.php @@ -37,7 +37,7 @@ class Minz_Log { || ($env === Minz_Configuration::PRODUCTION && ($level >= Minz_Log::NOTICE)))) { if ($file_name === null) { - $file_name = LOG_PATH . '/' . Minz_Configuration::currentUser() . '.log'; + $file_name = LOG_PATH . '/' . Minz_Session::param('currentUser', '_') . '.log'; } switch ($level) { diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index 9655539b2..1ea68e104 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -60,8 +60,7 @@ class Minz_ModelPdo { ); self::$sharedBd = $this->bd; - $userPrefix = Minz_Configuration::currentUser (); - $this->prefix = $db['prefix'] . (empty($userPrefix) ? '' : ($userPrefix . '_')); + $this->prefix = $db['prefix'] . Minz_Session::param('currentUser', '_') . '_'; self::$sharedPrefix = $this->prefix; } catch (Exception $e) { throw new Minz_PDOConnectionException ( diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index 6e45fd226..3f6ed88a3 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -8,7 +8,7 @@ class Minz_Session { /** * $session stocke les variables de session */ - private static $session = array (); + private static $session = array (); //TODO: Try to avoid having another local copy /** * Initialise la session, avec un nom @@ -33,13 +33,7 @@ class Minz_Session { * @return la valeur de la variable de session, false si n'existe pas */ public static function param ($p, $default = false) { - if (isset (self::$session[$p])) { - $return = self::$session[$p]; - } else { - $return = $default; - } - - return $return; + return isset(self::$session[$p]) ? self::$session[$p] : $default; } diff --git a/lib/lib_rss.php b/lib/lib_rss.php index b266fa5c7..7489f2bf5 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -163,8 +163,9 @@ function uSecString() { return str_pad($t['usec'], 6, '0'); } -function invalidateHttpCache($currentUser = '') { //TODO: Make multi-user compatible - file_put_contents(DATA_PATH . '/touch.txt', uTimeString()); +function invalidateHttpCache() { + //touch(LOG_PATH . '/' . Minz_Session::param('currentUser', '_') . '.log'); + Minz_Session::_param('touch', uTimeString()); } function usernameFromPath($userPath) { @@ -175,10 +176,6 @@ function usernameFromPath($userPath) { } } -function isValidUser($user) { - return $user != '' && ctype_alnum($user) && file_exists(DATA_PATH . '/' . $user . '_user.php'); -} - function listUsers() { return array_map('usernameFromPath', glob(DATA_PATH . '/*_user.php')); } diff --git a/p/i/index.php b/p/i/index.php index 8d9343a30..3dcf659c9 100755 --- a/p/i/index.php +++ b/p/i/index.php @@ -22,22 +22,23 @@ if (file_exists ('install.php')) { require('install.php'); } else { require('../../constants.php'); + require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader session_cache_limiter(''); + Minz_Session::init('FreshRSS'); + if (!file_exists(DATA_PATH . '/no-cache.txt')) { - require (LIB_PATH . '/http-conditional.php'); - $dateLastModification = max( - @filemtime(DATA_PATH . '/touch.txt'), + require(LIB_PATH . '/http-conditional.php'); + $currentUser = Minz_Session::param('currentUser', ''); + $dateLastModification = $currentUser === '' ? time() : max( + @filemtime(LOG_PATH . '/' . $currentUser . '.log'), @filemtime(DATA_PATH . '/config.php') ); - $_SERVER['QUERY_STRING'] .= '&utime=' . file_get_contents(DATA_PATH . '/touch.txt'); //For ETag if (httpConditional($dateLastModification, 0, 0, false, false, true)) { exit(); //No need to send anything } } - require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader - try { $front_controller = new FreshRSS(); $front_controller->init (); -- cgit v1.2.3 From 1ac09e7fe4a5408290d06116c6fb8152e018fe26 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 31 Dec 2013 02:59:07 +0100 Subject: Multi-utilisateur fonctionnel en HTTP Auth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + Possibilité d'ajout / suppression d'utilisateur (seulement par l'administrateur) + Divers changements pour le mode multi-utilisateur https://github.com/marienfressinaud/FreshRSS/issues/126 + Minz : Renomme "sel_application" en "salt' --- app/Controllers/configureController.php | 41 ++-------- app/Controllers/entryController.php | 28 +++---- app/Controllers/usersController.php | 132 ++++++++++++++++++++++++++++++++ app/Models/UserDAO.php | 33 ++++++++ app/i18n/en.php | 7 +- app/i18n/fr.php | 7 +- app/sql.php | 20 ++--- app/views/configure/archiving.phtml | 23 ++++-- app/views/configure/users.phtml | 91 ++++++++++++++++++---- lib/Minz/Configuration.php | 53 +++++++------ lib/Minz/FileNotExistException.php | 2 +- lib/Minz/ModelPdo.php | 12 ++- p/i/install.php | 48 ++++-------- 13 files changed, 353 insertions(+), 144 deletions(-) create mode 100644 app/Controllers/usersController.php create mode 100644 app/Models/UserDAO.php (limited to 'lib/Minz/ModelPdo.php') diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 2260e978b..17abf6b89 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -309,41 +309,6 @@ class FreshRSS_configure_Controller extends Minz_ActionController { } public function usersAction() { - if (Minz_Request::isPost()) { - $ok = true; - $current_token = $this->view->conf->token; - - $mail = Minz_Request::param('mail_login', false); - $token = Minz_Request::param('token', $current_token); - - $this->view->conf->_mail_login($mail); - $this->view->conf->_token($token); - $ok &= $this->view->conf->save(); - - Minz_Session::_param('mail', $this->view->conf->mail_login); - - if (Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { - $anon = Minz_Request::param('anon_access', false); - $anon = ((bool)$anon) && ($anon !== 'no'); - $auth_type = Minz_Request::param('auth_type', 'none'); - if ($anon != Minz_Configuration::allowAnonymous() || - $auth_type != Minz_Configuration::authType()) { - Minz_Configuration::_allowAnonymous($anon); - Minz_Configuration::_authType($auth_type); - $ok &= Minz_Configuration::writeFile(); - } - } - - //TODO: use $ok - $notif = array( - 'type' => 'good', - 'content' => Minz_Translate::t('configuration_updated') - ); - Minz_Session::_param('notification', $notif); - - Minz_Request::forward(array('c' => 'configure', 'a' => 'users'), true); - } - Minz_View::prependTitle(Minz_Translate::t ('users') . ' - '); } @@ -369,6 +334,10 @@ class FreshRSS_configure_Controller extends Minz_ActionController { $entryDAO = new FreshRSS_EntryDAO(); $this->view->nb_total = $entryDAO->count(); - $this->view->size_total = $entryDAO->size(); + $this->view->size_user = $entryDAO->size(); + + if (Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { + $this->view->size_total = $entryDAO->size(true); + } } } diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index da4ab5ecc..a24dfe6d6 100755 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -16,6 +16,7 @@ class FreshRSS_entry_Controller extends Minz_ActionController { $this->view->_useLayout (false); } } + public function lastAction () { $ajax = Minz_Request::param ('ajax'); if (!$ajax && $this->redirect) { @@ -87,22 +88,23 @@ class FreshRSS_entry_Controller extends Minz_ActionController { } public function optimizeAction() { - @set_time_limit(300); - invalidateHttpCache(); + if (Minz_Request::isPost()) { + @set_time_limit(300); - // La table des entrées a tendance à grossir énormément - // Cette action permet d'optimiser cette table permettant de grapiller un peu de place - // Cette fonctionnalité n'est à appeler qu'occasionnellement - $entryDAO = new FreshRSS_EntryDAO(); - $entryDAO->optimizeTable(); + // La table des entrées a tendance à grossir énormément + // Cette action permet d'optimiser cette table permettant de grapiller un peu de place + // Cette fonctionnalité n'est à appeler qu'occasionnellement + $entryDAO = new FreshRSS_EntryDAO(); + $entryDAO->optimizeTable(); - invalidateHttpCache(); + invalidateHttpCache(); - $notif = array ( - 'type' => 'good', - 'content' => Minz_Translate::t ('optimization_complete') - ); - Minz_Session::_param ('notification', $notif); + $notif = array ( + 'type' => 'good', + 'content' => Minz_Translate::t ('optimization_complete') + ); + Minz_Session::_param ('notification', $notif); + } Minz_Request::forward(array( 'c' => 'configure', diff --git a/app/Controllers/usersController.php b/app/Controllers/usersController.php new file mode 100644 index 000000000..7d9568083 --- /dev/null +++ b/app/Controllers/usersController.php @@ -0,0 +1,132 @@ +view->loginOk) { + Minz_Error::error( + 403, + array('error' => array(Minz_Translate::t('access_denied'))) + ); + } + } + + public function idAction() { + if (Minz_Request::isPost()) { + $ok = true; + $mail = Minz_Request::param('mail_login', false); + $this->view->conf->_mail_login($mail); + $ok &= $this->view->conf->save(); + + Minz_Session::_param('mail', $this->view->conf->mail_login); + + //TODO: use $ok + $notif = array( + 'type' => 'good', + 'content' => Minz_Translate::t('configuration_updated') + ); + Minz_Session::_param('notification', $notif); + + Minz_Request::forward(array('c' => 'configure', 'a' => 'users'), true); + } + } + + public function authAction() { + if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { + $ok = true; + $current_token = $this->view->conf->token; + $token = Minz_Request::param('token', $current_token); + $this->view->conf->_token($token); + $ok &= $this->view->conf->save(); + + Minz_Session::_param('mail', $this->view->conf->mail_login); + + $anon = Minz_Request::param('anon_access', false); + $anon = ((bool)$anon) && ($anon !== 'no'); + $auth_type = Minz_Request::param('auth_type', 'none'); + if ($anon != Minz_Configuration::allowAnonymous() || + $auth_type != Minz_Configuration::authType()) { + Minz_Configuration::_allowAnonymous($anon); + Minz_Configuration::_authType($auth_type); + $ok &= Minz_Configuration::writeFile(); + } + + $notif = array( + 'type' => $ok ? 'good' : 'bad', + 'content' => Minz_Translate::t($ok ? 'configuration_updated' : 'error_occurred') + ); + Minz_Session::_param('notification', $notif); + } + Minz_Request::forward(array('c' => 'configure', 'a' => 'users'), true); + } + + public function createAction() { + if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { + require_once(APP_PATH . '/sql.php'); + + $new_user_language = Minz_Request::param('new_user_language', $this->view->conf->language); + if (!in_array($new_user_language, $this->view->conf->availableLanguages())) { + $new_user_language = $this->view->conf->language; + } + + $new_user_name = Minz_Request::param('new_user_name'); + $ok = ctype_alnum($new_user_name); + + $new_user_email = filter_var($_POST['new_user_email'], FILTER_VALIDATE_EMAIL); + if (empty($new_user_email)) { + $new_user_email = ''; + $ok &= Minz_Configuration::authType() !== 'persona'; + } + + if ($ok) { + $configPath = DATA_PATH . '/' . $new_user_name . '_user.php'; + $ok &= !file_exists($configPath); + } + if ($ok) { + $config_array = array( + 'language' => $new_user_language, + 'mail_login' => $new_user_email, + ); + $ok &= (file_put_contents($configPath, "createUser($new_user_name); + } + + $notif = array( + 'type' => $ok ? 'good' : 'bad', + 'content' => Minz_Translate::t($ok ? 'user_created' : 'error_occurred', $new_user_name) + ); + Minz_Session::_param('notification', $notif); + } + Minz_Request::forward(array('c' => 'configure', 'a' => 'users'), true); + } + + public function deleteAction() { + if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { + require_once(APP_PATH . '/sql.php'); + + $username = Minz_Request::param('username'); + $ok = ctype_alnum($username); + + if ($ok) { + $ok &= ($username !== Minz_Configuration::defaultUser()); //It is forbidden to delete the default user + } + if ($ok) { + $configPath = DATA_PATH . '/' . $username . '_user.php'; + $ok &= file_exists($configPath); + } + if ($ok) { + $userDAO = new FreshRSS_UserDAO(); + $ok &= $userDAO->deleteUser($username); + $ok &= unlink($configPath); + } + $notif = array( + 'type' => $ok ? 'good' : 'bad', + 'content' => Minz_Translate::t($ok ? 'user_deleted' : 'error_occurred', $username) + ); + Minz_Session::_param('notification', $notif); + } + Minz_Request::forward(array('c' => 'configure', 'a' => 'users'), true); + } +} diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php new file mode 100644 index 000000000..afa049fb9 --- /dev/null +++ b/app/Models/UserDAO.php @@ -0,0 +1,33 @@ +bd->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true)); + if ($stm && $stm->execute()) { + return true; + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } + + public function deleteUser($username) { + require_once(APP_PATH . '/sql.php'); + $db = Minz_Configuration::dataBase(); + + $sql = sprintf(SQL_DROP_TABLES, $db['prefix'] . $username . '_'); + $stm = $this->bd->prepare($sql); + if ($stm && $stm->execute()) { + return true; + } else { + $info = $stm->errorInfo(); + Minz_Log::record ('SQL error : ' . $info[2], Minz_Log::ERROR); + return false; + } + } +} diff --git a/app/i18n/en.php b/app/i18n/en.php index 8b9eee548..28aa1296a 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -137,7 +137,7 @@ return array ( 'articles' => 'articles', 'number_articles' => 'Number of articles', 'by_feed' => 'by feed', - 'by_default' => 'By default', + 'by_default' => 'By default', 'keep_history' => 'Minimum number of articles to keep', 'categorize' => 'Store in a category', 'truncate' => 'Delete all articles', @@ -167,6 +167,11 @@ return array ( 'auth_type' => 'Authentication method', 'auth_none' => 'None (dangerous)', 'users_list' => 'List of users', + 'create_user' => 'Create new user', + 'username' => 'Username', + 'create' => 'Create', + 'user_created' => 'User %s has been created', + 'user_deleted' => 'User %s has been deleted', 'language' => 'Language', 'month' => 'months', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index cad156d47..39aeaf29a 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -137,7 +137,7 @@ return array ( 'articles' => 'articles', 'number_articles' => 'Nombre d’articles', 'by_feed' => 'par flux', - 'by_default' => 'Par défaut', + 'by_default' => 'Par défaut', 'keep_history' => 'Nombre minimum d’articles à conserver', 'categorize' => 'Ranger dans une catégorie', 'truncate' => 'Supprimer tous les articles', @@ -167,6 +167,11 @@ return array ( 'auth_type' => 'Méthode d’authentification', 'auth_none' => 'Aucune (dangereux)', 'users_list' => 'Liste des utilisateurs', + 'create_user' => 'Créer un nouvel utilisateur', + 'username' => 'Nom d’utilisateur', + 'create' => 'Créer', + 'user_created' => 'L’utilisateur %s a été créé', + 'user_deleted' => 'L’utilisateur %s a été supprimé', 'language' => 'Langue', 'month' => 'mois', diff --git a/app/sql.php b/app/sql.php index 6951d7231..8646b4da5 100644 --- a/app/sql.php +++ b/app/sql.php @@ -1,16 +1,15 @@ ">

- +
@@ -31,17 +31,28 @@
+ +
+
- +

-

nb_total; ?> , size_total); ?>.

-

- -

+

nb_total, ' ', Minz_Translate::t('articles'), ', ', formatBytes($this->size_user); ?>

+ +
+ + +
+

+
+

size_total); ?>

+
+
+
diff --git a/app/views/configure/users.phtml b/app/views/configure/users.phtml index cb6579a6b..223f81e8d 100644 --- a/app/views/configure/users.phtml +++ b/app/views/configure/users.phtml @@ -3,16 +3,15 @@
-
+
- $_SERVER['REMOTE_USER'] =
@@ -22,21 +21,25 @@ conf->mail_login; ?>
- + placeholder="alice@example.net" />
+
+ +
- + - +
+
@@ -46,17 +49,7 @@ -
-
- -
- -
- + $_SERVER['REMOTE_USER'] = ``
@@ -67,6 +60,8 @@ + + Mozilla Persona
@@ -95,4 +90,66 @@ + +
+ + +
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+ + +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ + conf->mail_login; ?> +
+ +
+
+ +
+
+ + +
+
+ +
+ +
diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php index 1513af6d0..873908ce6 100644 --- a/lib/Minz/Configuration.php +++ b/lib/Minz/Configuration.php @@ -28,7 +28,7 @@ class Minz_Configuration { /** * définition des variables de configuration - * $sel_application une chaîne de caractères aléatoires (obligatoire) + * $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 @@ -42,7 +42,7 @@ class Minz_Configuration { * - password mot de passe de l'utilisateur * - base le nom de la base de données */ - private static $sel_application = ''; + private static $salt = ''; private static $environment = Minz_Configuration::PRODUCTION; private static $base_url = ''; private static $use_url_rewriting = false; @@ -55,17 +55,19 @@ class Minz_Configuration { private static $auth_type = 'none'; private static $db = array ( - 'host' => false, - 'user' => false, - 'password' => false, - 'base' => false + 'type' => 'mysql', + 'host' => '', + 'user' => '', + 'password' => '', + 'base' => '', + 'prefix' => '', ); /* * Getteurs */ public static function salt () { - return self::$sel_application; + return self::$salt; } public static function environment () { return self::$environment; @@ -145,7 +147,7 @@ class Minz_Configuration { 'general' => array( 'environment' => self::$environment, 'use_url_rewriting' => self::$use_url_rewriting, - 'sel_application' => self::$sel_application, + 'salt' => self::$salt, 'base_url' => self::$base_url, 'title' => self::$title, 'default_user' => self::$default_user, @@ -189,14 +191,18 @@ class Minz_Configuration { } $general = $ini_array['general']; - // sel_application est obligatoire - if (!isset ($general['sel_application'])) { - throw new Minz_BadConfigurationException ( - 'sel_application', - Minz_Exception::ERROR - ); + // salt est obligatoire + if (!isset ($general['salt'])) { + if (isset($general['sel_application'])) { //v0.6 + $general['salt'] = $general['sel_application']; + } else { + throw new Minz_BadConfigurationException ( + 'salt', + Minz_Exception::ERROR + ); + } } - self::$sel_application = $general['sel_application']; + self::$salt = $general['salt']; if (isset ($general['environment'])) { switch ($general['environment']) { @@ -256,18 +262,15 @@ class Minz_Configuration { } // Base de données - $db = false; if (isset ($ini_array['db'])) { $db = $ini_array['db']; - } - if ($db) { - if (!isset ($db['host'])) { + if (empty($db['host'])) { throw new Minz_BadConfigurationException ( 'host', Minz_Exception::ERROR ); } - if (!isset ($db['user'])) { + if (empty($db['user'])) { throw new Minz_BadConfigurationException ( 'user', Minz_Exception::ERROR @@ -279,19 +282,23 @@ class Minz_Configuration { Minz_Exception::ERROR ); } - if (!isset ($db['base'])) { + if (empty($db['base'])) { throw new Minz_BadConfigurationException ( 'base', Minz_Exception::ERROR ); } - self::$db['type'] = isset ($db['type']) ? $db['type'] : 'mysql'; + if (!empty($db['type'])) { + self::$db['type'] = $db['type']; + } self::$db['host'] = $db['host']; self::$db['user'] = $db['user']; self::$db['password'] = $db['password']; self::$db['base'] = $db['base']; - self::$db['prefix'] = isset ($db['prefix']) ? $db['prefix'] : ''; + if (isset($db['prefix'])) { + self::$db['prefix'] = $db['prefix']; + } } } diff --git a/lib/Minz/FileNotExistException.php b/lib/Minz/FileNotExistException.php index df2b8ff6c..f8dfbdf66 100644 --- a/lib/Minz/FileNotExistException.php +++ b/lib/Minz/FileNotExistException.php @@ -1,7 +1,7 @@ */ @@ -23,7 +23,7 @@ class Minz_ModelPdo { protected $bd; protected $prefix; - + /** * Créé la connexion à la base de données à l'aide des variables * HOST, BASE, USER et PASS définies dans le fichier de configuration @@ -80,11 +80,15 @@ class Minz_ModelPdo { $this->bd->rollBack(); } - public function size() { + public function size($all = false) { $db = Minz_Configuration::dataBase (); $sql = 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = ?'; - $stm = $this->bd->prepare ($sql); $values = array ($db['base']); + if (!$all) { + $sql .= ' AND table_name LIKE ?'; + $values[] = $this->prefix . '%'; + } + $stm = $this->bd->prepare ($sql); $stm->execute ($values); $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); return $res[0]; diff --git a/p/i/install.php b/p/i/install.php index 672f64b94..e953cf699 100644 --- a/p/i/install.php +++ b/p/i/install.php @@ -12,6 +12,8 @@ if (isset ($_GET['step'])) { define ('STEP', 1); } +define('SQL_CREATE_DB', 'CREATE DATABASE %1$s DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;'); + include(APP_PATH . '/sql.php'); // @@ -151,7 +153,7 @@ function saveStep2 () { return false; } - $_SESSION['sel_application'] = sha1(uniqid(mt_rand(), true).implode('', stat(__FILE__))); + $_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)) { @@ -162,7 +164,7 @@ function saveStep2 () { $token = ''; if ($_SESSION['mail_login']) { - $token = sha1($_SESSION['sel_application'] . $_SESSION['mail_login']); + $token = sha1($_SESSION['salt'] . $_SESSION['mail_login']); } $config_array = array ( @@ -173,7 +175,7 @@ function saveStep2 () { ); $configPath = DATA_PATH . '/' . $_SESSION['default_user'] . '_user.php'; - @unlink(configPath); //To avoid access-rights problems + @unlink($configPath); //To avoid access-rights problems file_put_contents($configPath, " array( 'environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], 'use_url_rewriting' => false, - 'sel_application' => $_SESSION['sel_application'], + 'salt' => $_SESSION['salt'], 'base_url' => '', 'title' => $_SESSION['title'], 'default_user' => $_SESSION['default_user'], @@ -424,7 +426,7 @@ function checkStep0 () { if ($ini_array) { $ini_general = isset($ini_array['general']) ? $ini_array['general'] : null; if ($ini_general) { - $keys = array('environment', 'sel_application', 'title', 'default_user'); + $keys = array('environment', 'salt', 'title', 'default_user'); foreach ($keys as $key) { if ((empty($_SESSION[$key])) && isset($ini_general[$key])) { $_SESSION[$key] = $ini_general[$key]; @@ -496,7 +498,7 @@ function checkStep1 () { } function checkStep2 () { - $conf = !empty($_SESSION['sel_application']) && + $conf = !empty($_SESSION['salt']) && !empty($_SESSION['title']) && !empty($_SESSION['old_entries']) && isset($_SESSION['mail_login']) && @@ -537,7 +539,7 @@ function checkStep3 () { } function checkBD () { - $error = false; + $ok = false; try { $str = ''; @@ -575,35 +577,18 @@ function checkBD () { $res = $c->query($sql); //Backup tables } - $sql = sprintf (SQL_CAT, $_SESSION['bd_prefix_user']); - $res = $c->query ($sql); - - if (!$res) { - $error = true; - } - - $sql = sprintf (SQL_FEED, $_SESSION['bd_prefix_user']); - $res = $c->query ($sql); - - if (!$res) { - $error = true; - } - - $sql = sprintf (SQL_ENTRY, $_SESSION['bd_prefix_user']); - $res = $c->query ($sql); - - if (!$res) { - $error = true; - } + $sql = sprintf(SQL_CREATE_TABLES, $_SESSION['bd_prefix_user']); + $stm = $c->prepare($sql, array(PDO::ATTR_EMULATE_PREPARES => true)); + $ok = $stm->execute(); } catch (PDOException $e) { $error = true; } - if ($error && file_exists (DATA_PATH . '/config.php')) { - unlink (DATA_PATH . '/config.php'); + if (!$ok) { + @unlink(DATA_PATH . '/config.php'); } - return !$error; + return $ok; } /*** AFFICHAGE ***/ @@ -729,9 +714,6 @@ function printStep2 () {
-
-- cgit v1.2.3 From b4c477ca41a7ecaa6364dd6a97603829b14b11ef Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 2 Jan 2014 01:47:03 +0100 Subject: actualize_script compatible multi-utilisateur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Messages plus verbeux dans actualize_script * Ajout d'un message syslog lorsque SimplePie fait une requête HTTP * Minz_Session ne fermait pas les sessions complètement. * Nouvelle option dans Minz_Dispatcher et Minz_FrontController pour ne pas utiliser ob_gzhandler. Contribue à https://github.com/marienfressinaud/FreshRSS/issues/126 --- app/actualize_script.php | 36 ++++++++++++++++++++++++++---------- app/views/feed/actualize.phtml | 2 +- lib/Minz/Dispatcher.php | 23 +++++++++++++++++------ lib/Minz/FrontController.php | 15 ++++++++++++++- lib/Minz/ModelPdo.php | 5 +++++ lib/Minz/Session.php | 2 +- lib/SimplePie/SimplePie/File.php | 1 + 7 files changed, 65 insertions(+), 19 deletions(-) (limited to 'lib/Minz/ModelPdo.php') diff --git a/app/actualize_script.php b/app/actualize_script.php index efe21fab6..e0f995afe 100755 --- a/app/actualize_script.php +++ b/app/actualize_script.php @@ -3,24 +3,40 @@ require(dirname(__FILE__) . '/../constants.php'); //TODO: check if already running -$_GET['c'] = 'feed'; -$_GET['a'] = 'actualize'; -$_GET['force'] = true; -$_SERVER['HTTP_HOST'] = ''; - require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader -$freshRSS = new FreshRSS (); +session_cache_limiter(''); +ob_implicit_flush(false); +ob_start(); +echo 'Results: ', "\n"; //Buffered $users = listUsers(); shuffle($users); -foreach ($users as $user) { +foreach ($users as $myUser) { + syslog(LOG_INFO, 'FreshRSS actualize ' . $myUser); + fwrite(STDOUT, 'Actualize ' . $myUser . "...\n"); //Unbuffered + echo $myUser, ' '; //Buffered + + $_GET['c'] = 'feed'; + $_GET['a'] = 'actualize'; + $_GET['ajax'] = 1; + $_GET['force'] = true; + $_SERVER['HTTP_HOST'] = ''; + + $freshRSS = new FreshRSS(); + $freshRSS->_useOb(false); + Minz_Session::init('FreshRSS'); - Minz_Session::_param('currentUser', $user); + Minz_Session::_param('currentUser', $myUser); + $freshRSS->init(); $freshRSS->run(); - //invalidateHttpCache(); - touch(LOG_PATH . '/' . $user . '.log'); + + invalidateHttpCache(); Minz_Session::unset_session(true); + Minz_ModelPdo::clean(); } +syslog(LOG_INFO, 'FreshRSS actualize done.'); +ob_end_flush(); +fwrite(STDOUT, 'Done.' . "\n"); diff --git a/app/views/feed/actualize.phtml b/app/views/feed/actualize.phtml index a0aba9318..d86bac9de 100644 --- a/app/views/feed/actualize.phtml +++ b/app/views/feed/actualize.phtml @@ -1 +1 @@ -OK \ No newline at end of file +OK diff --git a/lib/Minz/Dispatcher.php b/lib/Minz/Dispatcher.php index c2c5e7f65..71dfe8ac6 100644 --- a/lib/Minz/Dispatcher.php +++ b/lib/Minz/Dispatcher.php @@ -40,19 +40,26 @@ class Minz_Dispatcher { * Remplit le body de Response à partir de la Vue * @exception Minz_Exception */ - public function run () { + public function run ($ob = true) { $cache = new Minz_Cache(); // Le ob_start est dupliqué : sans ça il y a un bug sous Firefox // ici on l'appelle avec 'ob_gzhandler', après sans. // Vraisemblablement la compression fonctionne mais c'est sale // J'ignore les effets de bord :( - ob_start ('ob_gzhandler'); + if ($ob) { + ob_start ('ob_gzhandler'); + } if (Minz_Cache::isEnabled () && !$cache->expired ()) { - ob_start (); + if ($ob) { + ob_start (); + } $cache->render (); - $text = ob_get_clean(); + if ($ob) { + $text = ob_get_clean(); + } } else { + $text = ''; //TODO: Clean this code while (Minz_Request::$reseted) { Minz_Request::$reseted = false; @@ -67,9 +74,13 @@ class Minz_Dispatcher { $this->controller->lastAction (); if (!Minz_Request::$reseted) { - ob_start (); + if ($ob) { + ob_start (); + } $this->controller->view ()->build (); - $text = ob_get_clean(); + if ($ob) { + $text = ob_get_clean(); + } } } catch (Minz_Exception $e) { throw $e; diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php index 8e9c511a6..7b8526bc8 100644 --- a/lib/Minz/FrontController.php +++ b/lib/Minz/FrontController.php @@ -26,6 +26,8 @@ class Minz_FrontController { protected $dispatcher; protected $router; + private $useOb = true; + /** * Constructeur * Initialise le router et le dispatcher @@ -61,7 +63,7 @@ class Minz_FrontController { */ public function run () { try { - $this->dispatcher->run (); + $this->dispatcher->run ($this->useOb); Minz_Response::send (); } catch (Minz_Exception $e) { try { @@ -94,4 +96,15 @@ class Minz_FrontController { } exit ('### Application problem ###
'."\n".$txt); } + + public function useOb() { + return $this->useOb; + } + + /** + * Use ob_start('ob_gzhandler') or not. + */ + public function _useOb($ob) { + return $this->useOb = (bool)$ob; + } } diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index a643da1f0..831df13a2 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -93,6 +93,11 @@ class Minz_ModelPdo { $res = $stm->fetchAll(PDO::FETCH_COLUMN, 0); return $res[0]; } + + public static function clean() { + self::$sharedBd = null; + self::$sharedPrefix = ''; + } } class FreshPDO extends PDO { diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index 3f6ed88a3..37faff0fb 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -60,7 +60,7 @@ class Minz_Session { public static function unset_session ($force = false) { $language = self::param ('language'); - session_unset (); + session_destroy(); self::$session = array (); if (!$force) { diff --git a/lib/SimplePie/SimplePie/File.php b/lib/SimplePie/SimplePie/File.php index 063ad955e..cf926cf5a 100644 --- a/lib/SimplePie/SimplePie/File.php +++ b/lib/SimplePie/SimplePie/File.php @@ -77,6 +77,7 @@ class SimplePie_File $this->useragent = $useragent; if (preg_match('/^http(s)?:\/\//i', $url)) { + syslog(LOG_INFO, 'SimplePie GET ' . $url); //FreshRSS if ($useragent === null) { $useragent = ini_get('user_agent'); -- cgit v1.2.3