diff --git a/CHANGELOG b/CHANGELOG index 93cea5e..dedc22d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,10 +9,12 @@ New features: - Command-line functionality for managing Miniflux login tokens Bug fixes: +- Further relax Fever HTTP correctness, to fix more clients - Use icons specified in Atom feeds when available - Do not return null as subscription unread count - Explicitly forbid U+003A COLON and control characters in usernames, for compatibility with RFC 7617 +- Never return 401 in response to an OPTIONS request - Accept "t" and "f" as booleans in Tiny Tiny RSS Changes: diff --git a/lib/Database.php b/lib/Database.php index b3b2b22..776b46d 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -801,11 +801,11 @@ class Database { f.modified as edited, s.modified as modified, f.next_fetch, - i.id as icon_id, + case when i.data is not null then i.id end as icon_id, i.url as icon_url, folder, t.top as top_folder, d.name as folder_name, dt.name as top_folder_name, coalesce(s.title, f.title) as title, - coalesce((articles - hidden - marked), articles) as unread + coalesce((articles - hidden - marked), coalesce(articles,0)) as unread FROM arsse_subscriptions as s join arsse_feeds as f on f.id = s.feed left join topmost as t on t.f_id = s.folder diff --git a/tests/cases/Database/SeriesSubscription.php b/tests/cases/Database/SeriesSubscription.php index b029846..625ac39 100644 --- a/tests/cases/Database/SeriesSubscription.php +++ b/tests/cases/Database/SeriesSubscription.php @@ -47,9 +47,11 @@ trait SeriesSubscription { 'columns' => [ 'id' => "int", 'url' => "str", + 'data' => "blob", ], 'rows' => [ - [1,"http://example.com/favicon.ico"], + [1,"http://example.com/favicon.ico", "ICON DATA"], + [2,"http://example.net/favicon.ico", null], ], ], 'arsse_feeds' => [ @@ -66,7 +68,8 @@ trait SeriesSubscription { 'rows' => [ [1,"http://example.com/feed1", "Ook", "", "",strtotime("now"),strtotime("now"),null], [2,"http://example.com/feed2", "eek", "", "",strtotime("now - 1 hour"),strtotime("now - 1 hour"),1], - [3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),null], + [3,"http://example.com/feed3", "Ack", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),2], + [4,"http://example.com/feed4", "Foo", "", "",strtotime("now + 1 hour"),strtotime("now + 1 hour"),null], ], ], 'arsse_subscriptions' => [ @@ -88,6 +91,7 @@ trait SeriesSubscription { [3,"john.doe@example.com",3,"Ook",2,0,1,null,null,0], [4,"jill.doe@example.com",2,null,null,0,0,null,null,0], [5,"jack.doe@example.com",2,null,null,1,2,"","3|E",0], + [6,"john.doe@example.com",4,"Bar",3,0,0,null,null,0], ], ], 'arsse_tags' => [ @@ -329,6 +333,8 @@ trait SeriesSubscription { 'unread' => 4, 'pinned' => 1, 'order_type' => 2, + 'icon_url' => "http://example.com/favicon.ico", + 'icon_id' => 1, ], [ 'url' => "http://example.com/feed3", @@ -340,6 +346,21 @@ trait SeriesSubscription { 'unread' => 2, 'pinned' => 0, 'order_type' => 1, + 'icon_url' => "http://example.net/favicon.ico", + 'icon_id' => null, + ], + [ + 'url' => "http://example.com/feed4", + 'title' => "Bar", + 'folder' => 3, + 'top_folder' => 1, + 'folder_name' => "Rocketry", + 'top_folder_name' => "Technology", + 'unread' => 0, + 'pinned' => 0, + 'order_type' => 0, + 'icon_url' => null, + 'icon_id' => null, ], ]; $this->assertResult($exp, Arsse::$db->subscriptionList($this->user)); @@ -375,7 +396,7 @@ trait SeriesSubscription { $this->assertResult($exp, Arsse::$db->subscriptionList($this->user, null, false)); } - public function testListSubscriptionsWithoutRecursion(): void { + public function testListSubscriptionsWithRecursion(): void { $exp = [ [ 'url' => "http://example.com/feed3", @@ -396,7 +417,7 @@ trait SeriesSubscription { } public function testCountSubscriptions(): void { - $this->assertSame(2, Arsse::$db->subscriptionCount($this->user)); + $this->assertSame(3, Arsse::$db->subscriptionCount($this->user)); $this->assertSame(1, Arsse::$db->subscriptionCount($this->user, 2)); } @@ -488,7 +509,7 @@ trait SeriesSubscription { $exp = "http://example.com/favicon.ico"; $this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 1)['url']); $this->assertSame($exp, Arsse::$db->subscriptionIcon(null, 2)['url']); - $this->assertSame(null, Arsse::$db->subscriptionIcon(null, 3)); + $this->assertSame(null, Arsse::$db->subscriptionIcon(null, 6)); } public function testRetrieveTheFaviconOfAMissingSubscription(): void { @@ -500,7 +521,7 @@ trait SeriesSubscription { $exp = "http://example.com/favicon.ico"; $user = "john.doe@example.com"; $this->assertSame($exp, Arsse::$db->subscriptionIcon($user, 1)['url']); - $this->assertSame(null, Arsse::$db->subscriptionIcon($user, 3)); + $this->assertSame(null, Arsse::$db->subscriptionIcon($user, 6)); $user = "jane.doe@example.com"; $this->assertSame($exp, Arsse::$db->subscriptionIcon($user, 2)['url']); } diff --git a/tests/cases/REST/Fever/TestAPI.php b/tests/cases/REST/Fever/TestAPI.php index 3128c44..0868d13 100644 --- a/tests/cases/REST/Fever/TestAPI.php +++ b/tests/cases/REST/Fever/TestAPI.php @@ -425,8 +425,8 @@ class TestAPI extends \JKingWeb\Arsse\Test\AbstractTest { 'Not an API request' => ["", "", "POST", null, new EmptyResponse(404)], 'Wrong method' => ["api", "", "PUT", null, new EmptyResponse(405, ['Allow' => "OPTIONS,POST"])], 'Non-standard method' => ["api", "", "GET", null, new JsonResponse([])], - 'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", new EmptyResponse(415, ['Accept' => "application/x-www-form-urlencoded, multipart/form-data"])], - 'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", new JsonResponse([])], + 'Wrong content type' => ["api", '{"api_key":"validToken"}', "POST", "application/json", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this + 'Non-standard content type' => ["api", '{"api_key":"validToken"}', "POST", "multipart/form-data; boundary=33b68964f0de4c1f-5144aa6caaa6e4a8-18bfaf416a1786c8-5c5053a45f221bc1", new JsonResponse([])], // some clients send nonsensical content types; Fever seems to have allowed this ]; }