mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2025-12-30 17:07:49 -05:00
Fix 3 related error handling when updating the feed URL with an invalid URL. Previously leading to unclear 500 page with additional PHP errors.
360 lines
14 KiB
PHP
360 lines
14 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Controller to handle subscription actions.
|
|
*/
|
|
class FreshRSS_subscription_Controller extends FreshRSS_ActionController {
|
|
/**
|
|
* This action is called before every other action in that class. It is
|
|
* the common boiler plate for every action. It is triggered by the
|
|
* underlying framework.
|
|
*/
|
|
public function firstAction() {
|
|
if (!FreshRSS_Auth::hasAccess()) {
|
|
Minz_Error::error(403);
|
|
}
|
|
|
|
$catDAO = FreshRSS_Factory::createCategoryDao();
|
|
$feedDAO = FreshRSS_Factory::createFeedDao();
|
|
|
|
$catDAO->checkDefault();
|
|
$feedDAO->updateTTL();
|
|
$this->view->categories = $catDAO->listSortedCategories(false, true);
|
|
$this->view->default_category = $catDAO->getDefault();
|
|
|
|
$signalError = false;
|
|
foreach ($this->view->categories as $cat) {
|
|
$feeds = $cat->feeds();
|
|
foreach ($feeds as $feed) {
|
|
if ($feed->inError()) {
|
|
$signalError = true;
|
|
}
|
|
}
|
|
if ($signalError) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
$this->view->signalError = $signalError;
|
|
}
|
|
|
|
/**
|
|
* This action handles the main subscription page
|
|
*
|
|
* It displays categories and associated feeds.
|
|
*/
|
|
public function indexAction() {
|
|
FreshRSS_View::appendScript(Minz_Url::display('/scripts/category.js?' . @filemtime(PUBLIC_PATH . '/scripts/category.js')));
|
|
FreshRSS_View::appendScript(Minz_Url::display('/scripts/feed.js?' . @filemtime(PUBLIC_PATH . '/scripts/feed.js')));
|
|
FreshRSS_View::prependTitle(_t('sub.title') . ' · ');
|
|
|
|
$this->view->onlyFeedsWithError = Minz_Request::paramTernary('error');
|
|
|
|
$id = Minz_Request::param('id');
|
|
$this->view->displaySlider = false;
|
|
if (false !== $id) {
|
|
$type = Minz_Request::param('type');
|
|
$this->view->displaySlider = true;
|
|
switch ($type) {
|
|
case 'category':
|
|
$categoryDAO = FreshRSS_Factory::createCategoryDao();
|
|
$this->view->category = $categoryDAO->searchById($id);
|
|
break;
|
|
default:
|
|
$feedDAO = FreshRSS_Factory::createFeedDao();
|
|
$this->view->feed = $feedDAO->searchById($id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
* configuration 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: 0)
|
|
* Default values are empty strings unless specified.
|
|
*/
|
|
public function feedAction() {
|
|
if (Minz_Request::param('ajax')) {
|
|
$this->view->_layout(false);
|
|
} else {
|
|
FreshRSS_View::appendScript(Minz_Url::display('/scripts/feed.js?' . @filemtime(PUBLIC_PATH . '/scripts/feed.js')));
|
|
}
|
|
|
|
$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;
|
|
}
|
|
|
|
$feed = $this->view->feeds[$id];
|
|
$this->view->feed = $feed;
|
|
|
|
FreshRSS_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $feed->name() . ' · ');
|
|
|
|
if (Minz_Request::isPost()) {
|
|
$user = trim(Minz_Request::param('http_user_feed' . $id, ''));
|
|
$pass = trim(Minz_Request::param('http_pass_feed' . $id, ''));
|
|
|
|
$httpAuth = '';
|
|
if ($user !== '' && $pass !== '') { //TODO: Sanitize
|
|
$httpAuth = $user . ':' . $pass;
|
|
}
|
|
|
|
$feed->_ttl(intval(Minz_Request::param('ttl', FreshRSS_Feed::TTL_DEFAULT)));
|
|
$feed->_mute(boolval(Minz_Request::param('mute', false)));
|
|
|
|
$feed->_attributes('read_upon_gone', Minz_Request::paramTernary('read_upon_gone'));
|
|
$feed->_attributes('mark_updated_article_unread', Minz_Request::paramTernary('mark_updated_article_unread'));
|
|
$feed->_attributes('read_upon_reception', Minz_Request::paramTernary('read_upon_reception'));
|
|
$feed->_attributes('clear_cache', Minz_Request::paramTernary('clear_cache'));
|
|
|
|
$keep_max_n_unread = intval(Minz_Request::param('keep_max_n_unread', 0));
|
|
$feed->_attributes('keep_max_n_unread', $keep_max_n_unread > 0 ? $keep_max_n_unread : null);
|
|
|
|
$read_when_same_title_in_feed = Minz_Request::param('read_when_same_title_in_feed', '');
|
|
if ($read_when_same_title_in_feed === '') {
|
|
$read_when_same_title_in_feed = null;
|
|
} else {
|
|
$read_when_same_title_in_feed = intval($read_when_same_title_in_feed);
|
|
if ($read_when_same_title_in_feed <= 0) {
|
|
$read_when_same_title_in_feed = false;
|
|
}
|
|
}
|
|
$feed->_attributes('read_when_same_title_in_feed', $read_when_same_title_in_feed);
|
|
|
|
$cookie = Minz_Request::param('curl_params_cookie', '');
|
|
$cookie_file = Minz_Request::paramBoolean('curl_params_cookiefile');
|
|
$max_redirs = intval(Minz_Request::param('curl_params_redirects', 0));
|
|
$useragent = Minz_Request::param('curl_params_useragent', '');
|
|
$proxy_address = Minz_Request::param('curl_params', '');
|
|
$proxy_type = Minz_Request::param('proxy_type', '');
|
|
$opts = [];
|
|
if ($proxy_address !== '' && $proxy_type !== '' && in_array($proxy_type, [0, 2, 4, 5, 6, 7])) {
|
|
$opts[CURLOPT_PROXY] = $proxy_address;
|
|
$opts[CURLOPT_PROXYTYPE] = intval($proxy_type);
|
|
}
|
|
if ($cookie !== '') {
|
|
$opts[CURLOPT_COOKIE] = $cookie;
|
|
}
|
|
if ($cookie_file) {
|
|
// Pass empty cookie file name to enable the libcurl cookie engine
|
|
// without reading any existing cookie data.
|
|
$opts[CURLOPT_COOKIEFILE] = '';
|
|
}
|
|
if ($max_redirs != 0) {
|
|
$opts[CURLOPT_MAXREDIRS] = $max_redirs;
|
|
$opts[CURLOPT_FOLLOWLOCATION] = 1;
|
|
}
|
|
if ($useragent !== '') {
|
|
$opts[CURLOPT_USERAGENT] = $useragent;
|
|
}
|
|
$feed->_attributes('curl_params', empty($opts) ? null : $opts);
|
|
|
|
$feed->_attributes('content_action', Minz_Request::param('content_action', 'replace', true));
|
|
|
|
$feed->_attributes('ssl_verify', Minz_Request::paramTernary('ssl_verify'));
|
|
$timeout = intval(Minz_Request::param('timeout', 0));
|
|
$feed->_attributes('timeout', $timeout > 0 ? $timeout : null);
|
|
|
|
if (Minz_Request::paramBoolean('use_default_purge_options')) {
|
|
$feed->_attributes('archiving', null);
|
|
} else {
|
|
if (!Minz_Request::paramBoolean('enable_keep_max')) {
|
|
$keepMax = false;
|
|
} elseif (!$keepMax = Minz_Request::param('keep_max')) {
|
|
$keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT;
|
|
}
|
|
if ($enableRetentionPeriod = Minz_Request::paramBoolean('enable_keep_period')) {
|
|
$keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD;
|
|
if (is_numeric(Minz_Request::param('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::param('keep_period_unit'))) {
|
|
$keepPeriod = str_replace('1', Minz_Request::param('keep_period_count'), Minz_Request::param('keep_period_unit'));
|
|
}
|
|
} else {
|
|
$keepPeriod = false;
|
|
}
|
|
$feed->_attributes('archiving', [
|
|
'keep_period' => $keepPeriod,
|
|
'keep_max' => $keepMax,
|
|
'keep_min' => intval(Minz_Request::param('keep_min', 0)),
|
|
'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'),
|
|
'keep_labels' => Minz_Request::paramBoolean('keep_labels'),
|
|
'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'),
|
|
]);
|
|
}
|
|
|
|
$feed->_filtersAction('read', preg_split('/[\n\r]+/', Minz_Request::param('filteractions_read', '')));
|
|
|
|
$feed->_kind(intval(Minz_Request::param('feed_kind', FreshRSS_Feed::KIND_RSS)));
|
|
if ($feed->kind() == FreshRSS_Feed::KIND_HTML_XPATH) {
|
|
$xPathSettings = [];
|
|
if (Minz_Request::param('xPathItem', '') != '') $xPathSettings['item'] = Minz_Request::param('xPathItem', '', true);
|
|
if (Minz_Request::param('xPathItemTitle', '') != '') $xPathSettings['itemTitle'] = Minz_Request::param('xPathItemTitle', '', true);
|
|
if (Minz_Request::param('xPathItemContent', '') != '') $xPathSettings['itemContent'] = Minz_Request::param('xPathItemContent', '', true);
|
|
if (Minz_Request::param('xPathItemUri', '') != '') $xPathSettings['itemUri'] = Minz_Request::param('xPathItemUri', '', true);
|
|
if (Minz_Request::param('xPathItemAuthor', '') != '') $xPathSettings['itemAuthor'] = Minz_Request::param('xPathItemAuthor', '', true);
|
|
if (Minz_Request::param('xPathItemTimestamp', '') != '') $xPathSettings['itemTimestamp'] = Minz_Request::param('xPathItemTimestamp', '', true);
|
|
if (Minz_Request::param('xPathItemTimeFormat', '') != '') $xPathSettings['itemTimeFormat'] = Minz_Request::param('xPathItemTimeFormat', '', true);
|
|
if (Minz_Request::param('xPathItemThumbnail', '') != '') $xPathSettings['itemThumbnail'] = Minz_Request::param('xPathItemThumbnail', '', true);
|
|
if (Minz_Request::param('xPathItemCategories', '') != '') $xPathSettings['itemCategories'] = Minz_Request::param('xPathItemCategories', '', true);
|
|
if (Minz_Request::param('xPathItemUid', '') != '') $xPathSettings['itemUid'] = Minz_Request::param('xPathItemUid', '', true);
|
|
if (!empty($xPathSettings)) {
|
|
$feed->_attributes('xpath', $xPathSettings);
|
|
}
|
|
}
|
|
|
|
$feed->_attributes('path_entries_filter', Minz_Request::param('path_entries_filter', '', true));
|
|
|
|
$values = array(
|
|
'name' => Minz_Request::param('name', ''),
|
|
'kind' => $feed->kind(),
|
|
'description' => sanitizeHTML(Minz_Request::param('description', '', true)),
|
|
'website' => checkUrl(Minz_Request::param('website', '')),
|
|
'url' => checkUrl(Minz_Request::param('url', '')),
|
|
'category' => intval(Minz_Request::param('category', 0)),
|
|
'pathEntries' => Minz_Request::param('path_entries', ''),
|
|
'priority' => intval(Minz_Request::param('priority', FreshRSS_Feed::PRIORITY_MAIN_STREAM)),
|
|
'httpAuth' => $httpAuth,
|
|
'ttl' => $feed->ttl(true),
|
|
'attributes' => $feed->attributes(),
|
|
);
|
|
|
|
invalidateHttpCache();
|
|
|
|
$from = Minz_Request::param('from');
|
|
switch ($from) {
|
|
case 'stats':
|
|
$url_redirect = array('c' => 'stats', 'a' => 'idle', 'params' => array('id' => $id, 'from' => 'stats'));
|
|
break;
|
|
case 'normal':
|
|
case 'reader':
|
|
$get = Minz_Request::param('get');
|
|
if ($get) {
|
|
$url_redirect = array('c' => 'index', 'a' => $from, 'params' => array('get' => $get));
|
|
} else {
|
|
$url_redirect = array('c' => 'index', 'a' => $from);
|
|
}
|
|
break;
|
|
default:
|
|
$url_redirect = array('c' => 'subscription', 'params' => array('id' => $id));
|
|
}
|
|
|
|
if ($values['url'] != '' && $feedDAO->updateFeed($id, $values) !== false) {
|
|
$feed->_categoryId($values['category']);
|
|
// update url and website values for faviconPrepare
|
|
$feed->_url($values['url'], false);
|
|
$feed->_website($values['website'], false);
|
|
$feed->faviconPrepare();
|
|
|
|
Minz_Request::good(_t('feedback.sub.feed.updated'), $url_redirect);
|
|
} else {
|
|
if ($values['url'] == '') {
|
|
Minz_Log::warning('Invalid feed URL!');
|
|
}
|
|
Minz_Request::bad(_t('feedback.sub.feed.error'), $url_redirect);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function categoryAction() {
|
|
$this->view->_layout(false);
|
|
|
|
$categoryDAO = FreshRSS_Factory::createCategoryDao();
|
|
|
|
$id = Minz_Request::param('id');
|
|
$category = $categoryDAO->searchById($id);
|
|
if ($id === false || null === $category) {
|
|
Minz_Error::error(404);
|
|
return;
|
|
}
|
|
$this->view->category = $category;
|
|
|
|
if (Minz_Request::isPost()) {
|
|
if (Minz_Request::paramBoolean('use_default_purge_options')) {
|
|
$category->_attributes('archiving', null);
|
|
} else {
|
|
if (!Minz_Request::paramBoolean('enable_keep_max')) {
|
|
$keepMax = false;
|
|
} elseif (!$keepMax = Minz_Request::param('keep_max')) {
|
|
$keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT;
|
|
}
|
|
if ($enableRetentionPeriod = Minz_Request::paramBoolean('enable_keep_period')) {
|
|
$keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD;
|
|
if (is_numeric(Minz_Request::param('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::param('keep_period_unit'))) {
|
|
$keepPeriod = str_replace('1', Minz_Request::param('keep_period_count'), Minz_Request::param('keep_period_unit'));
|
|
}
|
|
} else {
|
|
$keepPeriod = false;
|
|
}
|
|
$category->_attributes('archiving', [
|
|
'keep_period' => $keepPeriod,
|
|
'keep_max' => $keepMax,
|
|
'keep_min' => intval(Minz_Request::param('keep_min', 0)),
|
|
'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'),
|
|
'keep_labels' => Minz_Request::paramBoolean('keep_labels'),
|
|
'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'),
|
|
]);
|
|
}
|
|
|
|
$position = Minz_Request::param('position');
|
|
$category->_attributes('position', '' === $position ? null : (int) $position);
|
|
|
|
$opml_url = checkUrl(Minz_Request::param('opml_url', ''));
|
|
if ($opml_url != '') {
|
|
$category->_kind(FreshRSS_Category::KIND_DYNAMIC_OPML);
|
|
$category->_attributes('opml_url', $opml_url);
|
|
} else {
|
|
$category->_kind(FreshRSS_Category::KIND_NORMAL);
|
|
$category->_attributes('opml_url', null);
|
|
}
|
|
|
|
$values = [
|
|
'kind' => $category->kind(),
|
|
'name' => Minz_Request::param('name', ''),
|
|
'attributes' => $category->attributes(),
|
|
];
|
|
|
|
invalidateHttpCache();
|
|
|
|
$url_redirect = array('c' => 'subscription', 'params' => array('id' => $id, 'type' => 'category'));
|
|
if (false !== $categoryDAO->updateCategory($id, $values)) {
|
|
Minz_Request::good(_t('feedback.sub.category.updated'), $url_redirect);
|
|
} else {
|
|
Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This action displays the bookmarklet page.
|
|
*/
|
|
public function bookmarkletAction() {
|
|
FreshRSS_View::prependTitle(_t('sub.title.subscription_tools') . ' . ');
|
|
}
|
|
|
|
/**
|
|
* This action displays the page to add a new feed
|
|
*/
|
|
public function addAction() {
|
|
FreshRSS_View::appendScript(Minz_Url::display('/scripts/feed.js?' . @filemtime(PUBLIC_PATH . '/scripts/feed.js')));
|
|
FreshRSS_View::prependTitle(_t('sub.title.add') . ' . ');
|
|
}
|
|
}
|