/** * This action handles the feed configuration page. * * It displays the feed configuration page. * If this action is reached through a POST request, it stores all new * configuraiton values then sends a notification to the user. * * The options available on the page are: * - name * - description * - website URL * - feed URL * - category id (default: default category id) * - CSS path to article on website * - display in main stream (default: 0) * - HTTP authentication * - number of article to retain (default: -2) * - refresh frequency (default: -2) * Default values are empty strings unless specified. */ public function feedAction() { if (Minz_Request::param('ajax')) { $this->view->_useLayout(false); } $feedDAO = FreshRSS_Factory::createFeedDao(); $this->view->feeds = $feedDAO->listFeeds(); $id = Minz_Request::param('id'); if ($id === false || !isset($this->view->feeds[$id])) { Minz_Error::error(404); return; } $this->view->feed = $this->view->feeds[$id]; Minz_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $this->view->feed->name() . ' · '); if (Minz_Request::isPost()) { $user = Minz_Request::param('http_user', ''); $pass = Minz_Request::param('http_pass', ''); $httpAuth = ''; if ($user != '' || $pass != '') { $httpAuth = $user . ':' . $pass; } $cat = intval(Minz_Request::param('category', 0)); $values = array('name' => Minz_Request::param('name', ''), 'description' => sanitizeHTML(Minz_Request::param('description', '', true)), 'website' => Minz_Request::param('website', ''), 'url' => Minz_Request::param('url', ''), 'category' => $cat, 'pathEntries' => Minz_Request::param('path_entries', ''), 'priority' => intval(Minz_Request::param('priority', 0)), 'httpAuth' => $httpAuth, 'keep_history' => intval(Minz_Request::param('keep_history', -2)), 'ttl' => intval(Minz_Request::param('ttl', -2))); invalidateHttpCache(); $url_redirect = array('c' => 'subscription', 'params' => array('id' => $id)); if ($feedDAO->updateFeed($id, $values) !== false) { $this->view->feed->_category($cat); $this->view->feed->faviconPrepare(); Minz_Request::good(_t('feedback.sub.feed.updated'), $url_redirect); } else { Minz_Request::bad(_t('feedback.sub.feed.error'), $url_redirect); } } }
public function firstAction() { if (!FreshRSS_Auth::hasAccess('admin')) { Minz_Error::error(403); } invalidateHttpCache(); $this->view->update_to_apply = false; $this->view->last_update_time = 'unknown'; $timestamp = @filemtime(join_path(DATA_PATH, 'last_update.txt')); if ($timestamp !== false) { $this->view->last_update_time = timestamptodate($timestamp); } }
public function save() { @rename($this->filename, $this->filename . '.bak.php'); if (file_put_contents($this->filename, "<?php\n return " . var_export($this->data, true) . ';', LOCK_EX) === false) { throw new Minz_PermissionDeniedException($this->filename); } if (function_exists('opcache_invalidate')) { opcache_invalidate($this->filename); //Clear PHP 5.5+ cache for include } invalidateHttpCache(); return true; }
public function archivingAction() { if (Minz_Request::isPost()) { $old = Minz_Request::param('old_entries', 3); $keepHistoryDefault = Minz_Request::param('keep_history_default', 0); $this->view->conf->_old_entries($old); $this->view->conf->_keep_history_default($keepHistoryDefault); $this->view->conf->save(); invalidateHttpCache(); $notif = array('type' => 'good', 'content' => Minz_Translate::t('configuration_updated')); Minz_Session::_param('notification', $notif); Minz_Request::forward(array('c' => 'configure', 'a' => 'archiving'), true); } Minz_View::prependTitle(Minz_Translate::t('archiving_configuration') . ' · '); $entryDAO = new FreshRSS_EntryDAO(); $this->view->nb_total = $entryDAO->count(); $this->view->size_user = $entryDAO->size(); if (Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { $this->view->size_total = $entryDAO->size(true); } }
public function deleteAction() { if (Minz_Request::isPost() && Minz_Configuration::isAdmin(Minz_Session::param('currentUser', '_'))) { require_once APP_PATH . '/sql.php'; $username = Minz_Request::param('username'); $ok = ctype_alnum($username); if ($ok) { $ok &= strcasecmp($username, Minz_Configuration::defaultUser()) !== 0; //It is forbidden to delete the default user } if ($ok) { $configPath = DATA_PATH . '/' . $username . '_user.php'; $ok &= file_exists($configPath); } if ($ok) { $userDAO = new FreshRSS_UserDAO(); $ok &= $userDAO->deleteUser($username); $ok &= unlink($configPath); //TODO: delete Persona file } invalidateHttpCache(); $notif = array('type' => $ok ? 'good' : 'bad', 'content' => Minz_Translate::t($ok ? 'user_deleted' : 'error_occurred', $username)); Minz_Session::_param('notification', $notif); } Minz_Request::forward(array('c' => 'configure', 'a' => 'users'), true); }
/** * This action delete an existing user. * * Request parameter is: * - username * * @todo clean up this method. Idea: create a User->clean() method. */ public function deleteAction() { $username = Minz_Request::param('username'); $redirect_url = urldecode(Minz_Request::param('r', false, true)); if (!$redirect_url) { $redirect_url = array('c' => 'user', 'a' => 'manage'); } $self_deletion = Minz_Session::param('currentUser', '_') === $username; if (Minz_Request::isPost() && (FreshRSS_Auth::hasAccess('admin') || $self_deletion)) { $db = FreshRSS_Context::$system_conf->db; require_once APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php'; $ok = ctype_alnum($username); $user_data = join_path(DATA_PATH, 'users', $username); if ($ok) { $default_user = FreshRSS_Context::$system_conf->default_user; $ok &= strcasecmp($username, $default_user) !== 0; //It is forbidden to delete the default user } if ($ok && $self_deletion) { // We check the password if it's a self-destruction $nonce = Minz_Session::param('nonce'); $challenge = Minz_Request::param('challenge', ''); $ok &= FreshRSS_FormAuth::checkCredentials($username, FreshRSS_Context::$user_conf->passwordHash, $nonce, $challenge); } if ($ok) { $ok &= is_dir($user_data); } if ($ok) { $userDAO = new FreshRSS_UserDAO(); $ok &= $userDAO->deleteUser($username); $ok &= recursive_unlink($user_data); //TODO: delete Persona file } if ($ok && $self_deletion) { FreshRSS_Auth::removeAccess(); $redirect_url = array('c' => 'index', 'a' => 'index'); } invalidateHttpCache(); $notif = array('type' => $ok ? 'good' : 'bad', 'content' => _t('feedback.user.deleted' . (!$ok ? '.error' : ''), $username)); Minz_Session::_param('notification', $notif); } Minz_Request::forward($redirect_url, true); }
function saveStep3() { if (!empty($_POST)) { if (empty($_POST['type']) || empty($_POST['host']) || empty($_POST['user']) || empty($_POST['base'])) { $_SESSION['bd_error'] = 'Missing parameters!'; } $_SESSION['bd_type'] = isset($_POST['type']) ? $_POST['type'] : 'mysql'; $_SESSION['bd_host'] = $_POST['host']; $_SESSION['bd_user'] = $_POST['user']; $_SESSION['bd_password'] = $_POST['pass']; $_SESSION['bd_base'] = substr($_POST['base'], 0, 64); $_SESSION['bd_prefix'] = substr($_POST['prefix'], 0, 16); $_SESSION['bd_prefix_user'] = $_SESSION['bd_prefix'] . (empty($_SESSION['default_user']) ? '' : $_SESSION['default_user'] . '_'); $ini_array = array('general' => array('environment' => empty($_SESSION['environment']) ? 'production' : $_SESSION['environment'], 'use_url_rewriting' => false, 'salt' => $_SESSION['salt'], 'base_url' => '', 'title' => $_SESSION['title'], 'default_user' => $_SESSION['default_user'], 'auth_type' => $_SESSION['auth_type'], 'allow_anonymous' => isset($_SESSION['allow_anonymous']) ? $_SESSION['allow_anonymous'] : false), 'db' => array('type' => $_SESSION['bd_type'], 'host' => $_SESSION['bd_host'], 'user' => $_SESSION['bd_user'], 'password' => $_SESSION['bd_password'], 'base' => $_SESSION['bd_base'], 'prefix' => $_SESSION['bd_prefix'])); @unlink(DATA_PATH . '/config.php'); //To avoid access-rights problems file_put_contents(DATA_PATH . '/config.php', "<?php\n return " . var_export($ini_array, true) . ';'); if (file_exists(DATA_PATH . '/config.php') && file_exists(DATA_PATH . '/application.ini')) { @unlink(DATA_PATH . '/application.ini'); //v0.6 } $res = checkBD(); if ($res) { $_SESSION['bd_error'] = ''; header('Location: index.php?step=4'); } elseif (empty($_SESSION['bd_error'])) { $_SESSION['bd_error'] = 'Unknown error!'; } } invalidateHttpCache(); }
/** * This action handles the archive configuration page. * * It displays the archive configuration page. * If this action is reached through a POST request, it stores all new * configuration values then sends a notification to the user. * * The options available on that page are: * - duration to retain old article (default: 3) * - number of article to retain per feed (default: 0) * - refresh frequency (default: -2) * * @todo explain why the default value is -2 but this value does not * exist in the drop-down list */ public function archivingAction() { if (Minz_Request::isPost()) { FreshRSS_Context::$user_conf->old_entries = Minz_Request::param('old_entries', 3); FreshRSS_Context::$user_conf->keep_history_default = Minz_Request::param('keep_history_default', 0); FreshRSS_Context::$user_conf->ttl_default = Minz_Request::param('ttl_default', -2); FreshRSS_Context::$user_conf->save(); invalidateHttpCache(); Minz_Request::good(_t('feedback.conf.updated'), array('c' => 'configure', 'a' => 'archiving')); } Minz_View::prependTitle(_t('conf.archiving.title') . ' · '); $entryDAO = FreshRSS_Factory::createEntryDao(); $this->view->nb_total = $entryDAO->count(); $this->view->size_user = $entryDAO->size(); if (FreshRSS_Auth::hasAccess('admin')) { $this->view->size_total = $entryDAO->size(true); } }
/** * 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 formLogoutAction() { $this->view->_useLayout(false); invalidateHttpCache(); Minz_Session::_param('currentUser'); Minz_Session::_param('mail'); Minz_Session::_param('passwordHash'); Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); }
continue; } Minz_Log::notice('FreshRSS actualize ' . $user, $log_file); if (defined('STDOUT')) { fwrite(STDOUT, 'Actualize ' . $user . "...\n"); //Unbuffered } echo $user, ' '; //Buffered Minz_Session::_param('currentUser', $user); new Minz_ModelPdo($user); //TODO: FIXME: Quick-fix while waiting for a better FreshRSS() constructor/init FreshRSS_Auth::giveAccess(); $app->init(); $app->run(); if (!invalidateHttpCache()) { Minz_Log::notice('FreshRSS write access problem in ' . join_path(USERS_PATH, $user, 'log.txt'), $log_file); if (defined('STDERR')) { fwrite(STDERR, 'Write access problem in ' . join_path(USERS_PATH, $user, 'log.txt') . "\n"); } } } Minz_Log::notice('FreshRSS actualize done.', $log_file); if (defined('STDOUT')) { fwrite(STDOUT, 'Done.' . "\n"); $end_date = date_create('now'); $duration = date_diff($end_date, $begin_date); fwrite(STDOUT, 'Ending feed actualization at ' . $end_date->format('c') . "\n"); //Unbuffered fwrite(STDOUT, 'Feed actualizations took ' . $duration->format('%a day(s), %h hour(s), %i minute(s) and %s seconds') . ' for ' . count($users) . " users\n"); //Unbuffered
/** * This action purges old entries from feeds. * * @todo should be a POST request * @todo should be in feedController */ public function purgeAction() { @set_time_limit(300); $nb_month_old = max(FreshRSS_Context::$user_conf->old_entries, 1); $date_min = time() - 3600 * 24 * 30 * $nb_month_old; $feedDAO = FreshRSS_Factory::createFeedDao(); $feeds = $feedDAO->listFeeds(); $nb_total = 0; invalidateHttpCache(); foreach ($feeds as $feed) { $feed_history = $feed->keepHistory(); if ($feed_history == -2) { // TODO: -2 must be a constant! // -2 means we take the default value from configuration $feed_history = FreshRSS_Context::$user_conf->keep_history_default; } if ($feed_history >= 0) { $nb = $feedDAO->cleanOldEntries($feed->id(), $date_min, $feed_history); if ($nb > 0) { $nb_total += $nb; Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url() . ']'); } } } $feedDAO->updateCachedValues(); invalidateHttpCache(); Minz_Request::good(_t('feedback.sub.purge_completed', $nb_total), array('c' => 'configure', 'a' => 'archiving')); }
/** * This action handles the system configuration page. * * It displays the system configuration page. * If this action is reach through a POST request, it stores all new * configuration values then sends a notification to the user. * * The options available on the page are: * - user limit (default: 1) * - user category limit (default: 16384) * - user feed limit (default: 16384) */ public function systemAction() { if (!FreshRSS_Auth::hasAccess('admin')) { Minz_Error::error(403); } if (Minz_Request::isPost()) { $limits = FreshRSS_Context::$system_conf->limits; $limits['max_registrations'] = Minz_Request::param('max-registrations', 1); $limits['max_feeds'] = Minz_Request::param('max-feeds', 16384); $limits['max_categories'] = Minz_Request::param('max-categories', 16384); FreshRSS_Context::$system_conf->limits = $limits; FreshRSS_Context::$system_conf->title = Minz_Request::param('instance-name', 'FreshRSS'); FreshRSS_Context::$system_conf->auto_update_url = Minz_Request::param('auto-update-url', false); FreshRSS_Context::$system_conf->save(); invalidateHttpCache(); Minz_Session::_param('notification', array('type' => 'good', 'content' => _t('feedback.conf.updated'))); } }
public function deleteAction() { if (Minz_Request::isPost() && FreshRSS_Auth::hasAccess('admin')) { $db = FreshRSS_Context::$system_conf->db; require_once APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php'; $username = Minz_Request::param('username'); $ok = ctype_alnum($username); $user_data = join_path(DATA_PATH, 'users', $username); if ($ok) { $default_user = FreshRSS_Context::$system_conf->default_user; $ok &= strcasecmp($username, $default_user) !== 0; //It is forbidden to delete the default user } if ($ok) { $ok &= is_dir($user_data); } if ($ok) { $userDAO = new FreshRSS_UserDAO(); $ok &= $userDAO->deleteUser($username); $ok &= recursive_unlink($user_data); //TODO: delete Persona file } invalidateHttpCache(); $notif = array('type' => $ok ? 'good' : 'bad', 'content' => _t('feedback.user.deleted' . (!$ok ? '.error' : ''), $username)); Minz_Session::_param('notification', $notif); } Minz_Request::forward(array('c' => 'user', 'a' => 'manage'), true); }
function saveStep3() { if (!empty($_POST)) { if ($_SESSION['bd_type'] === 'sqlite') { $_SESSION['bd_base'] = $_SESSION['default_user']; $_SESSION['bd_host'] = ''; $_SESSION['bd_user'] = ''; $_SESSION['bd_password'] = ''; $_SESSION['bd_prefix'] = ''; $_SESSION['bd_prefix_user'] = ''; //No prefix for SQLite } else { if (empty($_POST['type']) || empty($_POST['host']) || empty($_POST['user']) || empty($_POST['base'])) { $_SESSION['bd_error'] = 'Missing parameters!'; } $_SESSION['bd_base'] = substr($_POST['base'], 0, 64); $_SESSION['bd_host'] = $_POST['host']; $_SESSION['bd_user'] = $_POST['user']; $_SESSION['bd_password'] = $_POST['pass']; $_SESSION['bd_prefix'] = substr($_POST['prefix'], 0, 16); $_SESSION['bd_prefix_user'] = $_SESSION['bd_prefix'] . (empty($_SESSION['default_user']) ? '' : $_SESSION['default_user'] . '_'); } $config_array = array('environment' => 'production', 'salt' => $_SESSION['salt'], 'title' => $_SESSION['title'], 'default_user' => $_SESSION['default_user'], 'auth_type' => $_SESSION['auth_type'], 'db' => array('type' => $_SESSION['bd_type'], 'host' => $_SESSION['bd_host'], 'user' => $_SESSION['bd_user'], 'password' => $_SESSION['bd_password'], 'base' => $_SESSION['bd_base'], 'prefix' => $_SESSION['bd_prefix'])); @unlink(join_path(DATA_PATH, 'config.php')); //To avoid access-rights problems file_put_contents(join_path(DATA_PATH, 'config.php'), "<?php\n return " . var_export($config_array, true) . ';'); $res = checkBD(); if ($res) { $_SESSION['bd_error'] = ''; header('Location: index.php?step=4'); } elseif (empty($_SESSION['bd_error'])) { $_SESSION['bd_error'] = 'Unknown error!'; } } invalidateHttpCache(); }
private static function check($statement) { if (preg_match('/^(?:UPDATE|INSERT|DELETE)/i', $statement)) { invalidateHttpCache(); } }
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); }
/** * This action remove entries from a given feed. * * It should be reached by a POST action. * * Parameter is: * - id (default: false) */ public function truncateAction() { $id = Minz_Request::param('id'); $url_redirect = array('c' => 'subscription', 'a' => 'index', 'params' => array('id' => $id)); if (!Minz_Request::isPost()) { Minz_Request::forward($url_redirect, true); } $feedDAO = FreshRSS_Factory::createFeedDao(); $n = $feedDAO->truncate($id); invalidateHttpCache(); if ($n === false) { Minz_Request::bad(_t('feedback.sub.feed.error'), $url_redirect); } else { Minz_Request::good(_t('feedback.sub.feed.n_entries_deleted', $n), $url_redirect); } }
function saveStep3() { if (!empty($_POST)) { if ($_SESSION['bd_type'] === 'sqlite') { $_SESSION['bd_base'] = $_SESSION['default_user']; $_SESSION['bd_host'] = ''; $_SESSION['bd_user'] = ''; $_SESSION['bd_password'] = ''; $_SESSION['bd_prefix'] = ''; $_SESSION['bd_prefix_user'] = ''; //No prefix for SQLite } else { if (empty($_POST['type']) || empty($_POST['host']) || empty($_POST['user']) || empty($_POST['base'])) { $_SESSION['bd_error'] = 'Missing parameters!'; } $_SESSION['bd_base'] = substr($_POST['base'], 0, 64); $_SESSION['bd_host'] = $_POST['host']; $_SESSION['bd_user'] = $_POST['user']; $_SESSION['bd_password'] = $_POST['pass']; $_SESSION['bd_prefix'] = substr($_POST['prefix'], 0, 16); $_SESSION['bd_prefix_user'] = $_SESSION['bd_prefix'] . (empty($_SESSION['default_user']) ? '' : $_SESSION['default_user'] . '_'); } // We use dirname to remove the /i part $base_url = dirname(Minz_Request::guessBaseUrl()); $config_array = array('salt' => $_SESSION['salt'], 'base_url' => $base_url, 'title' => $_SESSION['title'], 'default_user' => $_SESSION['default_user'], 'auth_type' => $_SESSION['auth_type'], 'db' => array('type' => $_SESSION['bd_type'], 'host' => $_SESSION['bd_host'], 'user' => $_SESSION['bd_user'], 'password' => $_SESSION['bd_password'], 'base' => $_SESSION['bd_base'], 'prefix' => $_SESSION['bd_prefix'], 'pdo_options' => array()), 'pubsubhubbub_enabled' => server_is_public($base_url)); @unlink(join_path(DATA_PATH, 'config.php')); //To avoid access-rights problems file_put_contents(join_path(DATA_PATH, 'config.php'), "<?php\n return " . var_export($config_array, true) . ';'); $res = checkBD(); if ($res) { $_SESSION['bd_error'] = ''; header('Location: index.php?step=4'); } elseif (empty($_SESSION['bd_error'])) { $_SESSION['bd_error'] = 'Unknown error!'; } } invalidateHttpCache(); }
/** * This action deletes all the feeds relative to a given category. * Feed-related queries are deleted. * * Request parameter is: * - id (of a category) */ public function emptyAction() { $feedDAO = FreshRSS_Factory::createFeedDao(); $url_redirect = array('c' => 'subscription', 'a' => 'index'); if (Minz_Request::isPost()) { invalidateHttpCache(); $id = Minz_Request::param('id'); if (!$id) { Minz_Request::bad(_t('feedback.sub.category.no_id'), $url_redirect); } // List feeds to remove then related user queries. $feeds = $feedDAO->listByCategory($id); if ($feedDAO->deleteFeedByCategory($id)) { // TODO: Delete old favicons // Remove related queries foreach ($feeds as $feed) { FreshRSS_Context::$user_conf->queries = remove_query_by_get('f_' . $feed->id(), FreshRSS_Context::$user_conf->queries); } FreshRSS_Context::$user_conf->save(); Minz_Request::good(_t('feedback.sub.category.emptied'), $url_redirect); } else { Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect); } } Minz_Request::forward($url_redirect, true); }
public function truncateAction() { if (Minz_Request::isPost()) { $id = Minz_Request::param('id'); $feedDAO = new FreshRSS_FeedDAO(); $n = $feedDAO->truncate($id); $notif = array('type' => $n === false ? 'bad' : 'good', 'content' => Minz_Translate::t('n_entries_deleted', $n)); Minz_Session::_param('notification', $notif); invalidateHttpCache(); Minz_Request::forward(array('c' => 'configure', 'a' => 'feed', 'params' => array('id' => $id)), true); } }