Esempio n. 1
0
 public static function icon($name, $urlOnly = false)
 {
     static $alts = array('add' => '✚', 'all' => '☰', 'bookmark' => '★', 'category' => '☷', 'category-white' => '☷', 'close' => '❌', 'configure' => '⚙', 'down' => '▽', 'favorite' => '★', 'help' => 'ⓘ', 'link' => '↗', 'login' => '🔒', 'logout' => '🔓', 'next' => '⏩', 'non-starred' => '☆', 'prev' => '⏪', 'read' => '☑', 'unread' => '☐', 'refresh' => '🔃', 'search' => '🔍', 'share' => '♺', 'starred' => '★', 'tag' => '⚐', 'up' => '△');
     if (!isset($alts[$name])) {
         return '';
     }
     $url = $name . '.svg';
     $url = isset(self::$themeIcons[$url]) ? self::$themeIconsUrl . $url : self::$defaultIconsUrl . $url;
     return $urlOnly ? Minz_Url::display($url) : '<img class="icon" src="' . Minz_Url::display($url) . '" alt="' . $alts[$name] . '" />';
 }
 /**
  * This action handles the main subscription page
  *
  * It displays categories and associated feeds.
  */
 public function indexAction()
 {
     Minz_View::appendScript(Minz_Url::display('/scripts/category.js?' . @filemtime(PUBLIC_PATH . '/scripts/category.js')));
     Minz_View::prependTitle(_t('sub.title') . ' · ');
     $id = Minz_Request::param('id');
     if ($id !== false) {
         $feedDAO = FreshRSS_Factory::createFeedDao();
         $this->view->feed = $feedDAO->searchById($id);
     }
 }
Esempio n. 3
0
 /**
  * This action displays the user profile page.
  */
 public function profileAction()
 {
     Minz_View::prependTitle(_t('conf.profile.title') . ' · ');
     Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js')));
     if (Minz_Request::isPost()) {
         $ok = true;
         $passwordPlain = Minz_Request::param('newPasswordPlain', '', true);
         if ($passwordPlain != '') {
             Minz_Request::_param('newPasswordPlain');
             //Discard plain-text password ASAP
             $_POST['newPasswordPlain'] = '';
             if (!function_exists('password_hash')) {
                 include_once LIB_PATH . '/password_compat.php';
             }
             $passwordHash = password_hash($passwordPlain, PASSWORD_BCRYPT, array('cost' => self::BCRYPT_COST));
             $passwordPlain = '';
             $passwordHash = preg_replace('/^\\$2[xy]\\$/', '\\$2a\\$', $passwordHash);
             //Compatibility with bcrypt.js
             $ok &= $passwordHash != '';
             FreshRSS_Context::$user_conf->passwordHash = $passwordHash;
         }
         Minz_Session::_param('passwordHash', FreshRSS_Context::$user_conf->passwordHash);
         $passwordPlain = Minz_Request::param('apiPasswordPlain', '', true);
         if ($passwordPlain != '') {
             if (!function_exists('password_hash')) {
                 include_once LIB_PATH . '/password_compat.php';
             }
             $passwordHash = password_hash($passwordPlain, PASSWORD_BCRYPT, array('cost' => self::BCRYPT_COST));
             $passwordPlain = '';
             $passwordHash = preg_replace('/^\\$2[xy]\\$/', '\\$2a\\$', $passwordHash);
             //Compatibility with bcrypt.js
             $ok &= $passwordHash != '';
             FreshRSS_Context::$user_conf->apiPasswordHash = $passwordHash;
         }
         // TODO: why do we need of hasAccess here?
         if (FreshRSS_Auth::hasAccess('admin')) {
             FreshRSS_Context::$user_conf->mail_login = Minz_Request::param('mail_login', '', true);
         }
         $email = FreshRSS_Context::$user_conf->mail_login;
         Minz_Session::_param('mail', $email);
         $ok &= FreshRSS_Context::$user_conf->save();
         if ($email != '') {
             $personaFile = DATA_PATH . '/persona/' . $email . '.txt';
             @unlink($personaFile);
             $ok &= file_put_contents($personaFile, Minz_Session::param('currentUser', '_')) !== false;
         }
         if ($ok) {
             Minz_Request::good(_t('feedback.profile.updated'), array('c' => 'user', 'a' => 'profile'));
         } else {
             Minz_Request::bad(_t('feedback.profile.error'), array('c' => 'user', 'a' => 'profile'));
         }
     }
 }
