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!');
     }
     $this->view->nonce = '';
     //Failure
     $this->view->salt1 = '';
 }
Esempio n. 2
0
 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 {
             $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());
 }
Esempio n. 4
0
 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'));
     }
 }
Esempio n. 5
0
 /**
  * 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;
 }
Esempio n. 6
0
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;
}
Esempio n. 7
0
 /**
  * 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);
     }
 }
Esempio n. 8
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'));
         }
     }
 }
Esempio n. 9
0
 /**
  * Load the files associated to $key into $translates.
  * @param $key the top level i18n key we want to load.
  */
 private static function loadKey($key)
 {
     // The top level key is not in $lang_files, it means it does not exist!
     if (!isset(self::$lang_files[$key])) {
         Minz_Log::debug($key . ' is not a valid top level key');
         return false;
     }
     self::$translates[$key] = array();
     foreach (self::$lang_files[$key] as $lang_pathname) {
         $i18n_array = (include $lang_pathname);
         if (!is_array($i18n_array)) {
             Minz_Log::warning('`' . $lang_pathname . '` does not contain a PHP array');
             continue;
         }
         // We must avoid to erase previous data so we just override them if
         // needed.
         self::$translates[$key] = array_replace_recursive(self::$translates[$key], $i18n_array);
     }
     return true;
 }
Esempio n. 10
0
/**
 * 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);
}
Esempio n. 11
0
 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;
 }
 /**
  * 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;
 }
Esempio n. 13
0
 /**
  * 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;
     }
 }
Esempio n. 14
0
 public function unsubscribeFeed()
 {
     Minz_Log::warning('TTRSS API: unsubscribeFeed() not implemented');
 }
Esempio n. 15
0
 /**
  * Affiche un élément graphique situé dans APP./views/helpers/
  * @param $helper l'élément à afficher
  */
 public function renderHelper($helper)
 {
     $fic_helper = '/views/helpers/' . $helper . '.phtml';
     if (!$this->includeFile($fic_helper)) {
         Minz_Log::warning('File not found: `' . $fic_helper . '`');
     }
 }
Esempio n. 16
0
 /**
  * This action disables an enabled extension for the current user.
  *
  * System extensions can only be disabled by an administrator.
  * This action must be reached by a POST request.
  *
  * Parameter is:
  * - e: the extension name (urlencoded).
  */
 public function disableAction()
 {
     $url_redirect = array('c' => 'extension', 'a' => 'index');
     if (Minz_Request::isPost()) {
         $ext_name = urldecode(Minz_Request::param('e'));
         $ext = Minz_ExtensionManager::findExtension($ext_name);
         if (is_null($ext)) {
             Minz_Request::bad(_t('feedback.extensions.not_found', $ext_name), $url_redirect);
         }
         if (!$ext->isEnabled()) {
             Minz_Request::bad(_t('feedback.extensions.not_enabled', $ext_name), $url_redirect);
         }
         $conf = null;
         if ($ext->getType() === 'system' && FreshRSS_Auth::hasAccess('admin')) {
             $conf = FreshRSS_Context::$system_conf;
         } elseif ($ext->getType() === 'user') {
             $conf = FreshRSS_Context::$user_conf;
         } else {
             Minz_Request::bad(_t('feedback.extensions.no_access', $ext_name), $url_redirect);
         }
         $res = $ext->uninstall();
         if ($res === true) {
             $ext_list = $conf->extensions_enabled;
             array_remove($ext_list, $ext_name);
             $conf->extensions_enabled = $ext_list;
             $conf->save();
             Minz_Request::good(_t('feedback.extensions.disable.ok', $ext_name), $url_redirect);
         } else {
             Minz_Log::warning('Can not unable extension ' . $ext_name . ': ' . $res);
             Minz_Request::bad(_t('feedback.extensions.disable.ko', $ext_name, _url('index', 'logs')), $url_redirect);
         }
     }
     Minz_Request::forward($url_redirect, true);
 }