/** * Affiche un élément graphique situé dans APP./views/helpers/ * @param $helper l'élément à afficher */ public function renderHelper($helper) { $fic_helper = APP_PATH . '/views/helpers/' . $helper . '.phtml'; if ((include $fic_helper) === false) { Minz_Log::record('File not found: `' . $fic_helper . '`', Minz_Log::WARNING); } }
public function nonceAction() { header('Content-Type: application/json; charset=UTF-8'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s \\G\\M\\T')); header('Expires: 0'); header('Cache-Control: private, no-cache, no-store, must-revalidate'); header('Pragma: no-cache'); $user = isset($_GET['user']) ? $_GET['user'] : ''; if (ctype_alnum($user)) { try { $salt = FreshRSS_Context::$system_conf->salt; $conf = get_user_configuration($user); $s = $conf->passwordHash; if (strlen($s) >= 60) { $this->view->salt1 = substr($s, 0, 29); //CRYPT_BLOWFISH Salt: "$2a$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". $this->view->nonce = sha1($salt . uniqid(mt_rand(), true)); Minz_Session::_param('nonce', $this->view->nonce); return; //Success } } catch (Minz_Exception $me) { Minz_Log::warning('Nonce failure: ' . $me->getMessage()); } } else { Minz_Log::notice('Nonce failure due to invalid username!'); } //Failure: Return random data. $this->view->salt1 = sprintf('$2a$%02d$', FreshRSS_user_Controller::BCRYPT_COST); $alphabet = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for ($i = 22; $i > 0; $i--) { $this->view->salt1 .= $alphabet[rand(0, 63)]; } $this->view->nonce = sha1(rand()); }
public function postUpdateHook() { $res = $this->install(); if ($res !== true) { Minz_Log::warning('Problem during TTRSS API extension post update: ' . $res); } }
public function nonceAction() { header('Content-Type: application/json; charset=UTF-8'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s \\G\\M\\T')); header('Expires: 0'); header('Cache-Control: private, no-cache, no-store, must-revalidate'); header('Pragma: no-cache'); $user = isset($_GET['user']) ? $_GET['user'] : ''; if (ctype_alnum($user)) { try { $conf = new FreshRSS_Configuration($user); $s = $conf->passwordHash; if (strlen($s) >= 60) { $this->view->salt1 = substr($s, 0, 29); //CRYPT_BLOWFISH Salt: "$2a$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". $this->view->nonce = sha1(Minz_Configuration::salt() . uniqid(mt_rand(), true)); Minz_Session::_param('nonce', $this->view->nonce); return; //Success } } catch (Minz_Exception $me) { Minz_Log::record('Nonce failure: ' . $me->getMessage(), Minz_Log::WARNING); } } $this->view->nonce = ''; //Failure $this->view->salt1 = ''; }
public function deleteCategory($id) { $sql = 'DELETE FROM `' . $this->prefix . 'category` WHERE id=?'; $stm = $this->bd->prepare($sql); $values = array($id); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } }
public function updateCachedValues() { //For one single feed, call updateLastUpdate($id) $sql = 'UPDATE `' . $this->prefix . 'feed` ' . 'SET cache_nbEntries=(SELECT COUNT(e1.id) FROM `' . $this->prefix . 'entry` e1 WHERE e1.id_feed=`' . $this->prefix . 'feed`.id),' . 'cache_nbUnreads=(SELECT COUNT(e2.id) FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed=`' . $this->prefix . 'feed`.id AND e2.is_read=0)'; $stm = $this->bd->prepare($sql); if ($stm && $stm->execute()) { return $stm->rowCount(); } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error updateCachedValues: ' . $info[2]); return false; } }
public function deleteCategory($id) { $sql = 'DELETE FROM `' . $this->prefix . 'category` WHERE id=?'; $stm = $this->bd->prepare($sql); $values = array($id); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error deleteCategory: ' . $info[2]); 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; } }
/** * Démarre l'application (lance le dispatcher et renvoie la réponse) */ public function run() { try { $this->dispatcher->run(); } catch (Minz_Exception $e) { try { Minz_Log::error($e->getMessage()); } catch (Minz_PermissionDeniedException $e) { $this->killApp($e->getMessage()); } if ($e instanceof Minz_FileNotExistException || $e instanceof Minz_ControllerNotExistException || $e instanceof Minz_ControllerNotActionControllerException || $e instanceof Minz_ActionException) { Minz_Error::error(404, array('error' => array($e->getMessage())), true); } else { $this->killApp(); } } }
public function deleteUser($username) { $db = FreshRSS_Context::$system_conf->db; require_once APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php'; if ($db['type'] === 'sqlite') { return unlink(join_path(DATA_PATH, 'users', $username, 'db.sqlite')); } else { $userPDO = new Minz_ModelPdo($username); $sql = sprintf(SQL_DROP_TABLES, $db['prefix'] . $username . '_'); $stm = $userPDO->bd->prepare($sql); if ($stm && $stm->execute()) { return true; } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error : ' . $info[2]); return false; } } }
public function checkAction() { $this->view->change_view('update', 'index'); if (file_exists(UPDATE_FILENAME)) { // There is already an update file to apply: we don't need to check // the webserver! // Or if already check during the last hour, do nothing. Minz_Request::forward(array('c' => 'update'), true); return; } $auto_update_url = FreshRSS_Context::$system_conf->auto_update_url . '?v=' . FRESHRSS_VERSION; $c = curl_init($auto_update_url); curl_setopt($c, CURLOPT_RETURNTRANSFER, true); curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2); $result = curl_exec($c); $c_status = curl_getinfo($c, CURLINFO_HTTP_CODE); $c_error = curl_error($c); curl_close($c); if ($c_status !== 200) { Minz_Log::warning('Error during update (HTTP code ' . $c_status . '): ' . $c_error); $this->view->message = array('status' => 'bad', 'title' => _t('gen.short.damn'), 'body' => _t('feedback.update.server_not_found', $auto_update_url)); return; } $res_array = explode("\n", $result, 2); $status = $res_array[0]; if (strpos($status, 'UPDATE') !== 0) { $this->view->message = array('status' => 'bad', 'title' => _t('gen.short.damn'), 'body' => _t('feedback.update.none')); @touch(join_path(DATA_PATH, 'last_update.txt')); return; } $script = $res_array[1]; if (file_put_contents(UPDATE_FILENAME, $script) !== false) { $version = explode(' ', $status, 2); $version = $version[1]; @file_put_contents(join_path(DATA_PATH, 'last_update.txt'), $version); Minz_Request::forward(array('c' => 'update'), true); } else { $this->view->message = array('status' => 'bad', 'title' => _t('gen.short.damn'), 'body' => _t('feedback.update.error', 'Cannot save the update script')); } }
/** * This action changes the category of a feed. * * This page must be reached by a POST request. * * Parameters are: * - f_id (default: false) * - c_id (default: false) * If c_id is false, default category is used. * * @todo should handle order of the feed inside the category. */ public function moveAction() { if (!Minz_Request::isPost()) { Minz_Request::forward(array('c' => 'subscription'), true); } $feed_id = Minz_Request::param('f_id'); $cat_id = Minz_Request::param('c_id'); if ($cat_id === false) { // If category was not given get the default one. $catDAO = new FreshRSS_CategoryDAO(); $catDAO->checkDefault(); $def_cat = $catDAO->getDefault(); $cat_id = $def_cat->id(); } $feedDAO = FreshRSS_Factory::createFeedDao(); $values = array('category' => $cat_id); $feed = $feedDAO->searchById($feed_id); if ($feed && ($feed->category() == $cat_id || $feedDAO->updateFeed($feed_id, $values))) { // TODO: return something useful } else { Minz_Log::warning('Cannot move feed `' . $feed_id . '` ' . 'in the category `' . $cat_id . '`'); Minz_Error::error(404); } }
/** * This method import a JSON-based feed (Google Reader format). * * @param array $origin represents a feed. * @param boolean $google_compliant takes care of some specific values if true. * @return FreshRSS_Feed if feed is in database at the end of the process, * else null. */ private function addFeedJson($origin, $google_compliant) { $default_cat = $this->catDAO->getDefault(); $return = null; $key = $google_compliant ? 'htmlUrl' : 'feedUrl'; $url = $origin[$key]; $name = $origin['title']; $website = $origin['htmlUrl']; try { // Create a Feed object and add it in database. $feed = new FreshRSS_Feed($url); $feed->_category($default_cat->id()); $feed->_name($name); $feed->_website($website); // Call the extension hook $feed = Minz_ExtensionManager::callHook('feed_before_insert', $feed); if (!is_null($feed)) { // addFeedObject checks if feed is already in DB so nothing else to // check here. $id = $this->feedDAO->addFeedObject($feed); if ($id !== false) { $feed->_id($id); $return = $feed; } } } catch (FreshRSS_Feed_Exception $e) { Minz_Log::warning($e->getMessage()); } return $return; }
/** * This action resets the authentication system. * * After reseting, form auth is set by default. */ public function resetAction() { Minz_View::prependTitle(_t('admin.auth.title_reset') . ' · '); Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); $this->view->no_form = false; // Enable changement of auth only if Persona! if (FreshRSS_Context::$system_conf->auth_type != 'persona') { $this->view->message = array('status' => 'bad', 'title' => _t('gen.short.damn'), 'body' => _t('feedback.auth.not_persona')); $this->view->no_form = true; return; } $conf = get_user_configuration(FreshRSS_Context::$system_conf->default_user); if (is_null($conf)) { return; } // Admin user must have set its master password. if (!$conf->passwordHash) { $this->view->message = array('status' => 'bad', 'title' => _t('gen.short.damn'), 'body' => _t('feedback.auth.no_password_set')); $this->view->no_form = true; return; } invalidateHttpCache(); if (Minz_Request::isPost()) { $nonce = Minz_Session::param('nonce'); $username = Minz_Request::param('username', ''); $challenge = Minz_Request::param('challenge', ''); $ok = FreshRSS_FormAuth::checkCredentials($username, $conf->passwordHash, $nonce, $challenge); if ($ok) { FreshRSS_Context::$system_conf->auth_type = 'form'; $ok = FreshRSS_Context::$system_conf->save(); if ($ok) { Minz_Request::good(_t('feedback.auth.form.set')); } else { Minz_Request::bad(_t('feedback.auth.form.not_set'), array('c' => 'auth', 'a' => 'reset')); } } else { Minz_Log::warning('Password mismatch for' . ' user='******', nonce=' . $nonce . ', c=' . $challenge); Minz_Request::bad(_t('feedback.auth.login.invalid'), array('c' => 'auth', 'a' => 'reset')); } } }
public function cleanOldEntries($id, $date_min, $keep = 15) { //Remember to call updateLastUpdate($id) or updateCachedValues() just after $sql = 'DELETE FROM ' . $this->prefix . 'entry ' . 'WHERE id_feed=:id_feed AND id<=:id_max ' . 'AND is_favorite=false ' . 'AND lastSeen < (SELECT maxLastSeen FROM (SELECT (MAX(e3.lastSeen)-99) AS maxLastSeen FROM ' . $this->prefix . 'entry e3 WHERE e3.id_feed=:id_feed) recent) ' . 'AND id NOT IN (SELECT id FROM (SELECT e2.id FROM ' . $this->prefix . 'entry e2 WHERE e2.id_feed=:id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select: MySQL doesn't support 'LIMIT & IN/ALL/ANY/SOME subquery' $stm = $this->bd->prepare($sql); if ($stm) { $id_max = intval($date_min) . '000000'; $stm->bindParam(':id_feed', $id, PDO::PARAM_INT); $stm->bindParam(':id_max', $id_max, PDO::PARAM_STR); $stm->bindParam(':keep', $keep, PDO::PARAM_INT); } if ($stm && $stm->execute()) { return $stm->rowCount(); } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error cleanOldEntries: ' . $info[2]); return false; } }
/** * Translate a key into its corresponding value based on selected language. * @param $key the key to translate. * @param additional parameters for variable keys. * @return the value corresponding to the key. * If no value is found, return the key itself. */ public static function t($key) { $group = explode('.', $key); if (count($group) < 2) { Minz_Log::debug($key . ' is not in a valid format'); $top_level = 'gen'; } else { $top_level = array_shift($group); } // If $translates[$top_level] is null it means we have to load the // corresponding files. if (!isset(self::$translates[$top_level]) || is_null(self::$translates[$top_level])) { $res = self::loadKey($top_level); if (!$res) { return $key; } } // Go through the i18n keys to get the correct translation value. $translates = self::$translates[$top_level]; $size_group = count($group); $level_processed = 0; $translation_value = $key; foreach ($group as $i18n_level) { $level_processed++; if (!isset($translates[$i18n_level])) { Minz_Log::debug($key . ' is not a valid key'); return $key; } if ($level_processed < $size_group) { $translates = $translates[$i18n_level]; } else { $translation_value = $translates[$i18n_level]; } } if (is_array($translation_value)) { if (isset($translation_value['_'])) { $translation_value = $translation_value['_']; } else { Minz_Log::debug($key . ' is not a valid key'); return $key; } } // Get the facultative arguments to replace i18n variables. $args = func_get_args(); unset($args[0]); return vsprintf($translation_value, $args); }
/** * This action displays the RSS feed of FreshRSS. */ public function rssAction() { $allow_anonymous = FreshRSS_Context::$system_conf->allow_anonymous; $token = FreshRSS_Context::$user_conf->token; $token_param = Minz_Request::param('token', ''); $token_is_ok = $token != '' && $token === $token_param; // Check if user has access. if (!FreshRSS_Auth::hasAccess() && !$allow_anonymous && !$token_is_ok) { Minz_Error::error(403); } try { $this->updateContext(); } catch (FreshRSS_Context_Exception $e) { Minz_Error::error(404); } try { $this->view->entries = $this->listEntriesByContext(); } catch (FreshRSS_EntriesGetter_Exception $e) { Minz_Log::notice($e->getMessage()); Minz_Error::error(404); } // No layout for RSS output. $this->view->url = empty($_SERVER['QUERY_STRING']) ? '' : '?' . $_SERVER['QUERY_STRING']; $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title(); $this->view->_useLayout(false); header('Content-Type: application/rss+xml; charset=utf-8'); }
function pubSubHubbubSubscribe($state) { if (FreshRSS_Context::$system_conf->base_url && $this->hubUrl && $this->selfUrl) { $hubFilename = PSHB_PATH . '/feeds/' . base64url_encode($this->selfUrl) . '/!hub.json'; $hubFile = @file_get_contents($hubFilename); if ($hubFile === false) { Minz_Log::warning('JSON not found for PubSubHubbub: ' . $this->url); return false; } $hubJson = json_decode($hubFile, true); if (!$hubJson || empty($hubJson['key']) || !ctype_xdigit($hubJson['key'])) { Minz_Log::warning('Invalid JSON for PubSubHubbub: ' . $this->url); return false; } $callbackUrl = checkUrl(FreshRSS_Context::$system_conf->base_url . 'api/pshb.php?k=' . $hubJson['key']); if ($callbackUrl == '') { Minz_Log::warning('Invalid callback for PubSubHubbub: ' . $this->url); return false; } $ch = curl_init(); curl_setopt_array($ch, array(CURLOPT_URL => $this->hubUrl, CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_USERAGENT => _t('gen.freshrss') . '/' . FRESHRSS_VERSION . ' (' . PHP_OS . '; ' . FRESHRSS_WEBSITE . ')', CURLOPT_POSTFIELDS => 'hub.verify=sync' . '&hub.mode=' . ($state ? 'subscribe' : 'unsubscribe') . '&hub.topic=' . urlencode($this->selfUrl) . '&hub.callback=' . urlencode($callbackUrl))); $response = curl_exec($ch); $info = curl_getinfo($ch); file_put_contents(USERS_PATH . '/_/log_pshb.txt', date('c') . "\t" . 'PubSubHubbub ' . ($state ? 'subscribe' : 'unsubscribe') . ' to ' . $this->selfUrl . ' with callback ' . $callbackUrl . ': ' . $info['http_code'] . ' ' . $response . "\n", FILE_APPEND); if (!$state) { //unsubscribe $hubJson['lease_end'] = time() - 60; file_put_contents($hubFilename, json_encode($hubJson)); } if (substr($info['http_code'], 0, 1) == '2') { return true; } else { $hubJson['lease_start'] = time(); //Prevent trying again too soon $hubJson['error'] = true; file_put_contents($hubFilename, json_encode($hubJson)); return false; } } return false; }
/** * Register and return the configuration for a given user. * * Note this function has been created to generate temporary configuration * objects. If you need a long-time configuration, please don't use this function. * * @param $username the name of the user of which we want the configuration. * @return a Minz_Configuration object, null if the configuration cannot be loaded. */ function get_user_configuration($username) { $namespace = 'user_' . $username; try { Minz_Configuration::register($namespace, join_path(USERS_PATH, $username, 'config.php'), join_path(USERS_PATH, '_', 'config.default.php')); } catch (Minz_ConfigurationNamespaceException $e) { // namespace already exists, do nothing. } catch (Minz_FileNotExistException $e) { Minz_Log::warning($e->getMessage()); return null; } return Minz_Configuration::get($namespace); }
# # ***** END LICENSE BLOCK ***** 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 if (!file_exists(DATA_PATH . '/no-cache.txt')) { require LIB_PATH . '/http-conditional.php'; $currentUser = Minz_Session::param('currentUser', ''); $dateLastModification = $currentUser === '' ? time() : max(@filemtime(join_path(USERS_PATH, $currentUser, 'log.txt')), @filemtime(join_path(DATA_PATH, 'config.php'))); if (httpConditional($dateLastModification, 0, 0, false, PHP_COMPRESSION, true)) { exit; //No need to send anything } } try { $front_controller = new FreshRSS(); $front_controller->init(); $front_controller->run(); } catch (Exception $e) { echo '### Fatal error! ###<br />', "\n"; Minz_Log::error($e->getMessage()); echo 'See logs files.'; } }
private function accessControl($currentUser) { if ($currentUser == '') { switch (Minz_Configuration::authType()) { case 'form': $currentUser = Minz_Configuration::defaultUser(); Minz_Session::_param('passwordHash'); $loginOk = false; break; case 'http_auth': $currentUser = httpAuthUser(); $loginOk = $currentUser != ''; break; case 'persona': $loginOk = false; $email = filter_var(Minz_Session::param('mail'), FILTER_VALIDATE_EMAIL); if ($email != '') { //TODO: Remove redundancy with indexController $personaFile = DATA_PATH . '/persona/' . $email . '.txt'; if (($currentUser = @file_get_contents($personaFile)) !== false) { $currentUser = trim($currentUser); $loginOk = true; } } if (!$loginOk) { $currentUser = Minz_Configuration::defaultUser(); } break; case 'none': $currentUser = Minz_Configuration::defaultUser(); $loginOk = true; break; default: $currentUser = Minz_Configuration::defaultUser(); $loginOk = false; break; } } else { $loginOk = true; } if (!ctype_alnum($currentUser)) { Minz_Session::_param('currentUser', ''); die('Invalid username [' . $currentUser . ']!'); } try { $this->conf = new FreshRSS_Configuration($currentUser); Minz_View::_param('conf', $this->conf); Minz_Session::_param('currentUser', $currentUser); } catch (Minz_Exception $me) { $loginOk = false; try { $this->conf = new FreshRSS_Configuration(Minz_Configuration::defaultUser()); Minz_Session::_param('currentUser', Minz_Configuration::defaultUser()); Minz_View::_param('conf', $this->conf); $notif = array('type' => 'bad', 'content' => 'Invalid configuration for user [' . $currentUser . ']!'); Minz_Session::_param('notification', $notif); Minz_Log::record($notif['content'] . ' ' . $me->getMessage(), Minz_Log::WARNING); Minz_Session::_param('currentUser', ''); } catch (Exception $e) { die($e->getMessage()); } } if ($loginOk) { switch (Minz_Configuration::authType()) { case 'form': $loginOk = Minz_Session::param('passwordHash') === $this->conf->passwordHash; break; case 'http_auth': $loginOk = strcasecmp($currentUser, httpAuthUser()) === 0; break; case 'persona': $loginOk = strcasecmp(Minz_Session::param('mail'), $this->conf->mail_login) === 0; break; case 'none': $loginOk = true; break; default: $loginOk = false; break; } } Minz_View::_param('loginOk', $loginOk); return $loginOk; }
/** * Return the value of the given param. * * @param $key the name of the param. * @param $default default value to return if key does not exist. * @return the value corresponding to the key. * @throws Minz_ConfigurationParamException if the param does not exist */ public function param($key, $default = null) { if (isset($this->data[$key])) { return $this->data[$key]; } elseif (!is_null($default)) { return $default; } else { Minz_Log::warning($key . ' does not exist in configuration'); return null; } }
public function importExportAction() { require_once LIB_PATH . '/lib_opml.php'; $catDAO = new FreshRSS_CategoryDAO(); $this->view->categories = $catDAO->listCategories(); $this->view->req = Minz_Request::param('q'); if ($this->view->req == 'export') { Minz_View::_title('freshrss_feeds.opml'); $this->view->_useLayout(false); header('Content-Type: application/xml; charset=utf-8'); header('Content-disposition: attachment; filename=freshrss_feeds.opml'); $feedDAO = new FreshRSS_FeedDAO(); $catDAO = new FreshRSS_CategoryDAO(); $list = array(); foreach ($catDAO->listCategories() as $key => $cat) { $list[$key]['name'] = $cat->name(); $list[$key]['feeds'] = $feedDAO->listByCategory($cat->id()); } $this->view->categories = $list; } elseif ($this->view->req == 'import' && Minz_Request::isPost()) { if ($_FILES['file']['error'] == 0) { invalidateHttpCache(); // on parse le fichier OPML pour récupérer les catégories et les flux associés try { list($categories, $feeds) = opml_import(file_get_contents($_FILES['file']['tmp_name'])); // On redirige vers le controller feed qui va se charger d'insérer les flux en BDD // les flux sont mis au préalable dans des variables de Request Minz_Request::_param('q', 'null'); Minz_Request::_param('categories', $categories); Minz_Request::_param('feeds', $feeds); Minz_Request::forward(array('c' => 'feed', 'a' => 'massiveImport')); } catch (FreshRSS_Opml_Exception $e) { Minz_Log::record($e->getMessage(), Minz_Log::WARNING); $notif = array('type' => 'bad', 'content' => Minz_Translate::t('bad_opml_file')); Minz_Session::_param('notification', $notif); Minz_Request::forward(array('c' => 'configure', 'a' => 'importExport'), true); } } } $feedDAO = new FreshRSS_FeedDAO(); $this->view->feeds = $feedDAO->listFeeds(); // au niveau de la vue, permet de ne pas voir un flux sélectionné dans la liste $this->view->flux = false; Minz_View::prependTitle(Minz_Translate::t('import_export_opml') . ' · '); }
# # ***** END LICENSE BLOCK ***** 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'); Minz_Session::_param('keepAlive', 1); //For Persona if (!file_exists(DATA_PATH . '/no-cache.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')); if (httpConditional($dateLastModification, 0, 0, false, false, true)) { exit; //No need to send anything } } try { $front_controller = new FreshRSS(); $front_controller->init(); $front_controller->run(); } catch (Exception $e) { echo '### Fatal error! ###<br />', "\n"; Minz_Log::record($e->getMessage(), Minz_Log::ERROR); echo 'See logs files.'; } }
function clientLogin($email, $pass) { //http://web.archive.org/web/20130604091042/http://undoc.in/clientLogin.html logMe('clientLogin(' . $email . ")\n"); if (ctype_alnum($email)) { if (!function_exists('password_verify')) { include_once LIB_PATH . '/password_compat.php'; } $conf = get_user_configuration($email); if (is_null($conf)) { Minz_Log::warning('Invalid API user ' . $email . ': configuration cannot be found.'); unauthorized(); } if ($conf->apiPasswordHash != '' && password_verify($pass, $conf->apiPasswordHash)) { header('Content-Type: text/plain; charset=UTF-8'); $system_conf = Minz_Configuration::get('system'); $auth = $email . '/' . sha1($system_conf->salt . $email . $conf->apiPasswordHash); echo 'SID=', $auth, "\n", 'Auth=', $auth, "\n"; exit; } else { Minz_Log::warning('Password API mismatch for user ' . $email); unauthorized(); } } else { badRequest(); } die; }
public function cleanOldEntries($id, $date_min, $keep = 15) { //Remember to call updateLastUpdate($id) just after $sql = 'DELETE e.* FROM `' . $this->prefix . 'entry` e ' . 'WHERE e.id_feed = :id_feed AND e.id <= :id_max AND e.is_favorite = 0 AND e.id NOT IN ' . '(SELECT id FROM (SELECT e2.id FROM `' . $this->prefix . 'entry` e2 WHERE e2.id_feed = :id_feed ORDER BY id DESC LIMIT :keep) keep)'; //Double select because of: MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' $stm = $this->bd->prepare($sql); $id_max = intval($date_min) . '000000'; $stm->bindParam(':id_feed', $id, PDO::PARAM_INT); $stm->bindParam(':id_max', $id_max, PDO::PARAM_INT); $stm->bindParam(':keep', $keep, PDO::PARAM_INT); if ($stm && $stm->execute()) { return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } }
/** * Load the extension source code based on info metadata. * * @param $info an array containing information about extension. * @return an extension inheriting from Minz_Extension. */ public static function load($info) { $entry_point_filename = $info['path'] . '/' . self::$ext_entry_point; $ext_class_name = $info['entrypoint'] . 'Extension'; include_once $entry_point_filename; // Test if the given extension class exists. if (!class_exists($ext_class_name)) { Minz_Log::warning('`' . $ext_class_name . '` cannot be found in `' . $entry_point_filename . '`'); return null; } // Try to load the class. $extension = null; try { $extension = new $ext_class_name($info); } catch (Minz_ExtensionException $e) { // We cannot load the extension? Invalid! Minz_Log::warning('In `' . $metadata_filename . '`: ' . $e->getMessage()); return null; } // Test if class is correct. if (!$extension instanceof Minz_Extension) { Minz_Log::warning('`' . $ext_class_name . '` is not an instance of `Minz_Extension`'); return null; } return $extension; }
public function updateLastSeen($id_feed, $guids) { if (count($guids) < 1) { return 0; } $sql = 'UPDATE `' . $this->prefix . 'entry` SET lastSeen=? WHERE id_feed=? AND guid IN (' . str_repeat('?,', count($guids) - 1) . '?)'; $stm = $this->bd->prepare($sql); $values = array(time(), $id_feed); $values = array_merge($values, $guids); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo(); if ($this->autoAddColumn($info)) { return $this->updateLastSeen($id_feed, $guids); } Minz_Log::error('SQL error updateLastSeen: ' . $info[0] . ': ' . $info[1] . ' ' . $info[2] . ' while updating feed ' . $id_feed); return false; } }
/** * Mark all the articles in a category as read. * There is a fail safe to prevent to mark as read articles that are * loaded during the mark as read action. Then the cache is updated. * * If $idMax equals 0, a deprecated debug message is logged * * @param integer $id category ID * @param integer $idMax fail safe article ID * @return integer affected rows */ public function markReadCat($id, $idMax = 0) { if ($idMax == 0) { $idMax = time() . '000000'; Minz_Log::debug('Calling markReadCat(0) is deprecated!'); } $sql = 'UPDATE `' . $this->prefix . 'entry` ' . 'SET is_read=1 ' . 'WHERE is_read=0 AND id <= ? AND ' . 'id_feed IN (SELECT f.id FROM `' . $this->prefix . 'feed` f WHERE f.category=?)'; $values = array($idMax, $id); $stm = $this->bd->prepare($sql); if (!($stm && $stm->execute($values))) { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); Minz_Log::error('SQL error markReadCat: ' . $info[2]); return false; } $affected = $stm->rowCount(); if ($affected > 0 && !$this->updateCacheUnreads($id, false)) { return false; } return $affected; }
public function purgeAction() { @set_time_limit(300); $nb_month_old = max($this->view->conf->old_entries, 1); $date_min = time() - 3600 * 24 * 30 * $nb_month_old; $feedDAO = new FreshRSS_FeedDAO(); $feeds = $feedDAO->listFeedsOrderUpdate(); $nbTotal = 0; invalidateHttpCache(); foreach ($feeds as $feed) { $feedHistory = $feed->keepHistory(); if ($feedHistory == -2) { //default $feedHistory = $this->view->conf->keep_history_default; } if ($feedHistory >= 0) { $nb = $feedDAO->cleanOldEntries($feed->id(), $date_min, $feedHistory); if ($nb > 0) { $nbTotal += $nb; Minz_Log::record($nb . ' old entries cleaned in feed [' . $feed->url() . ']', Minz_Log::DEBUG); $feedDAO->updateLastUpdate($feed->id()); } } } invalidateHttpCache(); $notif = array('type' => 'good', 'content' => Minz_Translate::t('purge_completed', $nbTotal)); Minz_Session::_param('notification', $notif); Minz_Request::forward(array('c' => 'configure', 'a' => 'archiving'), true); }