Esempio n. 4
0
 /**
  * This action displays the global view of FreshRSS.
  */
 public function globalAction()
 {
     $allow_anonymous = FreshRSS_Context::$system_conf->allow_anonymous;
     if (!FreshRSS_Auth::hasAccess() && !$allow_anonymous) {
         Minz_Request::forward(array('c' => 'auth', 'a' => 'login'));
         return;
     }
     Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js')));
     try {
         $this->updateContext();
     } catch (FreshRSS_Context_Exception $e) {
         Minz_Error::error(404);
     }
     $this->view->categories = FreshRSS_Context::$categories;
     $this->view->rss_title = FreshRSS_Context::$name . ' | ' . Minz_View::title();
     $title = _t('index.feed.title_global');
     if (FreshRSS_Context::$get_unread > 0) {
         $title = '(' . FreshRSS_Context::$get_unread . ') ' . $title;
     }
     Minz_View::prependTitle($title . ' · ');
 }
Esempio n. 5
0
 /**
  * Relance une requête
  * @param $url l'url vers laquelle est relancée la requête
  * @param $redirect si vrai, force la redirection http
  *                > sinon, le dispatcher recharge en interne
  */
 public static function forward($url = array(), $redirect = false)
 {
     if (!is_array($url)) {
         header('Location: ' . $url);
         exit;
     }
     $url = Minz_Url::checkUrl($url);
     if ($redirect) {
         header('Location: ' . Minz_Url::display($url, 'php'));
         exit;
     } else {
         self::_controllerName($url['c']);
         self::_actionName($url['a']);
         self::_params(array_merge(self::$params, $url['params']));
         Minz_Dispatcher::reset();
     }
 }
Esempio n. 6
0
 /**
  * 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'));
         }
     }
 }
 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;
     }
 }
Esempio n. 8
0
 public function loginAction()
 {
     $this->view->_useLayout(false);
     $url = 'https://verifier.login.persona.org/verify';
     $assert = Minz_Request::param('assertion');
     $params = 'assertion=' . $assert . '&audience=' . urlencode(Minz_Url::display(null, 'php', true));
     $ch = curl_init();
     $options = array(CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_POST => 2, CURLOPT_POSTFIELDS => $params);
     curl_setopt_array($ch, $options);
     $result = curl_exec($ch);
     curl_close($ch);
     $res = json_decode($result, true);
     $loginOk = false;
     $reason = '';
     if ($res['status'] === 'okay') {
         $email = filter_var($res['email'], FILTER_VALIDATE_EMAIL);
         if ($email != '') {
             $personaFile = DATA_PATH . '/persona/' . $email . '.txt';
             if (($currentUser = @file_get_contents($personaFile)) !== false) {
                 $currentUser = trim($currentUser);
                 if (ctype_alnum($currentUser)) {
                     try {
                         $this->conf = new FreshRSS_Configuration($currentUser);
                         $loginOk = strcasecmp($email, $this->conf->mail_login) === 0;
                     } catch (Minz_Exception $e) {
                         $reason = 'Invalid configuration for user [' . $currentUser . ']! ' . $e->getMessage();
                         //Permission denied or conf file does not exist
                     }
                 } else {
                     $reason = 'Invalid username format [' . $currentUser . ']!';
                 }
             }
         } else {
             $reason = 'Invalid email format [' . $res['email'] . ']!';
         }
     }
     if ($loginOk) {
         Minz_Session::_param('currentUser', $currentUser);
         Minz_Session::_param('mail', $email);
         $this->view->loginOk = true;
         invalidateHttpCache();
     } else {
         $res = array();
         $res['status'] = 'failure';
         $res['reason'] = $reason == '' ? Minz_Translate::t('invalid_login') : $reason;
         Minz_Log::record('Persona: ' . $res['reason'], Minz_Log::WARNING);
     }
     header('Content-Type: application/json; charset=UTF-8');
     $this->view->res = json_encode($res);
 }
Esempio n. 9
0
/**
 * Add support of image lazy loading
 * Move content from src attribute to data-original
 * @param content is the text we want to parse
 */
