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 = ''; }
/** * 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 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 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($this->useOb); Minz_Response::send(); } catch (Minz_Exception $e) { try { Minz_Log::record($e->getMessage(), Minz_Log::ERROR); } 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 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.'; } }
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; }
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); }
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; } }
public function formLoginAction() { if (Minz_Request::isPost()) { $ok = false; $nonce = Minz_Session::param('nonce'); $username = Minz_Request::param('username', ''); $c = Minz_Request::param('challenge', ''); if (ctype_alnum($username) && ctype_graph($c) && ctype_alnum($nonce)) { if (!function_exists('password_verify')) { include_once LIB_PATH . '/password_compat.php'; } try { $conf = new FreshRSS_Configuration($username); $s = $conf->passwordHash; $ok = password_verify($nonce . $s, $c); if ($ok) { Minz_Session::_param('currentUser', $username); Minz_Session::_param('passwordHash', $s); } else { Minz_Log::record('Password mismatch for user ' . $username . ', nonce=' . $nonce . ', c=' . $c, Minz_Log::WARNING); } } catch (Minz_Exception $me) { Minz_Log::record('Login failure: ' . $me->getMessage(), Minz_Log::WARNING); } } else { Minz_Log::record('Invalid credential parameters: user='******' challenge=' . $c . ' nonce=' . $nonce, Minz_Log::DEBUG); } if (!$ok) { $notif = array('type' => 'bad', 'content' => Minz_Translate::t('invalid_login')); Minz_Session::_param('notification', $notif); } $this->view->_useLayout(false); Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); } elseif (!Minz_Configuration::canLogIn()) { Minz_Error::error(403, array('error' => array(Minz_Translate::t('access_denied')))); } invalidateHttpCache(); }
public function massiveImportAction() { @set_time_limit(300); $this->catDAO = new FreshRSS_CategoryDAO(); $this->catDAO->checkDefault(); $entryDAO = new FreshRSS_EntryDAO(); $feedDAO = new FreshRSS_FeedDAO(); $categories = Minz_Request::param('categories', array(), true); $feeds = Minz_Request::param('feeds', array(), true); // on ajoute les catégories en masse dans une fonction à part $this->addCategories($categories); // on calcule la date des articles les plus anciens qu'on accepte $nb_month_old = $this->view->conf->old_entries; $date_min = time() - 3600 * 24 * 30 * $nb_month_old; // la variable $error permet de savoir si une erreur est survenue // Le but est de ne pas arrêter l'import même en cas d'erreur // L'utilisateur sera mis au courant s'il y a eu des erreurs, mais // ne connaîtra pas les détails. Ceux-ci seront toutefois logguées $error = false; $i = 0; foreach ($feeds as $feed) { try { $values = array('id' => $feed->id(), 'url' => $feed->url(), 'category' => $feed->category(), 'name' => $feed->name(), 'website' => $feed->website(), 'description' => $feed->description(), 'lastUpdate' => 0, 'httpAuth' => $feed->httpAuth()); // ajout du flux que s'il n'est pas déjà en BDD if (!$feedDAO->searchByUrl($values['url'])) { $id = $feedDAO->addFeed($values); if ($id) { $feed->_id($id); $feed->faviconPrepare(); } else { $error = true; } } } catch (FreshRSS_Feed_Exception $e) { $error = true; Minz_Log::record($e->getMessage(), Minz_Log::WARNING); } } if ($error) { $res = Minz_Translate::t('feeds_imported_with_errors'); } else { $res = Minz_Translate::t('feeds_imported'); } $notif = array('type' => 'good', 'content' => $res); Minz_Session::_param('notification', $notif); Minz_Session::_param('actualize_feeds', true); // et on redirige vers la page d'accueil Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); }
public function markReadFeed($id, $idMax = 0) { if ($idMax === 0) { $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1, f.cache_nbUnreads=0 ' . 'WHERE f.id=? AND e.is_read = 0'; $values = array($id); $stm = $this->bd->prepare($sql); if ($stm && $stm->execute($values)) { return $stm->rowCount(); } else { $info = $stm->errorInfo(); Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); return false; } } else { $this->bd->beginTransaction(); $sql = 'UPDATE `' . $this->prefix . 'entry` e INNER JOIN `' . $this->prefix . 'feed` f ON e.id_feed = f.id ' . 'SET e.is_read = 1 ' . 'WHERE f.id=? AND e.is_read = 0 AND e.id <= ?'; $values = array($id, $idMax); $stm = $this->bd->prepare($sql); if (!($stm && $stm->execute($values))) { $info = $stm->errorInfo(); Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); $this->bd->rollBack(); return false; } $affected = $stm->rowCount(); if ($affected > 0) { $sql = 'UPDATE `' . $this->prefix . 'feed` f ' . 'SET f.cache_nbUnreads=f.cache_nbUnreads-' . $affected . ' WHERE f.id=?'; $values = array($id); $stm = $this->bd->prepare($sql); if (!($stm && $stm->execute($values))) { $info = $stm->errorInfo(); Minz_Log::record('SQL error : ' . $info[2], Minz_Log::ERROR); $this->bd->rollBack(); return false; } } $this->bd->commit(); return $affected; } }