From b552abb3327f09baa1c0f4e821dc9f6bd6ef738e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 1 May 2018 17:02:11 +0200 Subject: [PATCH] JSON column for feeds (#1838) * Draft of JSON column for feeds https://github.com/FreshRSS/FreshRSS/issues/1654 * Add some per-feed options * Feed cURL timeout * Mark updated articles as read https://github.com/FreshRSS/FreshRSS/issues/891 * Mark as read upon reception https://github.com/FreshRSS/FreshRSS/issues/1702 * Ignore SSL (unsafe) https://github.com/FreshRSS/FreshRSS/issues/1811 * Try PHPCS workaround While waiting for a better syntax support --- app/Controllers/feedController.php | 15 +++-- app/Controllers/subscriptionController.php | 19 ++++-- app/Models/DatabaseDAO.php | 2 +- app/Models/Factory.php | 8 ++- app/Models/Feed.php | 26 +++++++- app/Models/FeedDAO.php | 73 +++++++++++++++++++--- app/Models/FeedDAOSQLite.php | 17 +++++ app/SQL/install.sql.mysql.php | 1 + app/SQL/install.sql.pgsql.php | 1 + app/SQL/install.sql.sqlite.php | 1 + app/i18n/cz/sub.php | 2 + app/i18n/de/sub.php | 2 + app/i18n/en/sub.php | 2 + app/i18n/es/sub.php | 2 + app/i18n/fr/sub.php | 2 + app/i18n/he/sub.php | 2 + app/i18n/it/sub.php | 2 + app/i18n/kr/sub.php | 2 + app/i18n/nl/sub.php | 2 + app/i18n/pt-br/sub.php | 2 + app/i18n/ru/sub.php | 2 + app/i18n/tr/sub.php | 2 + app/i18n/zh-cn/sub.php | 2 + app/views/helpers/feed/update.phtml | 47 ++++++++++++++ lib/Minz/ModelPdo.php | 4 +- lib/Minz/Request.php | 13 ++++ lib/lib_rss.php | 15 ++++- 27 files changed, 242 insertions(+), 26 deletions(-) create mode 100644 app/Models/FeedDAOSQLite.php diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 59c22b777..ca85e7cb8 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -84,6 +84,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController { 'description' => $feed->description(), 'lastUpdate' => time(), 'httpAuth' => $feed->httpAuth(), + 'attributes' => array(), ); $id = $feedDAO->addFeed($values); @@ -271,7 +272,6 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $updated_feeds = 0; $nb_new_articles = 0; - $is_read = FreshRSS_Context::$user_conf->mark_when['reception'] ? 1 : 0; foreach ($feeds as $feed) { $url = $feed->url(); //For detection of HTTP 301 @@ -353,8 +353,10 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } else { //This entry already exists but has been updated //Minz_Log::debug('Entry with GUID `' . $entry->guid() . '` updated in feed ' . $feed->id() . //', old hash ' . $existingHash . ', new hash ' . $entry->hash()); - //TODO: Make an updated/is_read policy by feed, in addition to the global one. - $needFeedCacheRefresh = FreshRSS_Context::$user_conf->mark_updated_article_unread; + $mark_updated_article_unread = $feed->attributes('mark_updated_article_unread') !== null ? ( + $feed->attributes('mark_updated_article_unread') + ) : FreshRSS_Context::$user_conf->mark_updated_article_unread; + $needFeedCacheRefresh = $mark_updated_article_unread; $entry->_isRead(FreshRSS_Context::$user_conf->mark_updated_article_unread ? false : null); //Change is_read according to policy. if (!$entryDAO->inTransaction()) { $entryDAO->beginTransaction(); @@ -365,15 +367,18 @@ class FreshRSS_feed_Controller extends Minz_ActionController { // This entry should not be added considering configuration and date. $oldGuids[] = $entry->guid(); } else { + $read_upon_reception = $feed->attributes('read_upon_reception') !== null ? ( + $feed->attributes('read_upon_reception') + ) : FreshRSS_Context::$user_conf->mark_when['reception']; if ($isNewFeed) { $id = min(time(), $entry_date) . uSecString(); - $entry->_isRead($is_read); + $entry->_isRead($read_upon_reception); } elseif ($entry_date < $date_min) { $id = min(time(), $entry_date) . uSecString(); $entry->_isRead(true); //Old article that was not in database. Probably an error, so mark as read } else { $id = uTimeString(); - $entry->_isRead($is_read); + $entry->_isRead($read_upon_reception); } $entry->_id($id); diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index 37efd3b57..860cd912f 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -15,7 +15,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { } $catDAO = new FreshRSS_CategoryDAO(); - $feedDAO = new FreshRSS_FeedDAO(); + $feedDAO = FreshRSS_Factory::createFeedDao(); $catDAO->checkDefault(); $feedDAO->updateTTL(); @@ -74,9 +74,10 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { return; } - $this->view->feed = $this->view->feeds[$id]; + $feed = $this->view->feeds[$id]; + $this->view->feed = $feed; - Minz_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $this->view->feed->name() . ' · '); + Minz_View::prependTitle(_t('sub.title.feed_management') . ' · ' . $feed->name() . ' · '); if (Minz_Request::isPost()) { $user = trim(Minz_Request::param('http_user_feed' . $id, '')); @@ -95,6 +96,13 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { $ttl = FreshRSS_Context::$user_conf->ttl_default; } + $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('ssl_verify', Minz_Request::paramTernary('ssl_verify')); + + $timeout = intval(Minz_Request::param('timeout', 0)); + $feed->_attributes('timeout', $timeout > 0 ? $timeout : null); + $values = array( 'name' => Minz_Request::param('name', ''), 'description' => sanitizeHTML(Minz_Request::param('description', '', true)), @@ -106,14 +114,15 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { 'httpAuth' => $httpAuth, 'keep_history' => intval(Minz_Request::param('keep_history', FreshRSS_Feed::KEEP_HISTORY_DEFAULT)), 'ttl' => $ttl * ($mute ? -1 : 1), + 'attributes' => $feed->attributes() ); 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(); + $feed->_category($cat); + $feed->faviconPrepare(); Minz_Request::good(_t('feedback.sub.feed.updated'), $url_redirect); } else { diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php index f5469f2b7..b8e5577e4 100644 --- a/app/Models/DatabaseDAO.php +++ b/app/Models/DatabaseDAO.php @@ -50,7 +50,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo { public function feedIsCorrect() { return $this->checkTable('feed', array( 'id', 'url', 'category', 'name', 'website', 'description', 'lastUpdate', - 'priority', 'pathEntries', 'httpAuth', 'error', 'keep_history', 'ttl', + 'priority', 'pathEntries', 'httpAuth', 'error', 'keep_history', 'ttl', 'attributes', 'cache_nbEntries', 'cache_nbUnreads' )); } diff --git a/app/Models/Factory.php b/app/Models/Factory.php index dfccc883e..764987c46 100644 --- a/app/Models/Factory.php +++ b/app/Models/Factory.php @@ -3,7 +3,13 @@ class FreshRSS_Factory { public static function createFeedDao($username = null) { - return new FreshRSS_FeedDAO($username); + $conf = Minz_Configuration::get('system'); + switch ($conf->db['type']) { + case 'sqlite': + return new FreshRSS_FeedDAOSQLite($username); + default: + return new FreshRSS_FeedDAO($username); + } } public static function createEntryDao($username = null) { diff --git a/app/Models/Feed.php b/app/Models/Feed.php index 196d94931..04101c10d 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -26,6 +26,7 @@ class FreshRSS_Feed extends Minz_Model { private $error = false; private $keep_history = self::KEEP_HISTORY_DEFAULT; private $ttl = self::TTL_DEFAULT; + private $attributes = array(); private $mute = false; private $hash = null; private $lockPath = ''; @@ -114,6 +115,13 @@ class FreshRSS_Feed extends Minz_Model { public function ttl() { return $this->ttl; } + public function attributes($key = '') { + if ($key == '') { + return $this->attributes; + } else { + return isset($this->attributes[$key]) ? $this->attributes[$key] : null; + } + } public function mute() { return $this->mute; } @@ -234,6 +242,22 @@ class FreshRSS_Feed extends Minz_Model { $this->ttl = abs($value); $this->mute = $value < self::TTL_DEFAULT; } + + public function _attributes($key, $value) { + if ($key == '') { + if (is_string($value)) { + $value = json_decode($value, true); + } + if (is_array($value)) { + $this->attributes = $value; + } + } elseif ($value === null) { + unset($this->attributes[$key]); + } else { + $this->attributes[$key] = $value; + } + } + public function _nbNotRead($value) { $this->nbNotRead = intval($value); } @@ -253,7 +277,7 @@ class FreshRSS_Feed extends Minz_Model { if ($this->httpAuth != '') { $url = preg_replace('#((.+)://)(.+)#', '${1}' . $this->httpAuth . '@${3}', $url); } - $feed = customSimplePie(); + $feed = customSimplePie($this->attributes()); if (substr($url, -11) === '#force_feed') { $feed->force_feed(true); $url = substr($url, 0, -11); diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php index 5c6e613d3..f968ae98b 100644 --- a/app/Models/FeedDAO.php +++ b/app/Models/FeedDAO.php @@ -1,6 +1,33 @@ bd->prepare('ALTER TABLE `' . $this->prefix . 'feed` ADD COLUMN attributes TEXT'); + return $stm && $stm->execute(); + } + } catch (Exception $e) { + Minz_Log::error('FreshRSS_FeedDAO::addColumn error: ' . $e->getMessage()); + } + return false; + } + + protected function autoUpdateDb($errorInfo) { + if (isset($errorInfo[0])) { + if ($errorInfo[0] === '42S22' || $errorInfo[0] === '42703') { //ER_BAD_FIELD_ERROR (Mysql), undefined_column (PostgreSQL) + foreach (array('attributes') as $column) { + if (stripos($errorInfo[2], $column) !== false) { + return $this->addColumn($column); + } + } + } + } + return false; + } + public function addFeed($valuesTmp) { $sql = ' INSERT INTO `' . $this->prefix . 'feed` @@ -15,10 +42,11 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { `httpAuth`, error, keep_history, - ttl + ttl, + attributes ) VALUES - (?, ?, ?, ?, ?, ?, 10, ?, 0, ?, ?)'; + (?, ?, ?, ?, ?, ?, 10, ?, 0, ?, ?, ?)'; $stm = $this->bd->prepare($sql); $valuesTmp['url'] = safe_ascii($valuesTmp['url']); @@ -34,12 +62,16 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { base64_encode($valuesTmp['httpAuth']), FreshRSS_Feed::KEEP_HISTORY_DEFAULT, FreshRSS_Feed::TTL_DEFAULT, + isset($valuesTmp['attributes']) ? json_encode($valuesTmp['attributes']) : '', ); if ($stm && $stm->execute($values)) { return $this->bd->lastInsertId('"' . $this->prefix . 'feed_id_seq"'); } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + if ($this->autoUpdateDb($info)) { + return $this->addFeed($valuesTmp); + } Minz_Log::error('SQL error addFeed: ' . $info[2]); return false; } @@ -60,7 +92,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { 'website' => $feed->website(), 'description' => $feed->description(), 'lastUpdate' => 0, - 'httpAuth' => $feed->httpAuth() + 'httpAuth' => $feed->httpAuth(), + 'attributes' => $feed->attributes(), ); $id = $this->addFeed($values); @@ -87,8 +120,10 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { foreach ($valuesTmp as $key => $v) { $set .= '`' . $key . '`=?, '; - if ($key == 'httpAuth') { + if ($key === 'httpAuth') { $valuesTmp[$key] = base64_encode($v); + } elseif ($key === 'attributes') { + $valuesTmp[$key] = json_encode($v); } } $set = substr($set, 0, -2); @@ -105,11 +140,25 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { return $stm->rowCount(); } else { $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo(); + if ($this->autoUpdateDb($info)) { + return $this->updateFeed($id, $valuesTmp); + } Minz_Log::error('SQL error updateFeed: ' . $info[2] . ' for feed ' . $id); return false; } } + public function updateFeedAttribute($feed, $key, $value) { + if ($feed instanceof FreshRSS_Feed) { + $feed->_attributes($key, $value); + return $this->updateFeed( + $feed->id(), + array('attributes' => $feed->attributes()) + ); + } + return false; + } + public function updateLastUpdate($id, $inError = false, $mtime = 0) { //See also updateCachedValue() $sql = 'UPDATE `' . $this->prefix . 'feed` ' . 'SET `lastUpdate`=?, error=? ' @@ -252,15 +301,22 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { */ public function listFeedsOrderUpdate($defaultCacheDuration = 3600) { $this->updateTTL(); - $sql = 'SELECT id, url, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, keep_history, ttl ' + $sql = 'SELECT id, url, name, website, `lastUpdate`, `pathEntries`, `httpAuth`, keep_history, ttl, attributes ' . 'FROM `' . $this->prefix . 'feed` ' . ($defaultCacheDuration < 0 ? '' : 'WHERE ttl >= ' . FreshRSS_Feed::TTL_DEFAULT . ' AND `lastUpdate` < (' . (time() + 60) . '-(CASE WHEN ttl=' . FreshRSS_Feed::TTL_DEFAULT . ' THEN ' . intval($defaultCacheDuration) . ' ELSE ttl END)) ') . 'ORDER BY `lastUpdate`'; $stm = $this->bd->prepare($sql); - $stm->execute(); - - return self::daoToFeed($stm->fetchAll(PDO::FETCH_ASSOC)); + if ($stm && $stm->execute()) { + return self::daoToFeed($stm->fetchAll(PDO::FETCH_ASSOC)); + } else { + $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo(); + if ($this->autoUpdateDb($info)) { + return $this->listFeedsOrderUpdate($defaultCacheDuration); + } + Minz_Log::error('SQL error listFeedsOrderUpdate: ' . $info[2]); + return array(); + } } public function listByCategory($cat) { @@ -385,6 +441,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo implements FreshRSS_Searchable { $myFeed->_error(isset($dao['error']) ? $dao['error'] : 0); $myFeed->_keepHistory(isset($dao['keep_history']) ? $dao['keep_history'] : FreshRSS_Feed::KEEP_HISTORY_DEFAULT); $myFeed->_ttl(isset($dao['ttl']) ? $dao['ttl'] : FreshRSS_Feed::TTL_DEFAULT); + $myFeed->_attributes('', isset($dao['attributes']) ? $dao['attributes'] : ''); $myFeed->_nbNotRead(isset($dao['cache_nbUnreads']) ? $dao['cache_nbUnreads'] : 0); $myFeed->_nbEntries(isset($dao['cache_nbEntries']) ? $dao['cache_nbEntries'] : 0); if (isset($dao['id'])) { diff --git a/app/Models/FeedDAOSQLite.php b/app/Models/FeedDAOSQLite.php new file mode 100644 index 000000000..3c203b378 --- /dev/null +++ b/app/Models/FeedDAOSQLite.php @@ -0,0 +1,17 @@ +bd->query("PRAGMA table_info('feed')")) { + $columns = $tableInfo->fetchAll(PDO::FETCH_COLUMN, 1); + foreach (array('attributes') as $column) { + if (!in_array($column, $columns)) { + return $this->addColumn($column); + } + } + } + return false; + } + +} diff --git a/app/SQL/install.sql.mysql.php b/app/SQL/install.sql.mysql.php index b94a24298..747a0a6b3 100644 --- a/app/SQL/install.sql.mysql.php +++ b/app/SQL/install.sql.mysql.php @@ -24,6 +24,7 @@ CREATE TABLE IF NOT EXISTS `%1$sfeed` ( `error` boolean DEFAULT 0, `keep_history` MEDIUMINT NOT NULL DEFAULT -2, -- v0.7 `ttl` INT NOT NULL DEFAULT 0, -- v0.7.3 + `attributes` TEXT, -- v1.11.0 `cache_nbEntries` int DEFAULT 0, -- v0.7 `cache_nbUnreads` int DEFAULT 0, -- v0.7 PRIMARY KEY (`id`), diff --git a/app/SQL/install.sql.pgsql.php b/app/SQL/install.sql.pgsql.php index 23afdb783..99f5a05d3 100644 --- a/app/SQL/install.sql.pgsql.php +++ b/app/SQL/install.sql.pgsql.php @@ -22,6 +22,7 @@ $SQL_CREATE_TABLES = array( "error" smallint DEFAULT 0, "keep_history" INT NOT NULL DEFAULT -2, "ttl" INT NOT NULL DEFAULT 0, + "attributes" TEXT, -- v1.11.0 "cache_nbEntries" INT DEFAULT 0, "cache_nbUnreads" INT DEFAULT 0, FOREIGN KEY ("category") REFERENCES "%1$scategory" ("id") ON DELETE SET NULL ON UPDATE CASCADE diff --git a/app/SQL/install.sql.sqlite.php b/app/SQL/install.sql.sqlite.php index d8e670bc8..cbfb719e5 100644 --- a/app/SQL/install.sql.sqlite.php +++ b/app/SQL/install.sql.sqlite.php @@ -21,6 +21,7 @@ $SQL_CREATE_TABLES = array( `error` boolean DEFAULT 0, `keep_history` MEDIUMINT NOT NULL DEFAULT -2, `ttl` INT NOT NULL DEFAULT 0, + `attributes` TEXT, -- v1.11.0 `cache_nbEntries` int DEFAULT 0, `cache_nbUnreads` int DEFAULT 0, FOREIGN KEY (`category`) REFERENCES `category`(`id`) ON DELETE SET NULL ON UPDATE CASCADE, diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php index ec77be317..5caf9acbe 100644 --- a/app/i18n/cz/sub.php +++ b/app/i18n/cz/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Zobrazit ve “Všechny kanály”', 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Statistika', 'think_to_add' => 'Můžete přidat kanály.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Název', 'title_add' => 'Přidat RSS kanál', 'ttl' => 'Neobnovovat častěji než', diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index 7f74c275e..0ba818c69 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'In Haupt-Feeds zeigen', 'normal' => 'Zeige in eigener Kategorie', ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Statistiken', 'think_to_add' => 'Sie können Feeds hinzufügen.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Titel', 'title_add' => 'Einen RSS-Feed hinzufügen', 'ttl' => 'Aktualisiere automatisch nicht öfter als', diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index b9bae7955..5ff41a4b3 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Show in main stream', 'normal' => 'Show in its category', ), + 'ssl_verify' => 'Verify SSL security', 'stats' => 'Statistics', 'think_to_add' => 'You may add some feeds.', + 'timeout' => 'Timeout in seconds', 'title' => 'Title', 'title_add' => 'Add a RSS feed', 'ttl' => 'Do not automatically refresh more often than', diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index 091c1e3e3..3abc85578 100755 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -39,8 +39,10 @@ return array( 'main_stream' => 'Mostrar en salida principal', 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Estadísticas', 'think_to_add' => 'Puedes añadir fuentes.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Título', 'title_add' => 'Añadir fuente RSS', 'ttl' => 'No actualizar de forma automática con una frecuencia mayor a', diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index 04be55aa5..c6af2fb90 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Afficher dans le flux principal', 'normal' => 'Afficher dans sa catégorie', ), + 'ssl_verify' => 'Vérification sécurité SSL', 'stats' => 'Statistiques', 'think_to_add' => 'Vous pouvez ajouter des flux.', + 'timeout' => 'Délai d’attente en secondes', 'title' => 'Titre', 'title_add' => 'Ajouter un flux RSS', 'ttl' => 'Ne pas automatiquement rafraîchir plus souvent que', diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index 849a1d5bd..a263cd728 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'הצגה בזרם המרכזי', 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'סטטיסטיקות', 'think_to_add' => 'ניתן להוסיף הזנות חדשות.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'כותרת', 'title_add' => 'הוספת הזנה', 'ttl' => 'אין לרענן אוטומטית יותר מ', diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index 698e64481..22d58a27f 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Mostra in homepage', // TODO 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Statistiche', 'think_to_add' => 'Aggiungi feed.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Titolo', 'title_add' => 'Aggiungi RSS feed', 'ttl' => 'Non aggiornare automaticamente piu di', diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php index e11d4588f..464b64f70 100644 --- a/app/i18n/kr/sub.php +++ b/app/i18n/kr/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => '메인 스트림에 표시하기', 'normal' => '피드가 속한 카테고리에만 표시하기', ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => '통계', 'think_to_add' => '피드를 추가할 수 있습니다.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => '제목', 'title_add' => 'RSS 피드 추가', 'ttl' => '다음 시간이 지나기 전에 새로고침 금지', diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index 6b1ac268b..067e226aa 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -45,8 +45,10 @@ return array( 'normal' => 'Show in its category', // TODO ), 'pubsubhubbub' => 'Directe notificaties met PubSubHubbub', + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Statistieken', 'think_to_add' => 'Voeg wat feeds toe.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Titel', 'title_add' => 'Voeg een RSS feed toe', 'ttl' => 'Vernieuw automatisch niet vaker dan', diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php index 09dde718f..1b084f08f 100644 --- a/app/i18n/pt-br/sub.php +++ b/app/i18n/pt-br/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Mostrar na tela principal', 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Estatísticas', 'think_to_add' => 'Você deve adicionar alguns feeds.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Título', 'title_add' => 'Adicionar o RSS feed', 'ttl' => 'Não atualize automáticamente mais que', diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index 9e360630a..bef49623f 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Show in main stream', // TODO 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'Statistics',// TODO 'think_to_add' => 'You may add some feeds.',// TODO + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Title',// TODO 'title_add' => 'Add a RSS feed',// TODO 'ttl' => 'Do not automatically refresh more often than',// TODO diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index 871731158..e8cd15d0d 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => 'Ana akışda göster', 'normal' => 'Show in its category', // TODO ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => 'İstatistikler', 'think_to_add' => 'Akış ekleyebilirsiniz.', + 'timeout' => 'Timeout in seconds', //TODO 'title' => 'Başlık', 'title_add' => 'RSS akışı ekle', 'ttl' => 'Şu kadar süreden fazla otomatik yenileme yapma', diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index bf73f82c4..034f8a9d9 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -44,8 +44,10 @@ return array( 'main_stream' => '在首页中显示', 'normal' => '在分类中显示', ), + 'ssl_verify' => 'Verify SSL security', //TODO 'stats' => '统计', 'think_to_add' => '你可以添加一些 RSS 源。', + 'timeout' => 'Timeout in seconds', //TODO 'title' => '标题', 'title_add' => '添加 RSS 源', 'ttl' => '最小自动更新时间', diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml index d379c5df8..01c90369c 100644 --- a/app/views/helpers/feed/update.phtml +++ b/app/views/helpers/feed/update.phtml @@ -178,6 +178,53 @@ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php index d769e0ff4..6928a2857 100644 --- a/lib/Minz/ModelPdo.php +++ b/lib/Minz/ModelPdo.php @@ -69,7 +69,7 @@ class Minz_ModelPdo { case 'sqlite': $string = 'sqlite:' . join_path(DATA_PATH, 'users', $currentUser, 'db.sqlite'); $this->prefix = ''; - $this->bd = new MinzPDOMSQLite($string, $db['user'], $db['password'], $driver_options); + $this->bd = new MinzPDOSQLite($string, $db['user'], $db['password'], $driver_options); $this->bd->exec('PRAGMA foreign_keys = ON;'); break; case 'pgsql': @@ -160,7 +160,7 @@ class MinzPDOMySql extends MinzPDO { } } -class MinzPDOMSQLite extends MinzPDO { +class MinzPDOSQLite extends MinzPDO { public function lastInsertId($name = null) { return parent::lastInsertId(); //We discard the name, only used by PostgreSQL } diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index a43509ded..e21697e42 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -39,6 +39,19 @@ class Minz_Request { return $default; } } + public static function paramTernary($key) { + if (isset(self::$params[$key])) { + $p = self::$params[$key]; + $tp = trim($p); + if ($p === null || $tp === '' || $tp === 'null') { + return null; + } elseif ($p == false || $tp == '0' || $tp === 'false' || $tp === 'no') { + return false; + } + return true; + } + return null; + } public static function defaultControllerName() { return self::$default_controller_name; } diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 215c4c362..9dfca385d 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -175,7 +175,7 @@ function html_only_entity_decode($text) { return strtr($text, $htmlEntitiesOnly); } -function customSimplePie() { +function customSimplePie($attributes = array()) { $system_conf = Minz_Configuration::get('system'); $limits = $system_conf->limits; $simplePie = new SimplePie(); @@ -183,8 +183,17 @@ function customSimplePie() { $simplePie->set_syslog($system_conf->simplepie_syslog_enabled); $simplePie->set_cache_location(CACHE_PATH); $simplePie->set_cache_duration($limits['cache_duration']); - $simplePie->set_timeout($limits['timeout']); - $simplePie->set_curl_options($system_conf->curl_options); + + $feed_timeout = empty($attributes['timeout']) ? 0 : intval($attributes['timeout']); + $simplePie->set_timeout($feed_timeout > 0 ? $feed_timeout : $limits['timeout']); + + $curl_options = $system_conf->curl_options; + if (isset($attributes['ssl_verify'])) { + $curl_options[CURLOPT_SSL_VERIFYHOST] = $attributes['ssl_verify'] ? 2 : 0; + $curl_options[CURLOPT_SSL_VERIFYPEER] = $attributes['ssl_verify'] ? true : false; + } + $simplePie->set_curl_options($curl_options); + $simplePie->strip_htmltags(array( 'base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html',