function lazyimg($content)
{
    return preg_replace('/<img([^>]+?)src=[\'"]([^"\']+)[\'"]([^>]*)>/i', '<img$1src="' . Minz_Url::display('/themes/icons/grey.gif') . '" data-original="$2"$3>', $content);
}
Esempio n. 10
0
 private function loadStylesAndScripts()
 {
     $theme = FreshRSS_Themes::load(FreshRSS_Context::$user_conf->theme);
     if ($theme) {
         foreach ($theme['files'] as $file) {
             if ($file[0] === '_') {
                 $theme_id = 'base-theme';
                 $filename = substr($file, 1);
             } else {
                 $theme_id = $theme['id'];
                 $filename = $file;
             }
             $filetime = @filemtime(PUBLIC_PATH . '/themes/' . $theme_id . '/' . $filename);
             Minz_View::appendStyle(Minz_Url::display('/themes/' . $theme_id . '/' . $filename . '?' . $filetime));
         }
     }
     Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')));
     Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js')));
     Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js')));
     if (FreshRSS_Context::$system_conf->auth_type === 'persona') {
         // TODO move it in a plugin
         // Needed for login AND logout with Persona.
         Minz_View::appendScript('https://login.persona.org/include.js');
         $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/persona.js');
         Minz_View::appendScript(Minz_Url::display('/scripts/persona.js?' . $file_mtime));
     }
 }
Esempio n. 11
0
 public function favicon()
 {
     return Minz_Url::display('/f.php?' . $this->hash());
 }
Esempio n. 12
0
function _url($controller, $action)
{
    $nb_args = func_num_args();
    if ($nb_args < 2 || $nb_args % 2 != 0) {
        return false;
    }
    $args = func_get_args();
    $params = array();
    for ($i = 2; $i < $nb_args; $i = $i + 2) {
        $params[$args[$i]] = $args[$i + 1];
    }
    return Minz_Url::display(array('c' => $controller, 'a' => $action, 'params' => $params));
}
Esempio n. 13
0
 private function loadStylesAndScripts($loginOk)
 {
     $theme = FreshRSS_Themes::load($this->conf->theme);
     if ($theme) {
         foreach ($theme['files'] as $file) {
             Minz_View::appendStyle(Minz_Url::display('/themes/' . $theme['id'] . '/' . $file . '?' . @filemtime(PUBLIC_PATH . '/themes/' . $theme['id'] . '/' . $file)));
         }
     }
     switch (Minz_Configuration::authType()) {
         case 'form':
             if (!$loginOk) {
                 Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js')));
             }
             break;
         case 'persona':
             Minz_View::appendScript('https://login.persona.org/include.js');
             break;
     }
     $includeLazyLoad = $this->conf->lazyload && ($this->conf->display_posts || Minz_Request::param('output') === 'reader');
     Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js')), false, !$includeLazyLoad, !$includeLazyLoad);
     if ($includeLazyLoad) {
         Minz_View::appendScript(Minz_Url::display('/scripts/jquery.lazyload.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.lazyload.min.js')));
     }
     Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js')));
     Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js')));
 }
Esempio n. 14
0
 /**
  * Return the url for a given file.
  *
  * @param $filename name of the file to serve.
  * @param $type the type (js or css) of the file to serve.
  * @return the url corresponding to the file.
  */
 public function getFileUrl($filename, $type)
 {
     $dir = substr(strrchr($this->path, '/'), 1);
     $file_name_url = urlencode($dir . '/static/' . $filename);
     $absolute_path = $this->path . '/static/' . $filename;
     $mtime = @filemtime($absolute_path);
     $url = '/ext.php?f=' . $file_name_url . '&amp;t=' . $type . '&amp;' . $mtime;
     return Minz_Url::display($url, 'php');
 }
