aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2021-03-24 19:04:51 +0100
committerGravatar GitHub <noreply@github.com> 2021-03-24 19:04:51 +0100
commitde40f3ad56b99b6128e8d9d207f5c5304ae97393 (patch)
tree7755eac081f32ba87445ec82a2a740ea4a1865eb
parent06fa51448336d8ad95d70e7cd96e4c3f4e30907a (diff)
Fix TT-RSS import (#3553)
-rw-r--r--app/Controllers/importExportController.php28
-rw-r--r--app/Models/DatabaseDAO.php5
-rw-r--r--app/Models/EntryDAO.php11
-rw-r--r--app/Services/ImportService.php6
4 files changed, 37 insertions, 13 deletions
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 3550ba0dd..f3b898df4 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -189,7 +189,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
private static function guessFileType($filename) {
if (substr_compare($filename, '.zip', -4) === 0) {
return 'zip';
- } elseif (substr_compare($filename, '.opml', -5) === 0) {
+ } elseif (stripos($filename, 'opml') !== false) {
return 'opml';
} elseif (substr_compare($filename, '.json', -5) === 0) {
if (strpos($filename, 'starred') !== false) {
@@ -208,11 +208,15 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
}
private function ttrssXmlToJson($xml) {
- $table = (array)simplexml_load_string($xml, null, LIBXML_NOCDATA);
+ $table = (array)simplexml_load_string($xml, null, LIBXML_NOBLANKS | LIBXML_NOCDATA);
$table['items'] = isset($table['article']) ? $table['article'] : array();
unset($table['article']);
for ($i = count($table['items']) - 1; $i >= 0; $i--) {
$item = (array)($table['items'][$i]);
+ $item = array_filter($item, function ($v) {
+ // Filter out empty properties, potentially reported as empty objects
+ return (is_string($v) && trim($v) !== '') || !empty($v);
+ });
$item['updated'] = isset($item['updated']) ? strtotime($item['updated']) : '';
$item['published'] = $item['updated'];
$item['content'] = array('content' => isset($item['content']) ? $item['content'] : '');
@@ -274,8 +278,14 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
// First, we check feeds of articles are in DB (and add them if needed).
foreach ($items as $item) {
- if (!isset($item['origin'])) {
- $item['origin'] = array('title' => 'Import');
+ if (empty($item['id'])) {
+ continue;
+ }
+ if (empty($item['origin'])) {
+ $item['origin'] = [];
+ }
+ if (empty($item['origin']['title']) || trim($item['origin']['title']) === '') {
+ $item['origin']['title'] = 'Import';
}
if (!empty($item['origin']['feedUrl'])) {
$feedUrl = $item['origin']['feedUrl'];
@@ -338,7 +348,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$newGuids = array();
$this->entryDAO->beginTransaction();
foreach ($items as $item) {
- if (empty($article_to_feed[$item['id']])) {
+ if (empty($item['id']) || empty($article_to_feed[$item['id']])) {
// Related feed does not exist for this entry, do nothing.
continue;
}
@@ -349,7 +359,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$is_read = null;
$tags = empty($item['categories']) ? array() : $item['categories'];
$labels = array();
- for ($i = count($tags) - 1; $i >= 0; $i --) {
+ for ($i = count($tags) - 1; $i >= 0; $i--) {
$tag = trim($tags[$i]);
if (strpos($tag, 'user/-/') !== false) {
if ($tag === 'user/-/state/com.google/starred') {
@@ -383,6 +393,8 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
$url = '';
}
+ $title = empty($item['title']) ? $url : $item['title'];
+
if (!empty($item['content']['content'])) {
$content = $item['content']['content'];
} elseif (!empty($item['summary']['content'])) {
@@ -408,7 +420,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
}
$entry = new FreshRSS_Entry(
- $feed_id, $item['id'], $item['title'], $author,
+ $feed_id, $item['id'], $title, $author,
$content, $url, $published, $is_read, $is_starred
);
$entry->_id(uTimeString());
@@ -493,7 +505,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
} elseif (!empty($origin['feedUrl'])) {
$website = $origin['feedUrl'];
}
- $name = empty($origin['title']) ? '' : $origin['title'];
+ $name = empty($origin['title']) ? $website : $origin['title'];
try {
// Create a Feed object and add it in database.
diff --git a/app/Models/DatabaseDAO.php b/app/Models/DatabaseDAO.php
index 4bda44268..86f72b14c 100644
--- a/app/Models/DatabaseDAO.php
+++ b/app/Models/DatabaseDAO.php
@@ -10,6 +10,11 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
const ER_BAD_TABLE_ERROR = '42S02';
const ER_DATA_TOO_LONG = '1406';
+ /**
+ * Based on SQLite SQLITE_MAX_VARIABLE_NUMBER
+ */
+ const MAX_VARIABLE_NUMBER = 998;
+
//MySQL InnoDB maximum index length for UTF8MB4
//https://dev.mysql.com/doc/refman/8.0/en/innodb-restrictions.html
const LENGTH_INDEX_UNICODE = 191;
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index c641878ad..9ed1d564d 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -989,8 +989,16 @@ SQL;
}
public function listHashForFeedGuids($id_feed, $guids) {
+ $result = [];
if (count($guids) < 1) {
- return array();
+ return $result;
+ } elseif (count($guids) > FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER) {
+ // Split a query with too many variables parameters
+ $guidsChunks = array_chunk($guids, FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER, true);
+ foreach ($guidsChunks as $guidsChunk) {
+ $result += $this->listHashForFeedGuids($id_feed, $guidsChunk);
+ }
+ return $result;
}
$guids = array_unique($guids);
$sql = 'SELECT guid, ' . $this->sqlHexEncode('hash') .
@@ -999,7 +1007,6 @@ SQL;
$values = array($id_feed);
$values = array_merge($values, $guids);
if ($stm && $stm->execute($values)) {
- $result = array();
$rows = $stm->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$result[$row['guid']] = $row['hex_hash'];
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index 973cd7825..635613475 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -67,8 +67,8 @@ class FreshRSS_Import_Service {
//Sort with categories first
usort($opml_elements, function ($a, $b) {
return strcmp(
- (isset($a['xmlUrl']) ? 'Z' : 'A') . $a['text'],
- (isset($b['xmlUrl']) ? 'Z' : 'A') . $b['text']);
+ (isset($a['xmlUrl']) ? 'Z' : 'A') . (isset($a['text']) ? $a['text'] : ''),
+ (isset($b['xmlUrl']) ? 'Z' : 'A') . (isset($b['text']) ? $b['text'] : ''));
});
foreach ($opml_elements as $elt) {
@@ -86,7 +86,7 @@ class FreshRSS_Import_Service {
} else {
$ok = false;
}
- } else {
+ } elseif (!empty($elt['text'])) {
// No xmlUrl? It should be a category!
$limit_reached = ($nb_cats >= $limits['max_categories']);
if (!FreshRSS_Context::$isCli && $limit_reached) {