diff options
| author | 2015-01-08 14:18:32 +0100 | |
|---|---|---|
| committer | 2015-01-08 14:18:32 +0100 | |
| commit | 73023bc12b81a27045703e1f733faeb2b4e02cec (patch) | |
| tree | 14aca1a1953d0a813c06794e48a63738abccdcea /app/Models | |
| parent | 26da4aa448906f857a252507b34d369a386043c6 (diff) | |
| parent | 0e4e16ac55097aa173c7c439367294ebd7645562 (diff) | |
Merge branch 'dev' into 252-extensions
Conflicts:
app/FreshRSS.php
app/Models/Configuration.php
app/views/index/index.phtml
app/views/index/normal.phtml
lib/Minz/Configuration.php
lib/Minz/Translate.php
lib/lib_rss.php
Diffstat (limited to 'app/Models')
| -rw-r--r-- | app/Models/Auth.php | 50 | ||||
| -rw-r--r-- | app/Models/Configuration.php | 365 | ||||
| -rw-r--r-- | app/Models/ConfigurationSetter.php | 368 | ||||
| -rw-r--r-- | app/Models/Context.php | 20 | ||||
| -rw-r--r-- | app/Models/EntryDAO.php | 2 | ||||
| -rw-r--r-- | app/Models/EntryDAOSQLite.php | 2 | ||||
| -rw-r--r-- | app/Models/Factory.php | 16 | ||||
| -rw-r--r-- | app/Models/Feed.php | 3 | ||||
| -rw-r--r-- | app/Models/LogDAO.php | 4 | ||||
| -rw-r--r-- | app/Models/Share.php | 232 | ||||
| -rw-r--r-- | app/Models/UserDAO.php | 12 |
11 files changed, 646 insertions, 428 deletions
diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 2971d65c8..4e7a71947 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -16,7 +16,8 @@ class FreshRSS_Auth { self::$login_ok = Minz_Session::param('loginOk', false); $current_user = Minz_Session::param('currentUser', ''); if ($current_user === '') { - $current_user = Minz_Configuration::defaultUser(); + $conf = Minz_Configuration::get('system'); + $current_user = $conf->default_user; Minz_Session::_param('currentUser', $current_user); } @@ -40,7 +41,9 @@ class FreshRSS_Auth { * @return boolean true if user can be connected, false else. */ private static function accessControl() { - switch (Minz_Configuration::authType()) { + $conf = Minz_Configuration::get('system'); + $auth_type = $conf->auth_type; + switch ($auth_type) { case 'form': $credentials = FreshRSS_FormAuth::getCredentialsFromCookie(); $current_user = ''; @@ -80,21 +83,18 @@ class FreshRSS_Auth { */ public static function giveAccess() { $current_user = Minz_Session::param('currentUser'); - try { - $conf = new FreshRSS_Configuration($current_user); - } catch(Minz_Exception $e) { - die($e->getMessage()); - } + $user_conf = get_user_configuration($current_user); + $system_conf = Minz_Configuration::get('system'); - switch (Minz_Configuration::authType()) { + switch ($system_conf->auth_type) { case 'form': - self::$login_ok = Minz_Session::param('passwordHash') === $conf->passwordHash; + self::$login_ok = Minz_Session::param('passwordHash') === $user_conf->passwordHash; break; case 'http_auth': self::$login_ok = strcasecmp($current_user, httpAuthUser()) === 0; break; case 'persona': - self::$login_ok = strcasecmp(Minz_Session::param('mail'), $conf->mail_login) === 0; + self::$login_ok = strcasecmp(Minz_Session::param('mail'), $user_conf->mail_login) === 0; break; case 'none': self::$login_ok = true; @@ -114,12 +114,14 @@ class FreshRSS_Auth { * @return boolean true if user has corresponding access, false else. */ public static function hasAccess($scope = 'general') { + $conf = Minz_Configuration::get('system'); + $default_user = $conf->default_user; $ok = self::$login_ok; switch ($scope) { case 'general': break; case 'admin': - $ok &= Minz_Session::param('currentUser') === Minz_Configuration::defaultUser(); + $ok &= Minz_Session::param('currentUser') === $default_user; break; default: $ok = false; @@ -133,9 +135,10 @@ class FreshRSS_Auth { public static function removeAccess() { Minz_Session::_param('loginOk'); self::$login_ok = false; - Minz_Session::_param('currentUser', Minz_Configuration::defaultUser()); + $conf = Minz_Configuration::get('system'); + Minz_Session::_param('currentUser', $conf->default_user); - switch (Minz_Configuration::authType()) { + switch ($conf->auth_type) { case 'form': Minz_Session::_param('passwordHash'); FreshRSS_FormAuth::deleteCookie(); @@ -151,6 +154,24 @@ class FreshRSS_Auth { // TODO: extensions } } + + /** + * Return if authentication is enabled on this instance of FRSS. + */ + public static function accessNeedsLogin() { + $conf = Minz_Configuration::get('system'); + $auth_type = $conf->auth_type; + return $auth_type !== 'none'; + } + + /** + * Return if authentication requires a PHP action. + */ + public static function accessNeedsAction() { + $conf = Minz_Configuration::get('system'); + $auth_type = $conf->auth_type; + return $auth_type === 'form' || $auth_type === 'persona'; + } } @@ -194,7 +215,8 @@ class FreshRSS_FormAuth { public static function makeCookie($username, $password_hash) { do { - $token = sha1(Minz_Configuration::salt() . $username . uniqid(mt_rand(), true)); + $conf = Minz_Configuration::get('system'); + $token = sha1($conf->salt . $username . uniqid(mt_rand(), true)); $token_file = DATA_PATH . '/tokens/' . $token . '.txt'; } while (file_exists($token_file)); diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php deleted file mode 100644 index 83a00d4bb..000000000 --- a/app/Models/Configuration.php +++ /dev/null @@ -1,365 +0,0 @@ -<?php - -class FreshRSS_Configuration { - private $filename; - - private $data = array( - 'language' => 'en', - 'old_entries' => 3, - 'keep_history_default' => 0, - 'ttl_default' => 3600, - 'mail_login' => '', - 'token' => '', - 'passwordHash' => '', //CRYPT_BLOWFISH - 'apiPasswordHash' => '', //CRYPT_BLOWFISH - 'posts_per_page' => 20, - 'view_mode' => 'normal', - 'default_view' => 'adaptive', - 'default_state' => FreshRSS_Entry::STATE_NOT_READ, - 'auto_load_more' => true, - 'display_posts' => false, - 'display_categories' => false, - 'hide_read_feeds' => true, - 'onread_jump_next' => true, - 'lazyload' => true, - 'sticky_post' => true, - 'reading_confirm' => false, - 'auto_remove_article' => false, - 'sort_order' => 'DESC', - 'anon_access' => false, - 'mark_when' => array( - 'article' => true, - 'site' => true, - 'scroll' => false, - 'reception' => false, - ), - 'theme' => 'Origine', - 'content_width' => 'thin', - 'shortcuts' => array( - 'mark_read' => 'r', - 'mark_favorite' => 'f', - 'go_website' => 'space', - 'next_entry' => 'j', - 'prev_entry' => 'k', - 'first_entry' => 'home', - 'last_entry' => 'end', - 'collapse_entry' => 'c', - 'load_more' => 'm', - 'auto_share' => 's', - 'focus_search' => 'a', - 'user_filter' => 'u', - 'help' => 'f1', - 'close_dropdown' => 'escape', - ), - 'topline_read' => true, - 'topline_favorite' => true, - 'topline_date' => true, - 'topline_link' => true, - 'bottomline_read' => true, - 'bottomline_favorite' => true, - 'bottomline_sharing' => true, - 'bottomline_tags' => true, - 'bottomline_date' => true, - 'bottomline_link' => true, - 'sharing' => array(), - 'queries' => array(), - 'html5_notif_timeout' => 0, - 'extensions_enabled' => array(), - ); - - private $available_languages = array( - 'en' => 'English', - 'fr' => 'Français', - ); - - private $shares; - - public function __construct($user) { - $this->filename = DATA_PATH . DIRECTORY_SEPARATOR . $user . '_user.php'; - - $data = @include($this->filename); - if (!is_array($data)) { - throw new Minz_PermissionDeniedException($this->filename); - } - - foreach ($data as $key => $value) { - if (isset($this->data[$key])) { - $function = '_' . $key; - $this->$function($value); - } - } - $this->data['user'] = $user; - - $this->shares = DATA_PATH . DIRECTORY_SEPARATOR . 'shares.php'; - - $shares = @include($this->shares); - if (!is_array($shares)) { - throw new Minz_PermissionDeniedException($this->shares); - } - - $this->data['shares'] = $shares; - } - - public function save() { - @rename($this->filename, $this->filename . '.bak.php'); - unset($this->data['shares']); // Remove shares because it is not intended to be stored in user configuration - if (file_put_contents($this->filename, "<?php\n return " . var_export($this->data, true) . ';', LOCK_EX) === false) { - throw new Minz_PermissionDeniedException($this->filename); - } - if (function_exists('opcache_invalidate')) { - opcache_invalidate($this->filename); //Clear PHP 5.5+ cache for include - } - invalidateHttpCache(); - return true; - } - - public function __get($name) { - if (array_key_exists($name, $this->data)) { - return $this->data[$name]; - } else { - $trace = debug_backtrace(); - trigger_error('Undefined FreshRSS_Configuration->' . $name . 'in ' . $trace[0]['file'] . ' line ' . $trace[0]['line'], E_USER_NOTICE); //TODO: Use Minz exceptions - return null; - } - } - - public function availableLanguages() { - return $this->available_languages; - } - - public function remove_query_by_get($get) { - $final_queries = array(); - foreach ($this->queries as $key => $query) { - if (empty($query['get']) || $query['get'] !== $get) { - $final_queries[$key] = $query; - } - } - $this->_queries($final_queries); - } - - public function _language($value) { - if (!isset($this->available_languages[$value])) { - $value = 'en'; - } - $this->data['language'] = $value; - } - public function _posts_per_page($value) { - $value = intval($value); - $this->data['posts_per_page'] = $value > 0 ? $value : 10; - } - public function _view_mode($value) { - if ($value === 'global' || $value === 'reader') { - $this->data['view_mode'] = $value; - } else { - $this->data['view_mode'] = 'normal'; - } - } - public function _default_view($value) { - switch ($value) { - case 'all': - $this->data['default_view'] = $value; - $this->data['default_state'] = (FreshRSS_Entry::STATE_READ + - FreshRSS_Entry::STATE_NOT_READ); - break; - case 'adaptive': - case 'unread': - default: - $this->data['default_view'] = $value; - $this->data['default_state'] = FreshRSS_Entry::STATE_NOT_READ; - } - } - public function _default_state($value) { - $this->data['default_state'] = (int)$value; - } - - public function _display_posts($value) { - $this->data['display_posts'] = ((bool)$value) && $value !== 'no'; - } - public function _display_categories($value) { - $this->data['display_categories'] = ((bool)$value) && $value !== 'no'; - } - public function _hide_read_feeds($value) { - $this->data['hide_read_feeds'] = (bool)$value; - } - public function _onread_jump_next($value) { - $this->data['onread_jump_next'] = ((bool)$value) && $value !== 'no'; - } - public function _lazyload($value) { - $this->data['lazyload'] = ((bool)$value) && $value !== 'no'; - } - public function _sticky_post($value) { - $this->data['sticky_post'] = ((bool)$value) && $value !== 'no'; - } - public function _reading_confirm($value) { - $this->data['reading_confirm'] = ((bool)$value) && $value !== 'no'; - } - public function _auto_remove_article($value) { - $this->data['auto_remove_article'] = ((bool)$value) && $value !== 'no'; - } - public function _sort_order($value) { - $this->data['sort_order'] = $value === 'ASC' ? 'ASC' : 'DESC'; - } - public function _old_entries($value) { - $value = intval($value); - $this->data['old_entries'] = $value > 0 ? $value : 3; - } - public function _keep_history_default($value) { - $value = intval($value); - $this->data['keep_history_default'] = $value >= -1 ? $value : 0; - } - public function _ttl_default($value) { - $value = intval($value); - $this->data['ttl_default'] = $value >= -1 ? $value : 3600; - } - public function _shortcuts($values) { - foreach ($values as $key => $value) { - if (isset($this->data['shortcuts'][$key])) { - $this->data['shortcuts'][$key] = $value; - } - } - } - public function _passwordHash($value) { - $this->data['passwordHash'] = ctype_graph($value) && (strlen($value) >= 60) ? $value : ''; - } - public function _apiPasswordHash($value) { - $this->data['apiPasswordHash'] = ctype_graph($value) && (strlen($value) >= 60) ? $value : ''; - } - public function _mail_login($value) { - $value = filter_var($value, FILTER_VALIDATE_EMAIL); - if ($value) { - $this->data['mail_login'] = $value; - } else { - $this->data['mail_login'] = ''; - } - } - public function _anon_access($value) { - $this->data['anon_access'] = ((bool)$value) && $value !== 'no'; - } - public function _mark_when($values) { - foreach ($values as $key => $value) { - if (isset($this->data['mark_when'][$key])) { - $this->data['mark_when'][$key] = ((bool)$value) && $value !== 'no'; - } - } - } - public function _sharing($values) { - $this->data['sharing'] = array(); - $unique = array(); - foreach ($values as $value) { - if (!is_array($value)) { - continue; - } - - // Verify URL and add default value when needed - if (isset($value['url'])) { - $is_url = ( - filter_var($value['url'], FILTER_VALIDATE_URL) || - (version_compare(PHP_VERSION, '5.3.3', '<') && - (strpos($value, '-') > 0) && - ($value === filter_var($value, FILTER_SANITIZE_URL))) - ); //PHP bug #51192 - if (!$is_url) { - continue; - } - } else { - $value['url'] = null; - } - - // Add a default name - if (empty($value['name'])) { - $value['name'] = $value['type']; - } - - $json_value = json_encode($value); - if (!in_array($json_value, $unique)) { - $unique[] = $json_value; - $this->data['sharing'][] = $value; - } - } - } - public function _queries($values) { - $this->data['queries'] = array(); - foreach ($values as $value) { - $value = array_filter($value); - $params = $value; - unset($params['name']); - unset($params['url']); - $value['url'] = Minz_Url::display(array('params' => $params)); - - $this->data['queries'][] = $value; - } - } - public function _theme($value) { - $this->data['theme'] = $value; - } - public function _content_width($value) { - if ($value === 'medium' || - $value === 'large' || - $value === 'no_limit') { - $this->data['content_width'] = $value; - } else { - $this->data['content_width'] = 'thin'; - } - } - - public function _html5_notif_timeout($value) { - $value = intval($value); - $this->data['html5_notif_timeout'] = $value >= 0 ? $value : 0; - } - - public function _token($value) { - $this->data['token'] = $value; - } - public function _auto_load_more($value) { - $this->data['auto_load_more'] = ((bool)$value) && $value !== 'no'; - } - public function _topline_read($value) { - $this->data['topline_read'] = ((bool)$value) && $value !== 'no'; - } - public function _topline_favorite($value) { - $this->data['topline_favorite'] = ((bool)$value) && $value !== 'no'; - } - public function _topline_date($value) { - $this->data['topline_date'] = ((bool)$value) && $value !== 'no'; - } - public function _topline_link($value) { - $this->data['topline_link'] = ((bool)$value) && $value !== 'no'; - } - public function _bottomline_read($value) { - $this->data['bottomline_read'] = ((bool)$value) && $value !== 'no'; - } - public function _bottomline_favorite($value) { - $this->data['bottomline_favorite'] = ((bool)$value) && $value !== 'no'; - } - public function _bottomline_sharing($value) { - $this->data['bottomline_sharing'] = ((bool)$value) && $value !== 'no'; - } - public function _bottomline_tags($value) { - $this->data['bottomline_tags'] = ((bool)$value) && $value !== 'no'; - } - public function _bottomline_date($value) { - $this->data['bottomline_date'] = ((bool)$value) && $value !== 'no'; - } - public function _bottomline_link($value) { - $this->data['bottomline_link'] = ((bool)$value) && $value !== 'no'; - } - - public function _extensions_enabled($value) { - if (!is_array($value)) { - $value = array($value); - } - $this->data['extensions_enabled'] = $value; - } - public function removeExtension($ext_name) { - $this->data['extensions_enabled'] = array_diff( - $this->data['extensions_enabled'], - array($ext_name) - ); - } - public function addExtension($ext_name) { - $found = array_search($ext_name, $this->data['extensions_enabled']) !== false; - if (!$found) { - $this->data['extensions_enabled'][] = $ext_name; - } - } -} diff --git a/app/Models/ConfigurationSetter.php b/app/Models/ConfigurationSetter.php new file mode 100644 index 000000000..9830fed28 --- /dev/null +++ b/app/Models/ConfigurationSetter.php @@ -0,0 +1,368 @@ +<?php + +class FreshRSS_ConfigurationSetter { + /** + * Return if the given key is supported by this setter. + * @param $key the key to test. + * @return true if the key is supported, false else. + */ + public function support($key) { + $name_setter = '_' . $key; + return is_callable(array($this, $name_setter)); + } + + /** + * Set the given key in data with the current value. + * @param $data an array containing the list of all configuration data. + * @param $key the key to update. + * @param $value the value to set. + */ + public function handle(&$data, $key, $value) { + $name_setter = '_' . $key; + call_user_func_array(array($this, $name_setter), array(&$data, $value)); + } + + /** + * A helper to set boolean values. + * + * @param $value the tested value. + * @return true if value is true and different from no, false else. + */ + private function handleBool($value) { + return ((bool)$value) && $value !== 'no'; + } + + /** + * The (long) list of setters for user configuration. + */ + private function _apiPasswordHash(&$data, $value) { + $data['apiPasswordHash'] = ctype_graph($value) && (strlen($value) >= 60) ? $value : ''; + } + + private function _content_width(&$data, $value) { + $value = strtolower($value); + if (!in_array($value, array('thin', 'medium', 'large', 'no_limit'))) { + $value = 'thin'; + } + + $data['content_width'] = $value; + } + + private function _default_state(&$data, $value) { + $data['default_state'] = (int)$value; + } + + private function _default_view(&$data, $value) { + switch ($value) { + case 'all': + $data['default_view'] = $value; + $data['default_state'] = (FreshRSS_Entry::STATE_READ + + FreshRSS_Entry::STATE_NOT_READ); + break; + case 'adaptive': + case 'unread': + default: + $data['default_view'] = $value; + $data['default_state'] = FreshRSS_Entry::STATE_NOT_READ; + } + } + + private function _html5_notif_timeout(&$data, $value) { + $value = intval($value); + $data['html5_notif_timeout'] = $value >= 0 ? $value : 0; + } + + private function _keep_history_default(&$data, $value) { + $value = intval($value); + $data['keep_history_default'] = $value >= -1 ? $value : 0; + } + + // It works for system config too! + private function _language(&$data, $value) { + $value = strtolower($value); + $languages = Minz_Translate::availableLanguages(); + if (!isset($languages[$value])) { + $value = 'en'; + } + $data['language'] = $value; + } + + private function _mail_login(&$data, $value) { + $value = filter_var($value, FILTER_VALIDATE_EMAIL); + $data['mail_login'] = $value ? $value : ''; + } + + private function _old_entries(&$data, $value) { + $value = intval($value); + $data['old_entries'] = $value > 0 ? $value : 3; + } + + private function _passwordHash(&$data, $value) { + $data['passwordHash'] = ctype_graph($value) && (strlen($value) >= 60) ? $value : ''; + } + + private function _posts_per_page(&$data, $value) { + $value = intval($value); + $data['posts_per_page'] = $value > 0 ? $value : 10; + } + + private function _queries(&$data, $values) { + $data['queries'] = array(); + foreach ($values as $value) { + $value = array_filter($value); + $params = $value; + unset($params['name']); + unset($params['url']); + $value['url'] = Minz_Url::display(array('params' => $params)); + $data['queries'][] = $value; + } + } + + private function _sharing(&$data, $values) { + $data['sharing'] = array(); + foreach ($values as $value) { + if (!is_array($value)) { + continue; + } + + // Verify URL and add default value when needed + if (isset($value['url'])) { + $is_url = ( + filter_var($value['url'], FILTER_VALIDATE_URL) || + (version_compare(PHP_VERSION, '5.3.3', '<') && + (strpos($value, '-') > 0) && + ($value === filter_var($value, FILTER_SANITIZE_URL))) + ); //PHP bug #51192 + if (!$is_url) { + continue; + } + } else { + $value['url'] = null; + } + + $data['sharing'][] = $value; + } + } + + private function _shortcuts(&$data, $values) { + foreach ($values as $key => $value) { + if (isset($data['shortcuts'][$key])) { + $data['shortcuts'][$key] = $value; + } + } + } + + private function _sort_order(&$data, $value) { + $data['sort_order'] = $value === 'ASC' ? 'ASC' : 'DESC'; + } + + private function _ttl_default(&$data, $value) { + $value = intval($value); + $data['ttl_default'] = $value >= -1 ? $value : 3600; + } + + private function _view_mode(&$data, $value) { + $value = strtolower($value); + if (!in_array($value, array('global', 'normal', 'reader'))) { + $value = 'normal'; + } + $data['view_mode'] = $value; + } + + /** + * A list of boolean setters. + */ + private function _anon_access(&$data, $value) { + $data['anon_access'] = $this->handleBool($value); + } + + private function _auto_load_more(&$data, $value) { + $data['auto_load_more'] = $this->handleBool($value); + } + + private function _auto_remove_article(&$data, $value) { + $data['auto_remove_article'] = $this->handleBool($value); + } + + private function _display_categories(&$data, $value) { + $data['display_categories'] = $this->handleBool($value); + } + + private function _display_posts(&$data, $value) { + $data['display_posts'] = $this->handleBool($value); + } + + private function _hide_read_feeds(&$data, $value) { + $data['hide_read_feeds'] = $this->handleBool($value); + } + + private function _lazyload(&$data, $value) { + $data['lazyload'] = $this->handleBool($value); + } + + private function _mark_when(&$data, $values) { + foreach ($values as $key => $value) { + if (isset($data['mark_when'][$key])) { + $data['mark_when'][$key] = $this->handleBool($value); + } + } + } + + private function _onread_jump_next(&$data, $value) { + $data['onread_jump_next'] = $this->handleBool($value); + } + + private function _reading_confirm(&$data, $value) { + $data['reading_confirm'] = $this->handleBool($value); + } + + private function _sticky_post(&$data, $value) { + $data['sticky_post'] = $this->handleBool($value); + } + + private function _bottomline_date(&$data, $value) { + $data['bottomline_date'] = $this->handleBool($value); + } + private function _bottomline_favorite(&$data, $value) { + $data['bottomline_favorite'] = $this->handleBool($value); + } + private function _bottomline_link(&$data, $value) { + $data['bottomline_link'] = $this->handleBool($value); + } + private function _bottomline_read(&$data, $value) { + $data['bottomline_read'] = $this->handleBool($value); + } + private function _bottomline_sharing(&$data, $value) { + $data['bottomline_sharing'] = $this->handleBool($value); + } + private function _bottomline_tags(&$data, $value) { + $data['bottomline_tags'] = $this->handleBool($value); + } + + private function _topline_date(&$data, $value) { + $data['topline_date'] = $this->handleBool($value); + } + private function _topline_favorite(&$data, $value) { + $data['topline_favorite'] = $this->handleBool($value); + } + private function _topline_link(&$data, $value) { + $data['topline_link'] = $this->handleBool($value); + } + private function _topline_read(&$data, $value) { + $data['topline_read'] = $this->handleBool($value); + } + + /** + * The (not so long) list of setters for system configuration. + */ + private function _allow_anonymous(&$data, $value) { + $data['allow_anonymous'] = $this->handleBool($value) && FreshRSS_Auth::accessNeedsAction(); + } + + private function _allow_anonymous_refresh(&$data, $value) { + $data['allow_anonymous_refresh'] = $this->handleBool($value) && $data['allow_anonymous']; + } + + private function _api_enabled(&$data, $value) { + $data['api_enabled'] = $this->handleBool($value); + } + + private function _auth_type(&$data, $value) { + $value = strtolower($value); + if (!in_array($value, array('form', 'http_auth', 'persona', 'none'))) { + $value = 'none'; + } + $data['auth_type'] = $value; + $this->_allow_anonymous($data, $data['allow_anonymous']); + } + + private function _db(&$data, $value) { + if (!isset($value['type'])) { + return; + } + + switch ($value['type']) { + case 'mysql': + if (empty($value['host']) || + empty($value['user']) || + empty($value['base']) || + !isset($value['password'])) { + return; + } + + $data['db']['type'] = $value['type']; + $data['db']['host'] = $value['host']; + $data['db']['user'] = $value['user']; + $data['db']['base'] = $value['base']; + $data['db']['password'] = $value['password']; + $data['db']['prefix'] = isset($value['prefix']) ? $value['prefix'] : ''; + break; + case 'sqlite': + $data['db']['type'] = $value['type']; + $data['db']['host'] = ''; + $data['db']['user'] = ''; + $data['db']['base'] = ''; + $data['db']['password'] = ''; + $data['db']['prefix'] = ''; + break; + default: + return; + } + } + + private function _default_user(&$data, $value) { + $user_list = listUsers(); + if (in_array($value, $user_list)) { + $data['default_user'] = $value; + } + } + + private function _environment(&$data, $value) { + $value = strtolower($value); + if (!in_array($value, array('silent', 'development', 'production'))) { + $value = 'production'; + } + $data['environment'] = $value; + } + + private function _limits(&$data, $values) { + $max_small_int = 16384; + $limits_keys = array( + 'cache_duration' => array( + 'min' => 0, + ), + 'timeout' => array( + 'min' => 0, + ), + 'max_inactivity' => array( + 'min' => 0, + ), + 'max_feeds' => array( + 'min' => 0, + 'max' => $max_small_int, + ), + 'max_categories' => array( + 'min' => 0, + 'max' => $max_small_int, + ), + ); + + foreach ($values as $key => $value) { + if (!isset($limits_keys[$key])) { + continue; + } + + $limits = $limits_keys[$key]; + if ( + (!isset($limits['min']) || $value > $limits['min']) && + (!isset($limits['max']) || $value < $limits['max']) + ) { + $data['limits'][$key] = $value; + } + } + } + + private function _unsafe_autologin_enabled(&$data, $value) { + $data['unsafe_autologin_enabled'] = $this->handleBool($value); + } +} diff --git a/app/Models/Context.php b/app/Models/Context.php index c8a65063a..1c770c756 100644 --- a/app/Models/Context.php +++ b/app/Models/Context.php @@ -5,7 +5,8 @@ * useful functions associated to the current view state. */ class FreshRSS_Context { - public static $conf = null; + public static $user_conf = null; + public static $system_conf = null; public static $categories = array(); public static $name = ''; @@ -37,17 +38,12 @@ class FreshRSS_Context { /** * Initialize the context. * - * Set the correct $conf and $categories variables. + * Set the correct configurations and $categories variables. */ public static function init() { // Init configuration. - $current_user = Minz_Session::param('currentUser'); - try { - self::$conf = new FreshRSS_Configuration($current_user); - } catch(Minz_Exception $e) { - Minz_Log::error('Cannot load configuration file of user `' . $current_user . '`'); - die($e->getMessage()); - } + self::$system_conf = Minz_Configuration::get('system'); + self::$user_conf = Minz_Configuration::get('user'); $catDAO = new FreshRSS_CategoryDAO(); self::$categories = $catDAO->listCategories(); @@ -198,7 +194,7 @@ class FreshRSS_Context { // By default, $next_get == $get self::$next_get = $get; - if (self::$conf->onread_jump_next && strlen($get) > 2) { + if (self::$user_conf->onread_jump_next && strlen($get) > 2) { $another_unread_id = ''; $found_current_get = false; switch ($get[0]) { @@ -276,7 +272,7 @@ class FreshRSS_Context { * @return boolean */ public static function isAutoRemoveAvailable() { - if (!self::$conf->auto_remove_article) { + if (!self::$user_conf->auto_remove_article) { return false; } if (self::isStateEnabled(FreshRSS_Entry::STATE_READ)) { @@ -297,7 +293,7 @@ class FreshRSS_Context { * @return boolean */ public static function isStickyPostEnabled() { - if (self::$conf->sticky_post) { + if (self::$user_conf->sticky_post) { return true; } if (self::isAutoRemoveAvailable()) { diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 4d06ac028..61beeea13 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -586,7 +586,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { } public function size($all = false) { - $db = Minz_Configuration::dataBase(); + $db = FreshRSS_Context::$system_conf->db; $sql = 'SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema=?'; //MySQL $values = array($db['base']); if (!$all) { diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php index bb1539e0c..ffe0f037c 100644 --- a/app/Models/EntryDAOSQLite.php +++ b/app/Models/EntryDAOSQLite.php @@ -169,6 +169,6 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO { } public function size($all = false) { - return @filesize(DATA_PATH . '/' . $this->current_user . '.sqlite'); + return @filesize(join_path(DATA_PATH, 'users', $this->current_user, 'db.sqlite')); } } diff --git a/app/Models/Factory.php b/app/Models/Factory.php index 91cb84998..db09d155d 100644 --- a/app/Models/Factory.php +++ b/app/Models/Factory.php @@ -3,8 +3,8 @@ class FreshRSS_Factory { public static function createFeedDao($username = null) { - $db = Minz_Configuration::dataBase(); - if ($db['type'] === 'sqlite') { + $conf = Minz_Configuration::get('system'); + if ($conf->db['type'] === 'sqlite') { return new FreshRSS_FeedDAOSQLite($username); } else { return new FreshRSS_FeedDAO($username); @@ -12,8 +12,8 @@ class FreshRSS_Factory { } public static function createEntryDao($username = null) { - $db = Minz_Configuration::dataBase(); - if ($db['type'] === 'sqlite') { + $conf = Minz_Configuration::get('system'); + if ($conf->db['type'] === 'sqlite') { return new FreshRSS_EntryDAOSQLite($username); } else { return new FreshRSS_EntryDAO($username); @@ -21,8 +21,8 @@ class FreshRSS_Factory { } public static function createStatsDAO($username = null) { - $db = Minz_Configuration::dataBase(); - if ($db['type'] === 'sqlite') { + $conf = Minz_Configuration::get('system'); + if ($conf->db['type'] === 'sqlite') { return new FreshRSS_StatsDAOSQLite($username); } else { return new FreshRSS_StatsDAO($username); @@ -30,8 +30,8 @@ class FreshRSS_Factory { } public static function createDatabaseDAO($username = null) { - $db = Minz_Configuration::dataBase(); - if ($db['type'] === 'sqlite') { + $conf = Minz_Configuration::get('system'); + if ($conf->db['type'] === 'sqlite') { return new FreshRSS_DatabaseDAOSQLite($username); } else { return new FreshRSS_DatabaseDAO($username); diff --git a/app/Models/Feed.php b/app/Models/Feed.php index 8f4b60097..86cbb783e 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -40,7 +40,8 @@ class FreshRSS_Feed extends Minz_Model { public function hash() { if ($this->hash === null) { - $this->hash = hash('crc32b', Minz_Configuration::salt() . $this->url); + $salt = FreshRSS_Context::$system_conf->salt; + $this->hash = hash('crc32b', $salt . $this->url); } return $this->hash; } diff --git a/app/Models/LogDAO.php b/app/Models/LogDAO.php index 21593435d..4c56e3150 100644 --- a/app/Models/LogDAO.php +++ b/app/Models/LogDAO.php @@ -3,7 +3,7 @@ class FreshRSS_LogDAO { public static function lines() { $logs = array(); - $handle = @fopen(LOG_PATH . '/' . Minz_Session::param('currentUser', '_') . '.log', 'r'); + $handle = @fopen(join_path(DATA_PATH, 'users', Minz_Session::param('currentUser', '_'), 'log.txt'), 'r'); if ($handle) { while (($line = fgets($handle)) !== false) { if (preg_match('/^\[([^\[]+)\] \[([^\[]+)\] --- (.*)$/', $line, $matches)) { @@ -20,6 +20,6 @@ class FreshRSS_LogDAO { } public static function truncate() { - file_put_contents(LOG_PATH . '/' . Minz_Session::param('currentUser', '_') . '.log', ''); + file_put_contents(join_path(DATA_PATH, 'users', Minz_Session::param('currentUser', '_'), 'log.txt'), ''); } } diff --git a/app/Models/Share.php b/app/Models/Share.php index b146db722..db6feda19 100644 --- a/app/Models/Share.php +++ b/app/Models/Share.php @@ -1,44 +1,240 @@ <?php +/** + * Manage the sharing options in FreshRSS. + */ class FreshRSS_Share { + /** + * The list of available sharing options. + */ + private static $list_sharing = array(); - static public function generateUrl($options, $selected, $link, $title) { - $share = $options[$selected['type']]; + /** + * Register a new sharing option. + * @param $share_options is an array defining the share option. + */ + public static function register($share_options) { + $type = $share_options['type']; + + if (isset(self::$list_sharing[$type])) { + return; + } + + $help_url = isset($share_options['help']) ? $share_options['help'] : ''; + self::$list_sharing[$type] = new FreshRSS_Share( + $type, $share_options['url'], $share_options['transform'], + $share_options['form'], $help_url + ); + } + + /** + * Register sharing options in a file. + * @param $filename the name of the file to load. + */ + public static function load($filename) { + $shares_from_file = @include($filename); + if (!is_array($shares_from_file)) { + $shares_from_file = array(); + } + + foreach ($shares_from_file as $share_type => $share_options) { + $share_options['type'] = $share_type; + self::register($share_options); + } + } + + /** + * Return the list of sharing options. + * @return an array of FreshRSS_Share objects. + */ + public static function enum() { + return self::$list_sharing; + } + + /** + * Return FreshRSS_Share object related to the given type. + * @param $type the share type, null if $type is not registered. + */ + public static function get($type) { + if (!isset(self::$list_sharing[$type])) { + return null; + } + + return self::$list_sharing[$type]; + } + + /** + * + */ + private $type = ''; + private $name = ''; + private $url_transform = ''; + private $transform = array(); + private $form_type = 'simple'; + private $help_url = ''; + private $custom_name = null; + private $base_url = null; + private $title = null; + private $link = null; + + /** + * Create a FreshRSS_Share object. + * @param $type is a unique string defining the kind of share option. + * @param $url_transform defines the url format to use in order to share. + * @param $transform is an array of transformations to apply on link and title. + * @param $form_type defines which form we have to use to complete. "simple" + * is typically for a centralized service while "advanced" is for + * decentralized ones. + * @param $help_url is an optional url to give help on this option. + */ + private function __construct($type, $url_transform, $transform = array(), + $form_type, $help_url = '') { + $this->type = $type; + $this->name = _t('gen.share.' . $type); + $this->url_transform = $url_transform; + $this->help_url = $help_url; + + if (!is_array($transform)) { + $transform = array(); + } + $this->transform = $transform; + + if (!in_array($form_type, array('simple', 'advanced'))) { + $form_type = 'simple'; + } + $this->form_type = $form_type; + } + + /** + * Update a FreshRSS_Share object with information from an array. + * @param $options is a list of informations to update where keys should be + * in this list: name, url, title, link. + */ + public function update($options) { + $available_options = array( + 'name' => 'custom_name', + 'url' => 'base_url', + 'title' => 'title', + 'link' => 'link', + ); + + foreach ($options as $key => $value) { + if (!isset($available_options[$key])) { + continue; + } + + $this->$available_options[$key] = $value; + } + } + + /** + * Return the current type of the share option. + */ + public function type() { + return $this->type; + } + + /** + * Return the current form type of the share option. + */ + public function formType() { + return $this->form_type; + } + + /** + * Return the current help url of the share option. + */ + public function help() { + return $this->help_url; + } + + /** + * Return the current name of the share option. + */ + public function name($real = false) { + if ($real || is_null($this->custom_name)) { + return $this->name; + } else { + return $this->custom_name; + } + } + + /** + * Return the current base url of the share option. + */ + public function baseUrl() { + return $this->base_url; + } + + /** + * Return the current url by merging url_transform and base_url. + */ + public function url() { $matches = array( '~URL~', '~TITLE~', '~LINK~', ); $replaces = array( - $selected['url'], - self::transformData($title, self::getTransform($share, 'title')), - self::transformData($link, self::getTransform($share, 'link')), + $this->base_url, + $this->title(), + $this->link(), ); - $url = str_replace($matches, $replaces, $share['url']); - return $url; + return str_replace($matches, $replaces, $this->url_transform); } - static private function transformData($data, $transform) { - if (!is_array($transform)) { - return $data; + /** + * Return the title. + * @param $raw true if we should get the title without transformations. + */ + public function title($raw = false) { + if ($raw) { + return $this->title; } - if (count($transform) === 0) { + + return $this->transform($this->title, $this->getTransform('title')); + } + + /** + * Return the link. + * @param $raw true if we should get the link without transformations. + */ + public function link($raw = false) { + if ($raw) { + return $this->link; + } + + return $this->transform($this->link, $this->getTransform('link')); + } + + /** + * Transform a data with the given functions. + * @param $data the data to transform. + * @param $tranform an array containing a list of functions to apply. + * @return the transformed data. + */ + private static function transform($data, $transform) { + if (!is_array($transform) || empty($transform)) { return $data; } + foreach ($transform as $action) { $data = call_user_func($action, $data); } + return $data; } - static private function getTransform($options, $type) { - $transform = $options['transform']; - - if (array_key_exists($type, $transform)) { - return $transform[$type]; + /** + * Get the list of transformations for the given attribute. + * @param $attr the attribute of which we want the transformations. + * @return an array containing a list of transformations to apply. + */ + private function getTransform($attr) { + if (array_key_exists($attr, $this->transform)) { + return $this->transform[$attr]; } - return $transform; + return $this->transform; } - } diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php index f04ae26bf..b55766ab4 100644 --- a/app/Models/UserDAO.php +++ b/app/Models/UserDAO.php @@ -2,7 +2,7 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { public function createUser($username) { - $db = Minz_Configuration::dataBase(); + $db = FreshRSS_Context::$system_conf->db; require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php'); $userPDO = new Minz_ModelPdo($username); @@ -34,11 +34,11 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { } public function deleteUser($username) { - $db = Minz_Configuration::dataBase(); + $db = FreshRSS_Context::$system_conf->db; require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php'); if ($db['type'] === 'sqlite') { - return unlink(DATA_PATH . '/' . $username . '.sqlite'); + return unlink(join_path(DATA_PATH, 'users', $username, 'db.sqlite')); } else { $userPDO = new Minz_ModelPdo($username); @@ -55,14 +55,14 @@ class FreshRSS_UserDAO extends Minz_ModelPdo { } public static function exist($username) { - return file_exists(DATA_PATH . '/' . $username . '_user.php'); + return is_dir(join_path(DATA_PATH , 'users', $username)); } public static function touch($username) { - return touch(DATA_PATH . '/' . $username . '_user.php'); + return touch(join_path(DATA_PATH , 'users', $username, 'config.php')); } public static function mtime($username) { - return @filemtime(DATA_PATH . '/' . $username . '_user.php'); + return @filemtime(join_path(DATA_PATH , 'users', $username, 'config.php')); } } |