Esempio n. 15
0
 /**
  * This action handles the article repartition statistic page.
  *
  * It displays the number of article and the average of article for the
  * following periods:
  *   - hour of the day
  *   - day of the week
  *   - month
  *
  * @todo verify that the metrics used here make some sense. Especially
  *       for the average.
  */
 public function repartitionAction()
 {
     $statsDAO = FreshRSS_Factory::createStatsDAO();
     $categoryDAO = new FreshRSS_CategoryDAO();
     $feedDAO = FreshRSS_Factory::createFeedDao();
     Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
     $id = Minz_Request::param('id', null);
     $this->view->categories = $categoryDAO->listCategories();
     $this->view->feed = $feedDAO->searchById($id);
     $this->view->days = $statsDAO->getDays();
     $this->view->months = $statsDAO->getMonths();
     $this->view->repartition = $statsDAO->calculateEntryRepartitionPerFeed($id);
     $this->view->repartitionHour = $statsDAO->calculateEntryRepartitionPerFeedPerHour($id);
     $this->view->averageHour = $statsDAO->calculateEntryAveragePerFeedPerHour($id);
     $this->view->repartitionDayOfWeek = $statsDAO->calculateEntryRepartitionPerFeedPerDayOfWeek($id);
     $this->view->averageDayOfWeek = $statsDAO->calculateEntryAveragePerFeedPerDayOfWeek($id);
     $this->view->repartitionMonth = $statsDAO->calculateEntryRepartitionPerFeedPerMonth($id);
     $this->view->averageMonth = $statsDAO->calculateEntryAveragePerFeedPerMonth($id);
 }
Esempio n. 16
0
 /**
  * Retourne un tableau représentant l'url passée par la barre d'adresses
  * Se base sur la table de routage
  * @return tableau représentant l'url
  * @exception RouteNotFoundException si l'uri n'est pas présente dans
  *          > la table de routage
  */
 public function buildWithRewriting()
 {
     $url = array();
     $uri = Minz_Request::getURI();
     $find = false;
     foreach ($this->routes as $route) {
         $regex = '*^' . $route['route'] . '$*';
         if (preg_match($regex, $uri, $matches)) {
             $url['c'] = $route['controller'];
             $url['a'] = $route['action'];
             $url['params'] = $this->getParams($route['params'], $matches);
             $find = true;
             break;
         }
     }
     if (!$find && $uri != '/') {
         throw new Minz_RouteNotFoundException($uri, Minz_Exception::ERROR);
     }
     // post-traitement
     $url = Minz_Url::checkUrl($url);
     return $url;
 }
Esempio n. 17
0
 /**
  * This action handles the creation of a user query.
  *
  * It gets the GET parameters and stores them in the configuration query
  * storage. Before it is saved, the unwanted parameters are unset to keep
  * lean data.
  */
 public function addQueryAction()
 {
     $category_dao = FreshRSS_Factory::createCategoryDAO();
     $feed_dao = FreshRSS_Factory::createFeedDao();
     $queries = array();
     foreach (FreshRSS_Context::$user_conf->queries as $key => $query) {
         $queries[$key] = new FreshRSS_UserQuery($query, $feed_dao, $category_dao);
     }
     $params = Minz_Request::params();
     $params['url'] = Minz_Url::display(array('params' => $params));
     $params['name'] = _t('conf.query.number', count($queries) + 1);
     $queries[] = new FreshRSS_UserQuery($params, $feed_dao, $category_dao);
     FreshRSS_Context::$user_conf->queries = $queries;
     FreshRSS_Context::$user_conf->save();
     Minz_Request::good(_t('feedback.conf.query_created', $query['name']), array('c' => 'configure', 'a' => 'queries'));
 }