예제 #1
0
 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 = '';
 }
예제 #2
0
 /**
  * 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);
     }
 }
예제 #3
0
 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;
     }
 }
예제 #4
0
 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;
     }
 }
예제 #5
0
 /**
  * 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();
         }
     }
 }
예제 #6
0
 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') . ' · ');
 }
예제 #7
0
#
# ***** 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.';
    }
}
예제 #8
0
 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;
 }
예제 #9
0
 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);
 }
예제 #10
0
 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;
     }
 }
예제 #11
0
 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();
 }
예제 #12
0
 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);
 }
예제 #13
0
 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;
     }
 }