summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--appinfo/database.xml12
-rw-r--r--appinfo/info.xml2
-rw-r--r--controller/feedcontroller.php8
-rw-r--r--css/navigation.css12
-rw-r--r--db/feed.php10
-rw-r--r--fetcher/feedfetcher.php21
-rw-r--r--fetcher/fetcher.php9
-rw-r--r--fetcher/ifeedfetcher.php6
-rw-r--r--fetcher/youtubefetcher.php9
-rw-r--r--js/build/app.min.js6
-rw-r--r--js/controller/NavigationController.js6
-rw-r--r--js/gulpfile.js2
-rw-r--r--js/service/FeedResource.js7
-rw-r--r--js/tests/unit/controller/NavigationControllerSpec.js10
-rw-r--r--js/tests/unit/service/FeedResourceSpec.js16
-rw-r--r--service/feedservice.php16
-rw-r--r--templates/part.navigation.addfeed.php20
-rw-r--r--tests/unit/db/FeedTest.php6
-rw-r--r--tests/unit/service/FeedServiceTest.php7
20 files changed, 155 insertions, 31 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a8932b21e..e1446b487 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@ owncloud-news (7.2.0)
* **New dependency**: Bump required PostgreSQL version to 9.4
* **New dependency**: Bump required MySql/MariaDB version to 5.5
* **Bugfix**: Fix bug that would not lowercase non ASCII characters when searching, #944
+* **Enhancement**: Add HTTP basic auth, #938
owncloud-news (7.1.2)
* **Enhancement**: Major JavaScript library updates:
diff --git a/appinfo/database.xml b/appinfo/database.xml
index a831b4211..9b6b36a3d 100644
--- a/appinfo/database.xml
+++ b/appinfo/database.xml
@@ -154,6 +154,18 @@
<notnull>false</notnull>
</field>
<field>
+ <name>basic_auth_user</name>
+ <type>clob</type>
+ <default></default>
+ <notnull>false</notnull>
+ </field>
+ <field>
+ <name>basic_auth_password</name>
+ <type>clob</type>
+ <default></default>
+ <notnull>false</notnull>
+ </field>
+ <field>
<name>deleted_at</name>
<type>integer</type>
<default>0</default>
diff --git a/appinfo/info.xml b/appinfo/info.xml
index cb58ef86b..38fd91fef 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -7,7 +7,7 @@
<author>Bernhard Posselt, Alessandro Cosentino, Jan-Christoph Borchardt</author>
<category>multimedia</category>
<licence>AGPL</licence>
- <version>7.1.2</version>
+ <version>7.1.3</version>
<namespace>News</namespace>
<!-- resources -->
diff --git a/controller/feedcontroller.php b/controller/feedcontroller.php
index 37e415661..2b95794a3 100644
--- a/controller/feedcontroller.php
+++ b/controller/feedcontroller.php
@@ -124,16 +124,20 @@ class FeedController extends Controller {
* @param string $url
* @param int $parentFolderId
* @param string $title
+ * @param string $user
+ * @param string $password
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
- public function create($url, $parentFolderId, $title){
+ public function create($url, $parentFolderId, $title=null,
+ $user=null, $password=null){
try {
// we need to purge deleted feeds if a feed is created to
// prevent already exists exceptions
$this->feedService->purgeDeleted($this->userId, false);
$feed = $this->feedService->create($url, $parentFolderId,
- $this->userId, $title);
+ $this->userId, $title,
+ $user, $password);
$params = ['feeds' => [$feed]];
try {
diff --git a/css/navigation.css b/css/navigation.css
index 8d2d3a362..d5ea11d7f 100644
--- a/css/navigation.css
+++ b/css/navigation.css
@@ -76,6 +76,18 @@
margin-right: 0;
}
+#app-navigation .add-new-popup .add-feed-advanced {
+ width: 100%;
+}
+
+#app-navigation .add-new-popup .add-feed-advanced-area {
+ padding: 10px 0;
+}
+
+#app-navigation .add-new-popup .add-feed-advanced-area h2 {
+ font-size: 11pt;
+ font-weight: bold;
+}
#app-navigation .add-new-popup .error {
padding: 0 0 10px 0;
diff --git a/db/feed.php b/db/feed.php
index 5e2c7fab0..f78b1f364 100644
--- a/db/feed.php
+++ b/db/feed.php
@@ -56,6 +56,10 @@ use \OCP\AppFramework\Db\Entity;
* @method void setUpdateErrorCount(integer $value)
* @method string getLastUpdateError()
* @method void setLastUpdateError(string $value)
+ * @method string getBasicAuthUser()
+ * @method void setBasicAuthUser(string $value)
+ * @method string getBasicAuthPassword()
+ * @method void setBasicAuthPassword(string $value)
*/
class Feed extends Entity implements IAPI, \JsonSerializable {
@@ -82,6 +86,8 @@ class Feed extends Entity implements IAPI, \JsonSerializable {
protected $updateMode;
protected $updateErrorCount;
protected $lastUpdateError;
+ protected $basicAuthUser;
+ protected $basicAuthPassword;
public function __construct(){
$this->addType('parentId', 'integer');
@@ -123,7 +129,9 @@ class Feed extends Entity implements IAPI, \JsonSerializable {
'pinned',
'updateMode',
'updateErrorCount',
- 'lastUpdateError'
+ 'lastUpdateError',
+ 'basicAuthUser',
+ 'basicAuthPassword'
]);
$url = parse_url($this->link)['host'];
diff --git a/fetcher/feedfetcher.php b/fetcher/feedfetcher.php
index 6b7460679..458f1220d 100644
--- a/fetcher/feedfetcher.php
+++ b/fetcher/feedfetcher.php
@@ -23,6 +23,8 @@ use PicoFeed\Client\InvalidUrlException;
use PicoFeed\Client\MaxRedirectException;
use PicoFeed\Client\MaxSizeException;
use PicoFeed\Client\TimeoutException;
+use PicoFeed\Client\ForbiddenException;
+use PicoFeed\Client\UnauthorizedException;
use OCP\IL10N;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -71,14 +73,24 @@ class FeedFetcher implements IFeedFetcher {
* no results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
+ * @param string $basicAuthUser if given, basic auth is set for this feed
+ * @param string $basicAuthPassword if given, basic auth is set for this
+ * feed. Ignored if user is null or an empty string
* @throws FetcherException if it fails
* @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items
*/
public function fetch($url, $getFavicon=true, $lastModified=null,
- $etag=null, $fullTextEnabled=false) {
+ $etag=null, $fullTextEnabled=false,
+ $basicAuthUser=null, $basicAuthPassword=null) {
try {
- $resource = $this->reader->discover($url, $lastModified, $etag);
+ if ($basicAuthUser !== null && trim($basicAuthUser) !== '') {
+ $resource = $this->reader->discover($url, $lastModified, $etag,
+ $basicAuthUser,
+ $basicAuthPassword);
+ } else {
+ $resource = $this->reader->discover($url, $lastModified, $etag);
+ }
if (!$resource->isModified()) {
return [null, null];
@@ -131,6 +143,11 @@ class FeedFetcher implements IFeedFetcher {
$msg = $this->l10n->t('Bigger than maximum allowed size');
} else if ($ex instanceof TimeoutException) {
$msg = $this->l10n->t('Request timed out');
+ } else if ($ex instanceof UnauthorizedException) {
+ $msg = $this->l10n->t('Required credentials for feed were ' .
+ 'either missing or incorrect');
+ } else if ($ex instanceof ForbiddenException) {
+ $msg = $this->l10n->t('Forbidden to access feed');
}
throw new FetcherException($msg);
diff --git a/fetcher/fetcher.php b/fetcher/fetcher.php
index 4787ccfdd..43c9e7a3f 100644
--- a/fetcher/fetcher.php
+++ b/fetcher/fetcher.php
@@ -44,16 +44,21 @@ class Fetcher {
* no results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
+ * @param string $basicAuthUser if given, basic auth is set for this feed
+ * @param string $basicAuthPassword if given, basic auth is set for this
+ * feed. Ignored if user is null or an empty string
* @throws FetcherException if simple pie fails
* @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items
*/
public function fetch($url, $getFavicon=true, $lastModified=null,
- $etag=null, $fullTextEnabled=false) {
+ $etag=null, $fullTextEnabled=false,
+ $basicAuthUser=null, $basicAuthPassword=null) {
foreach($this->fetchers as $fetcher){
if($fetcher->canHandle($url)){
return $fetcher->fetch($url, $getFavicon, $lastModified, $etag,
- $fullTextEnabled);
+ $fullTextEnabled, $basicAuthUser,
+ $basicAuthPassword);
}
}
diff --git a/fetcher/ifeedfetcher.php b/fetcher/ifeedfetcher.php
index 297885930..e854d83fe 100644
--- a/fetcher/ifeedfetcher.php
+++ b/fetcher/ifeedfetcher.php
@@ -27,12 +27,16 @@ interface IFeedFetcher {
* no results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
+ * @param string $basicAuthUser if given, basic auth is set for this feed
+ * @param string $basicAuthPassword if given, basic auth is set for this
+ * feed. Ignored if user is null or an empty string
* @throws FetcherException if the fetcher encounters a problem
* @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items
*/
function fetch($url, $getFavicon=true, $lastModified=null, $etag=null,
- $fullTextEnabled=false);
+ $fullTextEnabled=false, $basicAuthUser=null,
+ $basicAuthPassword=null);
/**
* @param string $url the url that should be fetched
diff --git a/fetcher/youtubefetcher.php b/fetcher/youtubefetcher.php
index 35ecd80f0..3752ba197 100644
--- a/fetcher/youtubefetcher.php
+++ b/fetcher/youtubefetcher.php
@@ -55,16 +55,21 @@ class YoutubeFetcher implements IFeedFetcher {
* no results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
+ * @param string $basicAuthUser if given, basic auth is set for this feed
+ * @param string $basicAuthPassword if given, basic auth is set for this
+ * feed. Ignored if user is null or an empty string
* @throws FetcherException if it fails
* @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items
*/
public function fetch($url, $getFavicon=true, $lastModified=null,
- $etag=null, $fullTextEnabled=false) {
+ $etag=null, $fullTextEnabled=false,
+ $basicAuthUser=null, $basicAuthPassword=null) {
$transformedUrl = $this->buildUrl($url);
$result = $this->feedFetcher->fetch(
- $transformedUrl, $getFavicon, $lastModified, $etag, $fullTextEnabled
+ $transformedUrl, $getFavicon, $lastModified, $etag,
+ $fullTextEnabled, $basicAuthUser, $basicAuthPassword
);
// reset feed url so we know the correct added url for the feed
diff --git a/js/build/app.min.js b/js/build/app.min.js
index 32ea96774..c2db1412e 100644
--- a/js/build/app.min.js
+++ b/js/build/app.min.js
@@ -1,3 +1,3 @@
-var app=angular.module("News",["ngRoute","ngSanitize","ngAnimate"]);app.config(["$routeProvider","$provide","$httpProvider",function(e,n,r){"use strict";var i={FEED:0,FOLDER:1,STARRED:2,SUBSCRIPTIONS:3,SHARED:4,EXPLORE:5};n.constant("REFRESH_RATE",60),n.constant("ITEM_BATCH_SIZE",40),n.constant("ITEM_AUTO_PAGE_SIZE",20),n.constant("BASE_URL",OC.generateUrl("/apps/news")),n.constant("FEED_TYPE",i),n.constant("MARK_READ_TIMEOUT",.5),n.constant("SCROLL_TIMEOUT",.1),n.factory("CSRFInterceptor",["$q","BASE_URL","$window",function(e,t,n){return{request:function(r){var i=n.location.href.split(n.location.pathname)[0];return 0!==r.url.indexOf(t)&&0!==r.url.indexOf(i)||(r.headers.requesttoken=oc_requesttoken),r||e.when(r)}}}]);var o={0:t("news","Request failed, network connection unavailable!"),401:t("news","Request unauthorized. Are you logged in?"),403:t("news","Request forbidden. Are you an admin?"),412:t("news","Token expired or app not enabled! Reload the page!"),500:t("news","Internal server error! Please check your data/owncloud.log file for additional information!"),503:t("news","Request failed, ownCloud is in currently in maintenance mode!")};n.factory("ConnectionErrorInterceptor",["$q","$timeout",function(e,t){var n;return{responseError:function(r){return r.status in o&&(n&&t.cancel(n),OC.Notification.hide(),OC.Notification.showHtml(o[r.status]),n=t(function(){OC.Notification.hide()},5e3)),e.reject(r)}}}]),r.interceptors.push("CSRFInterceptor"),r.interceptors.push("ConnectionErrorInterceptor");var s=function(e){return{data:["$http","$route","$q","$location","BASE_URL","ITEM_BATCH_SIZE","FEED_TYPE","SettingsResource","FeedResource",function(t,n,r,i,o,s,a,u,d){var c=u.get("showAll"),l=u.get("oldestFirst"),f=i.search().search||"",h=r.defer();if(null===c||null===l)h.resolve({});else{var p={type:e,limit:s,showAll:c,oldestFirst:l,search:f};if(void 0!==n.current&&void 0!==n.current.params&&void 0!==n.current.params.id&&(p.id=n.current.params.id),e===a.FEED){var g=d.getById(p.id);void 0===g||2===g.ordering?p.oldestFirst=!1:1===g.ordering&&(p.oldestFirst=!0)}t({url:o+"/items",method:"GET",params:p}).success(function(e){h.resolve(e)})}return h.promise}]}},a=function(){return{sites:["$http","$q","BASE_URL","$location","Publisher","SettingsResource",function(e,t,n,r,i,o){var s=t.defer(),a=r.search().lang;return a||(a=o.get("language")),e.get(n+"/settings").then(function(t){i.publishAll(t);var n=o.get("exploreUrl").replace(/\/+$/,""),r=n+"/feeds."+a+".json",s=n+"/feeds.en.json";return e.get(r)["catch"](function(){return e.get(s)})}).then(function(e){s.resolve(e.data)})["catch"](function(){s.reject()}),s.promise}]}};e.when("/items",{controller:"ContentController as Content",templateUrl:"content.html",resolve:s(i.SUBSCRIPTIONS),type:i.SUBSCRIPTIONS}).when("/items/starred",{controller:"ContentController as Content",templateUrl:"content.html",resolve:s(i.STARRED),type:i.STARRED}).when("/items/feeds/:id",{controller:"ContentController as Content",templateUrl:"content.html",resolve:s(i.FEED),type:i.FEED}).when("/items/folders/:id",{controller:"ContentController as Content",templateUrl:"content.html",resolve:s(i.FOLDER),type:i.FOLDER}).when("/explore",{controller:"ExploreController as Explore",templateUrl:"explore.html",resolve:a(),type:i.EXPLORE}).when("/shortcuts",{templateUrl:"shortcuts.html",type:-1})}]),app.run(["$rootScope","$location","$http","$q","$interval","$route","Loading","ItemResource","FeedResource","FolderResource","SettingsResource","Publisher","BASE_URL","FEED_TYPE","REFRESH_RATE",function(e,t,n,r,i,o,s,a,u,d,c,l,f,h,p){"use strict";s.setLoading("global",!0),l.subscribe(a).toChannels(["items","newestItemId","starred"]),l.subscribe(d).toChannels(["folders"]),l.subscribe(u).toChannels(["feeds"]),l.subscribe(c).toChannels(["settings"]);var g=r.defer();n.get(f+"/settings").success(function(e){l.publishAll(e),g.resolve()});var v=r.defer(),m=t.path();n.get(f+"/feeds/active").success(function(e){var n;switch(e.activeFeed.type){case h.FEED:n="/items/feeds/"+e.activeFeed.id;break;case h.FOLDER:n="/items/folders/"+e.activeFeed.id;break;case h.STARRED:n="/items/starred";break;case h.EXPLORE:n="/explore";break;default:n="/items"}/^\/items(\/(starred|explore|feeds\/\d+|folders\/\d+))?\/?$/.test(m)||t.path(n),v.resolve()});var y,E=r.defer();n.get(f+"/feeds").success(function(e){y=e,E.resolve()});var C,F=r.defer();n.get(f+"/folders").success(function(e){C=e,F.resolve()}),r.all([E.promise,F.promise]).then(function(){l.publishAll(y),l.publishAll(C),0===y.feeds.length&&0===C.folders.length&&t.path("/explore")}),r.all([g.promise,v.promise,E.promise,F.promise]).then(function(){o.reload(),s.setLoading("global",!1)}),i(function(){n.get(f+"/feeds").success(function(e){l.publishAll(e)}),n.get(f+"/folders").success(function(e){l.publishAll(e)})},1e3*p),e.$on("$routeChangeStart",function(){s.setLoading("content",!0)}),e.$on("$routeChangeSuccess",function(){s.setLoading("content",!1)}),e.$on("$routeChangeError",function(){t.path("/items")})}]),app.controller("AppController",["Loading","FeedResource","FolderResource",function(e,t,n){"use strict";this.loading=e,this.isFirstRun=function(){return 0===t.size()&&0===n.size()},this.play=function(e){this.playingItem=e}}]),app.controller("ContentController",["Publisher","FeedResource","ItemResource","SettingsResource","data","$route","$routeParams","$location","FEED_TYPE","ITEM_AUTO_PAGE_SIZE","Loading",function(e,t,n,r,i,o,s,a,u,d,c){"use strict";n.clear(),e.publishAll(i),this.isAutoPagingEnabled=!0,n.size()>=d?this.isNothingMoreToAutoPage=!1:this.isNothingMoreToAutoPage=!0,this.getItems=function(){return n.getAll()},this.toggleStar=function(e){n.toggleStar(e)},this.toggleItem=function(e){this.isCompactView()&&(e.show=!e.show)},this.isShowAll=function(){return r.get("showAll")},this.markRead=function(e){var r=n.get(e);r.keepUnread||r.unread!==!0||(n.markItemRead(e),t.markItemOfFeedRead(r.feedId))},this.getFeed=function(e){return t.getById(e)},this.toggleKeepUnread=function(e){var r=n.get(e);r.unread||(t.markItemOfFeedUnread(r.feedId),n.markItemRead(e,!1)),r.keepUnread=!r.keepUnread};var l=this,f=function(){var e=r.get("oldestFirst");if(l.isFeed()){var n=t.getById(s.id);n&&1===n.ordering?e=!0:n&&2===n.ordering&&(e=!1)}return e};this.orderBy=function(){return f()?"id":"-id"},this.isCompactView=function(){return r.get("compact")},this.isCompactExpand=function(){return r.get("compactExpand")},this.autoPagingEnabled=function(){return this.isAutoPagingEnabled},this.markReadEnabled=function(){return!r.get("preventReadOnScroll")},this.scrollRead=function(e){var r=[],i=[];e.forEach(function(e){var t=n.get(e);t.keepUnread||(r.push(e),i.push(t.feedId))}),r.length>0&&(t.markItemsOfFeedsRead(i),n.markItemsRead(r))},this.isFeed=function(){return o.current.$$route.type===u.FEED},this.autoPage=function(){if(!this.isNothingMoreToAutoPage){if(!this.isAutoPagingEnabled)return void(this.autoPageAgain=!0);this.isAutoPagingEnabled=!1,this.autoPageAgain=!1;var t=o.current.$$route.type,i=s.id,u=f(),l=r.get("showAll"),h=this,p=a.search().search;c.setLoading("autopaging",!0),n.autoPage(t,i,u,l,p).success(function(t){e.publishAll(t),t.items.length>=d?h.isAutoPagingEnabled=!0:h.isNothingMoreToAutoPage=!0,h.isAutoPagingEnabled&&h.autoPageAgain&&h.autoPage()}).error(function(){h.isAutoPagingEnabled=!0})["finally"](function(){c.setLoading("autopaging",!1)})}},this.getRelativeDate=function(e){if(void 0!==e&&""!==e){var t=r.get("language"),n=moment.unix(e).locale(t).fromNow()+"";return n}return""},this.refresh=function(){o.reload()},this.getMediaType=function(e){return e&&0===e.indexOf("audio")?"audio":e&&0===e.indexOf("video")?"video":void 0}}]),app.controller("ExploreController",["sites","$rootScope","FeedResource","SettingsResource","$location",function(e,t,n,r,i){"use strict";this.sites=e,this.feeds=Object.keys(e).map(function(t){return[t,e[t]]}).reduce(function(e,t){var n=t[0],r=t[1];return r.forEach(function(e){e.category=n}),e.concat(r)},[]),this.feedExists=function(e){return void 0!==n.getByLocation(e)},this.subscribeTo=function(e){t.$broadcast("addFeed",e)},this.isCategoryShown=function(e){return e.filter(function(e){return void 0===n.getByLocation(e.feed)}).length>0},this.getSupportedLanguageCodes=function(){return r.getSupportedLanguageCodes()},this.getCurrentLanguageCode=function(){var e=i.search().lang;return e||(e=r.get("language")),e},this.showLanguage=function(e){i.url("/explore/?lang="+e)},this.selectedLanguageCode=this.getCurrentLanguageCode()}]),app.controller("NavigationController",["$route","FEED_TYPE","FeedResource","FolderResource","ItemResource","SettingsResource","Publisher","$rootScope","$location","$q",function(e,t,n,r,i,o,s,a,u,d){"use strict";this.feedError="",this.showNewFolder=!1,this.renamingFolder=!1,this.addingFeed=!1,this.addingFolder=!1,this.folderError="",this.renameError="",this.feed={};var c=function(){return parseInt(e.current.params.id,10)};this.getLanguageCode=function(){return o.get("language")},this.getFeeds=function(){return n.getAll()},this.getFolders=function(){return r.getAll()},this.markFolderRead=function(e){n.markFolderRead(e),n.getByFolderId(e).forEach(function(e){i.markFeedRead(e.id)})},this.markFeedRead=function(e){i.markFeedRead(e),n.markFeedRead(e)},this.markRead=function(){i.markRead(),n.markRead()},this.isShowAll=function(){return o.get("showAll")},this.getFeedsOfFolder=function(e){return n.getByFolderId(e)},this.getUnreadCount=function(){return n.getUnreadCount()},this.isUnread=function(){return this.getUnreadCount()>0},this.getFeedUnreadCount=function(e){var t=n.getById(e);return void 0!==t?t.unreadCount:0},this.isFeedUnread=function(e){return this.getFeedUnreadCount(e)>0},this.getFolderUnreadCount=function(e){return n.getFolderUnreadCount(e)},this.isFolderUnread=function(e){return this.getFolderUnreadCount(e)>0},this.getStarredCount=function(){return i.getStarredCount()},this.isStarredUnread=function(){return this.getStarredCount()>0},this.toggleFolder=function(e){r.toggleOpen(e)},this.hasFeeds=function(e){return void 0!==n.getFolderUnreadCount(e)},this.subFeedActive=function(r){var i=e.current.$$route.type;if(i===t.FEED){var o=n.getById(c());if(void 0!==o&&o.folderId===r)return!0}return!1},this.isSubscriptionsActive=function(){return e.current&&e.current.$$route.type===t.SUBSCRIPTIONS},this.isStarredActive=function(){return e.current&&e.current.$$route.type===t.STARRED},this.isExploreActive=function(){return e.current&&e.current.$$route.type===t.EXPLORE},this.isFolderActive=function(n){return e.current&&e.current.$$route.type===t.FOLDER&&c()===n},this.isFeedActive=function(n){return e.current&&e.current.$$route.type===t.FEED&&c()===n},this.folderNameExists=function(e){return e=e||"",void 0!==r.get(e.trim())},this.feedUrlExists=function(e){return e=e||"",e=e.trim(),void 0!==n.get(e)||void 0!==n.get("http://"+e)},this.createFeed=function(e){var t=this;this.showNewFolder=!1,this.addingFeed=!0;var i=e.newFolder,o=e.existingFolder||{id:0};void 0===i||""===i?(o.getsFeed=!0,n.create(e.url,o.id,void 0).then(function(e){s.publishAll(e),u.path("/items/feeds/"+e.feeds[0].id+"/")})["finally"](function(){o.getsFeed=void 0,e.url="",t.addingFeed=!1})):r.create(i).then(function(n){s.publishAll(n),e.existingFolder=r.get(n.folders[0].name),e.newFolder=void 0,t.createFeed(e)})},this.createFolder=function(e){var t=this;this.addingFolder=!0,r.create(e.name).then(function(e){s.publishAll(e)})["finally"](function(){t.addingFolder=!1,e.name=""})},this.moveFeed=function(t,r){var i=!1,o=n.getById(t);o.folderId!==r&&((this.isFolderActive(o.folderId)||this.isFolderActive(r))&&(i=!0),n.move(t,r),i&&e.reload())},this.renameFeed=function(e){n.patch(e.id,{title:e.title}),e.editing=!1},this.renameFolder=function(e,t){e.renameError="",this.renamingFolder=!0;var n=this;e.name===t?(e.renameError="",e.editing=!1,this.renamingFolder=!1):r.rename(e.name,t).then(function(){e.renameError="",e.editing=!1},function(t){e.renameError=t})["finally"](function(){n.renamingFolder=!1})},this.reversiblyDeleteFeed=function(t){n.reversiblyDelete(t.id)["finally"](function(){e.reload()})},this.undoDeleteFeed=function(t){n.undoDelete(t.id)["finally"](function(){e.reload()})},this.deleteFeed=function(e){n["delete"](e.url)},this.reversiblyDeleteFolder=function(t){d.all(n.reversiblyDeleteFolder(t.id),r.reversiblyDelete(t.name))["finally"](function(){e.reload()})},this.undoDeleteFolder=function(t){d.all(n.undoDeleteFolder(t.id),r.undoDelete(t.name))["finally"](function(){e.reload()})},this.deleteFolder=function(e){n.deleteFolder(e.id),r["delete"](e.name)},this.setOrdering=function(t,r){n.patch(t.id,{ordering:r}),e.reload()},this.togglePinned=function(e){var t=n.getById(e);return t?n.patch(e,{pinned:!t.pinned}):void 0},this.setUpdateMode=function(e,t){return n.patch(e,{updateMode:t})},this.toggleFullText=function(t){a.$broadcast("$routeChangeStart"),n.toggleFullText(t.id)["finally"](function(){a.$broadcast("$routeChangeSuccess"),e.reload()})},this.search=function(e){""===e?u.search("search",null):u.search("search",e)};var l=this;a.$on("moveFeedToFolder",function(e,t){l.moveFeed(t.feedId,t.folderId)});var f=function(){var i;e.current&&(i=e.current.$$route.type);var o=0;if(i===t.FOLDER)o=c();else if(i===t.FEED){var s=n.getById(c());s&&(o=s.folderId)}var a;0!==o&&(a=r.getById(o)),l.feed.existingFolder=a};a.$on("$routeChangeSuccess",function(){f()})}]),app.controller("SettingsController",["$route","$q","SettingsResource","ItemResource","OPMLParser","OPMLImporter","Publisher",function(e,t,n,r,i,o,s){"use strict";this.isOPMLImporting=!1,this.isArticlesImporting=!1,this.opmlImportError=!1,this.articleImportError=!1;var a=function(t,r){n.set(t,r),["showAll","oldestFirst","compact"].indexOf(t)>=0&&e.reload()};this.toggleSetting=function(e){a(e,!this.getSetting(e))},this.getSetting=function(e){return n.get(e)},this.importOPML=function(e){this.opmlImportError=!1,this.articleImportError=!1;try{this.isOPMLImporting=!1;var t=i.parse(e),n=this,r=5;o.importFolders(t).then(function(e){return o.importFeedQueue(e,r)})["finally"](function(){n.isOPMLImporting=!1})}catch(s){console.error(s),this.isOPMLImporting=!1,this.opmlImportError=!0}},this.importArticles=function(e){this.opmlImportError=!1,this.articleImportError=!1;try{this.isArticlesImporting=!0;var t=JSON.parse(e),n=this;r.importArticles(t).success(function(e){s.publishAll(e)})["finally"](function(){n.isArticlesImporting=!1})}catch(i){console.error(i),this.articleImportError=!0,this.isArticlesImporting=!1}}}]),app.filter("trustUrl",["$sce",function(e){"use strict";return function(t){return e.trustAsResourceUrl(t)}}]),app.filter("unreadCountFormatter",function(){"use strict";return function(e){return e>999?"999+":e}}),app.factory("FeedResource",["Resource","$http","BASE_URL","$q",function(e,t,n,r){"use strict";var i=function(t,n,r){e.call(this,t,n,"url"),this.ids={},this.locations={},this.unreadCount=0,this.folderUnreadCount={},this.folderIds={},this.$q=r};return i.prototype=Object.create(e.prototype),i.prototype.receive=function(t){e.prototype.receive.call(this,t),this.updateUnreadCache(),this.updateFolderCache()},i.prototype.clear=function(){e.prototype.clear.call(this),this.unreadCount=0,this.folderUnreadCount={},this.folderIds={},this.ids={},this.locations={}},i.prototype.updateUnreadCache=function(){this.unreadCount=0,this.folderUnreadCount={};var e=this;this.values.forEach(function(t){t.unreadCount&&(e.unreadCount+=t.unreadCount),void 0!==t.folderId&&(e.folderUnreadCount[t.folderId]=e.folderUnreadCount[t.folderId]||0,e.folderUnreadCount[t.folderId]+=t.unreadCount)})},i.prototype.updateFolderCache=function(){this.folderIds={};var e=this;this.values.forEach(function(t){e.folderIds[t.folderId]=e.folderIds[t.folderId]||[],e.folderIds[t.folderId].push(t)})},i.prototype.add=function(t){e.prototype.add.call(this,t),void 0!==t.id&&(this.ids[t.id]=this.hashMap[t.url]),void 0!==t.location&&(this.locations[t.location]=this.hashMap[t.url])},i.prototype.markRead=function(){this.values.forEach(function(e){e.unreadCount=0}),this.updateUnreadCache()},i.prototype.markFeedRead=function(e){this.ids[e].unreadCount=0,this.updateUnreadCache()},i.prototype.markFolderRead=function(e){this.values.forEach(function(t){t.folderId===e&&(t.unreadCount=0)}),this.updateUnreadCache()},i.prototype.markItemOfFeedRead=function(e){this.ids[e].unreadCount-=1,this.updateUnreadCache()},i.prototype.markItemsOfFeedsRead=function(e){var t=this;e.forEach(function(e){t.ids[e].unreadCount-=1}),this.updateUnreadCache()},i.prototype.markItemOfFeedUnread=function(e){this.ids[e].unreadCount+=1,this.updateUnreadCache()},i.prototype.getUnreadCount=function(){return this.unreadCount},i.prototype.getFolderUnreadCount=function(e){return this.folderUnreadCount[e]},i.prototype.getByFolderId=function(e){return this.folderIds[e]||[]},i.prototype.getById=function(e){return this.ids[e]},i.prototype.getByLocation=function(e){return this.locations[e]},i.prototype.move=function(e,t){var n=this.getById(e);return n.folderId=t,this.updateFolderCache(),this.updateUnreadCache(),this.patch(e,{folderId:t})},i.prototype.create=function(e,t,n){e=e.trim(),e.startsWith("http")||(e="https://"+e),void 0!==n&&(n=n.trim());var r={url:e,folderId:t||0,title:n||e,unreadCount:0};this.add(r),this.updateFolderCache();var i=this.$q.defer();return this.http({method:"POST",url:this.BASE_URL+"/feeds",data:{url:e,parentFolderId:t||0,title:n}}).success(function(e){i.resolve(e)}).error(function(e){r.faviconLink="",r.error=e.message,i.reject()}),i.promise},i.prototype.reversiblyDelete=function(e,t,n){var r=this.getById(e);return r&&n!==!0&&(r.deleted=!0),t!==!1&&this.updateUnreadCache(),this.http["delete"](this.BASE_URL+"/feeds/"+e)},i.prototype.reversiblyDeleteFolder=function(e){var t=this,n=[];this.getByFolderId(e).forEach(function(e){n.push(t.reversiblyDelete(e.id,!1,!0))}),this.updateUnreadCache();var r=this.$q.all(n);return r.promise},i.prototype["delete"]=function(t,n){var r=this.get(t);return void 0!==r&&r.id&&delete this.ids[r.id],void 0!==r&&r.location&&delete this.locations[r.location],e.prototype["delete"].call(this,t),n!==!1&&(this.updateUnreadCache(),this.updateFolderCache()),r},i.prototype.deleteFolder=function(e){var t=this;this.getByFolderId(e).forEach(function(e){t["delete"](e.url,!1)}),this.updateUnreadCache(),this.updateFolderCache()},i.prototype.undoDelete=function(e,t){var n=this.getById(e);return n&&(n.deleted=!1),t!==!1&&this.updateUnreadCache(),this.http.post(this.BASE_URL+"/feeds/"+e+"/restore")},i.prototype.undoDeleteFolder=function(e){var t=this,n=[];this.getByFolderId(e).forEach(function(e){n.push(t.undoDelete(e.id,!1))}),this.updateUnreadCache();var r=this.$q.all(n);return r.promise},i.prototype.setOrdering=function(e,t){var n=this.getById(e);if(n){n.ordering=t;var r=this.BASE_URL+"/feeds/"+e;return this.http.patch(r,{ordering:t})}},i.prototype.setPinned=function(e,t){var n=this.getById(e);if(n){n.pinned=t;var r=this.BASE_URL+"/feeds/"+e;return this.http.patch(r,{pinned:t})}},i.prototype.patch=function(e,t){var n=this.getById(e);if(n){Object.keys(t).forEach(function(e){n[e]=t[e]});var r=this.BASE_URL+"/feeds/"+e;return this.http.patch(r,t)}},i.prototype.toggleFullText=function(e){var t=this.getById(e);return this.patch(e,{fullTextEnabled:!t.fullTextEnabled})},new i(t,n,r)}]),app.factory("FolderResource",["Resource","$http","BASE_URL","$q",function(e,t,n,r){"use strict";var i=function(t,n,r){e.call(this,t,n,"name"),this.deleted=null,this.$q=r,this.ids={}};return i.prototype=Object.create(e.prototype),i.prototype.add=function(t){e.prototype.add.call(this,t),void 0!==t.id&&(this.ids[t.id]=this.hashMap[t.name])},i.prototype.clear=function(){e.prototype.clear.call(this),this.ids={}},i.prototype["delete"]=function(t){var n=this.get(t);return void 0!==n&&n.id&&delete this.ids[n.id],e.prototype["delete"].call(this,t),n},i.prototype.toggleOpen=function(e){var t=this.get(e);return t.opened=!t.opened,this.http({url:this.BASE_URL+"/folders/"+t.id+"/open",method:"POST",data:{folderId:t.id,open:t.opened}})},i.prototype.rename=function(e,t){var n=this.get(e),r=this.$q.defer(),i=this;return this.http({url:this.BASE_URL+"/folders/"+n.id+"/rename",method:"POST",data:{folderName:t}}).success(function(){n.name=t,delete i.hashMap[e],i.hashMap[t]=n,r.resolve()}).error(function(e){r.reject(e.message)}),r.promise},i.prototype.getById=function(e){return this.ids[e]},i.prototype.create=function(e){e=e.trim();var t={name:e};this.add(t);var n=this.$q.defer();return this.http({url:this.BASE_URL+"/folders",method:"POST",data:{folderName:e}}).success(function(e){n.resolve(e)}).error(function(e){t.error=e.message}),n.promise},i.prototype.reversiblyDelete=function(e){var t=this.get(e),n=t.id;return t.deleted=!0,this.http["delete"](this.BASE_URL+"/folders/"+n)},i.prototype.undoDelete=function(e){var t=this.get(e),n=t.id;return t.deleted=!1,this.http.post(this.BASE_URL+"/folders/"+n+"/restore")},new i(t,n,r)}]),app.factory("ItemResource",["Resource","$http","BASE_URL","ITEM_BATCH_SIZE",function(e,t,n,r){"use strict";var i=function(t,n,r){e.call(this,t,n),this.batchSize=r,this.clear()};return i.prototype=Object.create(e.prototype),i.prototype.clear=function(){this.starredCount=0,this.lowestId=0,this.highestId=0,e.prototype.clear.call(this)},i.prototype.receive=function(t,n){switch(n){case"newestItemId":this.newestItemId=t;break;case"starred":this.starredCount=t;break;default:var r=this;t.forEach(function(e){0===r.lowestId&&(r.lowestId=e.id),0===r.highestId&&(r.highestId=e.id),e.id>r.highestId&&(r.highestId=e.id),e.id<r.lowestId&&(r.lowestId=e.id)}),e.prototype.receive.call(this,t,n)}},i.prototype.getNewestItemId=function(){return this.newestItemId},i.prototype.getStarredCount=function(){return this.starredCount},i.prototype.star=function(e,t){void 0===t&&(t=!0);var n=this.get(e),r=this.BASE_URL+"/items/"+n.feedId+"/"+n.guidHash+"/star";return n.starred=t,t?this.starredCount+=1:this.starredCount-=1,this.http({url:r,method:"POST",data:{isStarred:t}})},i.prototype.toggleStar=function(e){this.get(e).starred?this.star(e,!1):this.star(e,!0)},i.prototype.markItemRead=function(e,t){return void 0===t&&(t=!0),this.get(e).unread=!t,this.http({url:this.BASE_URL+"/items/"+e+"/read",method:"POST",data:{isRead:t}})},i.prototype.markItemsRead=function(e){var t=this;return e.forEach(function(e){t.get(e).unread=!1}),this.http({url:this.BASE_URL+"/items/read/multiple",method:"POST",data:{itemIds:e}})},i.prototype.markFeedRead=function(e,t){void 0===t&&(t=!0);var n=this.values.filter(function(t){return t.feedId===e});return n.forEach(function(e){e.unread=!t}),this.http.post(this.BASE_URL+"/feeds/"+e+"/read",{highestItemId:this.getNewestItemId()})},i.prototype.markRead=function(){return this.values.forEach(function(e){e.unread=!1}),this.http({url:this.BASE_URL+"/items/read",method:"POST",data:{highestItemId:this.getNewestItemId()}})},i.prototype.autoPage=function(e,t,n,r,i){var o;return o=n?this.highestId:this.lowestId,this.http({url:this.BASE_URL+"/items",method:"GET",params:{type:e,id:t,offset:o,limit:this.batchSize,oldestFirst:n,showAll:r,search:i}})},i.prototype.importArticles=function(e){return this.http({url:this.BASE_URL+"/feeds/import/articles",method:"POST",data:{json:e}})},new i(t,n,r)}]),app.service("Loading",function(){"use strict";this.loading={global:!1,content:!1,autopaging:!1},this.setLoading=function(e,t){this.loading[e]=t},this.isLoading=function(e){return this.loading[e]}}),app.service("OPMLImporter",["FeedResource","FolderResource","Publisher","$q",function(e,t,n,r){"use strict";var i=function(o){var s=r.defer();if(o.length>0){var a=o.pop(),u=a.url,d=a.title,c=0,l=a.folderName;if(void 0!==l&&void 0!==t.get(l)){var f=t.get(l);f.opened=!0,c=f.id,f.getsFeed=!0,f.getsFeedCounter=f.getsFeedCounter||0,f.getsFeedCounter+=1}void 0!==u&&void 0===e.get(u)&&e.create(u,c,d).then(function(e){n.publishAll(e)})["finally"](function(){0!==c&&(f.getsFeedCounter-=1,0===f.getsFeedCounter&&(f.getsFeed=!1)),i(o)})}else s.resolve();return s.promise};this.importFolders=function(e){var i=[],o=[];e.folders.forEach(function(e){if(void 0!==e.name){if(void 0===t.get(e.name)){var r=t.create(e.name).then(function(e){n.publishAll(e)});o.push(r)}e.feeds.forEach(function(t){t.folderName=e.name,i.push(t)})}}),i=i.concat(e.feeds);var s=r.defer();return r.all(o)["finally"](function(){s.resolve(i)}),s.promise},this.importFeedQueue=function(e,t){for(var n=r.defer(),o=[],s=0;t>s;s+=1)o.push(i(e));return r.all(o).then(function(){n.resolve()}),n.promise}}]),app.service("OPMLParser",function(){"use strict";var e=function(e){var t=e.attr("xmlUrl")||e.attr("htmlUrl"),n=e.attr("title")||e.attr("text")||t;return void 0===t?{type:"folder",name:n,feeds:[]}:{type:"feed",name:n,url:t}},t=function(n,r,i){for(var o=0;o<n.length;o+=1){var s=$(n[o]),a=e(s);"feed"===a.type?r.feeds.push(a):i?(t(s.children("outline"),a,!1),r.folders.push(a)):t(s.children("outline"),r,!1)}return r};this.parse=function(e){e=$.parseXML(e);var n=$(e).find("body > outline"),r={feeds:[],folders:[]};return t(n,r,!0)}}),app.service("Publisher",function(){"use strict";this.channels={},this.subscribe=function(e){var t=this;return{toChannels:function(n){n.forEach(function(n){t.channels[n]=t.channels[n]||[],t.channels[n].push(e)})}}},this.publishAll=function(e){var t=this;Object.keys(e).forEach(function(n){var r=t.channels[n];void 0!==r&&r.forEach(function(t){t.receive(e[n],n)})})}}),app.factory("Resource",function(){"use strict";var e=function(e,t,n){this.id=n||"id",this.values=[],this.hashMap={},this.http=e,this.BASE_URL=t};return e.prototype.receive=function(e){var t=this;e.forEach(function(e){t.add(e)})},e.prototype.add=function(e){var t=this.hashMap[e[this.id]];void 0===t?(this.values.push(e),this.hashMap[e[this.id]]=e):Object.keys(e).forEach(function(n){t[n]=e[n]})},e.prototype.size=function(){return this.values.length},e.prototype.get=function(e){return this.hashMap[e]},e.prototype["delete"]=function(e){var t=this,n=this.values.findIndex(function(n){return n[t.id]===e});void 0!==n&&this.values.splice(n,1),void 0!==this.hashMap[e]&&delete this.hashMap[e]},e.prototype.clear=function(){for(this.hashMap={};this.values.length>0;)this.values.pop()},e.prototype.getAll=function(){return this.values},e}),app.service("SettingsResource",["$http","BASE_URL",function(e,t){"use strict";this.settings={language:"en",showAll:null,compact:!1,oldestFirst:null,preventReadOnScroll:!1,compactExpand:!1,exploreUrl:""},this.defaultLanguageCode="en",this.supportedLanguageCodes=["ar-ma","ar","bg","ca","cs","cv","da","de","el","en","en-ca","en-gb","eo","es","et","eu","fi","fr-ca","fr","gl","he","hi","hu","id","is","it","ja","ka","ko","lv","ms-my","nb","ne","nl","pl","pt-br","pt","ro","ru","sk","sl","sv","th","tr","tzm-la","tzm","uk","zh-cn","zh-tw"],this.getSupportedLanguageCodes=function(){return this.supportedLanguageCodes},this.receive=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n];"language"===n&&(r=t.processLanguageCode(r)),t.settings[n]=r})},this.get=function(e){return this.settings[e]},this.set=function(n,r){return this.settings[n]=r,e({url:t+"/settings",method:"PUT",data:{language:this.settings.language,showAll:this.settings.showAll,compact:this.settings.compact,oldestFirst:this.settings.oldestFirst,compactExpand:this.settings.compactExpand,preventReadOnScroll:this.settings.preventReadOnScroll}})},this.processLanguageCode=function(e){return e=e.replace("_","-").toLowerCase(),this.supportedLanguageCodes.indexOf(e)<0&&(e=e.split("-")[0]),this.supportedLanguageCodes.indexOf(e)<0&&(e=this.defaultLanguageCode),e}}]),function(e,t,n,r,i,o){"use strict";var s=e.location,a=e.localStorage,u=function(e,t,r){var i=n.isContentHandlerRegistered,o=function(e,t){return i?"new"!==i(e,t):a.getItem("registeredHandler")===t};n.registerContentHandler&&!o(e,t)&&(n.registerContentHandler(e,t,r),i||a.setItem("registeredHandler",t))},d=s.protocol+"//"+s.host+s.pathname,c=d+"?subscribe_to=%s",l="application/vnd.mozilla.maybe.feed",f="ownCloud News @ "+d;u(l,c,f),i(t).ready(function(){var e=r("?subscribe_to");if(e&&"undefined"!==e){i("#new-feed").show();var t=i('input[ng-model="Navigation.feed.url"]');t.val(e),t.trigger("input"),setTimeout(function(){t.focus()},1e3)}})}(window,document,navigator,url,$),function(e,t){"use strict";e.addEventListener("beforeunload",function(){var e=t.querySelector("#app-content");e.scrollTo(0,0)})}(window,document),function(e,t,n){"use strict";var r=function(e){return!(e.is("input")||e.is("select")||e.is("textarea")||e.is("checkbox"))},i=function(e){return!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey)},o=function(e){var t=".active > .app-navigation-entry-menu .mark-read button",n=e.find(t);n.length>0&&n.trigger("click")},s=function(e,t){var n=e.offset().top-t.offset().top,r=n+e.height(),i=t.height();return n>=0&&i>r},a=function(e,t,n){0===e.length||!n&&s(e,t)||t.scrollTop(e.offset().top-t.offset().top+t.scrollTop())},u=function(e){var t=e.find(".active");a(t,e.children("ul"),!0)},d=function(e){e.find(".active > a:visible").trigger("click")},c=function(e,t){if(0===t.scrollTop()){var n=t.find(".pull-to-refresh");n.hasClass("show-pull-to-refresh")?n.hasClass("done")&&d(e):n.addClass("show-pull-to-refresh")}},l=function(e,t){e.children("a:visible").trigger("click"),a(e,t.children("ul"))},f=function(e){var t=e.find(".active"),r=e.find(".explore-feed,.subscriptions-feed:visible,.starred-feed:visible,.feed:visible");if(t.hasClass("folder"))for(;t.length>0;){var i=t.find(".feed:visible");if(i.length>0)return void l(n(i[0]),e);t=t.next(".folder")}else for(var o=0;o<r.length-1;o+=1){var