diff --git a/dist/files_opds-0.8.2.tar.gz b/dist/files_opds-0.8.2.tar.gz new file mode 100644 index 0000000..614ad60 Binary files /dev/null and b/dist/files_opds-0.8.2.tar.gz differ diff --git a/files_opds/CHANGELOG.md b/files_opds/CHANGELOG.md index 9553afd..c66df3c 100644 --- a/files_opds/CHANGELOG.md +++ b/files_opds/CHANGELOG.md @@ -1,4 +1,12 @@ -## UNRELEASED +## 0.8.2 - 2017-01-19 +### Fixed + - Support login tokens ('app passwords', NC/OC) and 2FA (NC) + +## 0.8.1 - 2017-01-14 +### Changed + - more robust preview generator, fallback to mimetype icon when showPreview throws exception + +## 0.8.0 - 2017-01-14 ### New - FictionBook 2 (.fb2) metadata parser - FB2 preview provider diff --git a/files_opds/README.md b/files_opds/README.md index 02fe09a..6500cfc 100644 --- a/files_opds/README.md +++ b/files_opds/README.md @@ -1,7 +1,7 @@ files_opds ---------- -The OPDS catalog app enables Nextcloud/Owncloud (*-cloud for the rest of this text) users to publish a sub-tree of their personal filesystem as an OPDS feed. Since *-cloud currently has limited to no support for metadata, these are for now stored in a separate table. As of v0.3 OPDS catalog can extract all relevant metadata from EPUB documents. v0.5 introduced ISBN-based metadata retrieval, while Calibre-generated metadata.opf files are parsed since v0.6. +The OPDS catalog app enables Nextcloud/Owncloud (*-cloud for the rest of this text) users to publish a sub-tree of their personal filesystem as an OPDS feed. Since *-cloud currently has limited to no support for metadata, these are for now stored in a separate table. As of v0.3 OPDS catalog can extract all relevant metadata from EPUB and PDF documents. v0.5 introduced ISBN-based metadata retrieval, while Calibre-generated metadata.opf files are parsed since v0.6. FictionBook 2 (.fb2) metadata is supported from v0.8.0. #### ISBN If an ISBN is found in either existing metadata or in the first 10 pages of the publication, metadata is retrieved from ISBNdb (key required, http://isbndb.com/account/logincreate, max. 500 queries/day) and Google Books (no key required). diff --git a/files_opds/appinfo/info.xml b/files_opds/appinfo/info.xml index ce8e98c..d7e9a15 100644 --- a/files_opds/appinfo/info.xml +++ b/files_opds/appinfo/info.xml @@ -11,7 +11,7 @@ The feed is in compliance with the OPDS 1.1 specification according to the online OPDS validator (http://opds-validator.appspot.com/). AGPL - 0.8.0 + 0.8.2 Frank de Lange tools files diff --git a/files_opds/index.php b/files_opds/index.php index 48cc1b5..7098f8f 100644 --- a/files_opds/index.php +++ b/files_opds/index.php @@ -14,24 +14,14 @@ namespace OCA\Files_Opds; \OCP\App::checkAppEnabled('files_opds'); -/* Enable login through basic auth, using normal OC username/password - * This is required because opds clients do not support the normal - * OC login process - */ -if (Util::authenticateUser() === false) { - Util::changeHttpStatus(401); - exit; -} - -\OCP\User::checkLoggedIn(); +Util::authenticateUser(); /* Refuse access if user disabled opds support */ if (Config::get('enable', 'false') === 'false') { Util::changeHttpStatus(403); - exit; + exit(); } - /* id defaults to 'root' (meaning 'serve root feed') */ $id = isset($_GET['id']) ? $_GET['id'] : 'root'; diff --git a/files_opds/lib/util.php b/files_opds/lib/util.php index a3b8044..b33cafe 100644 --- a/files_opds/lib/util.php +++ b/files_opds/lib/util.php @@ -12,17 +12,28 @@ namespace OCA\Files_Opds; +use OC\Authentication\Exceptions\PasswordLoginForbiddenException; +use OC\User\LoginException; + /** * Utility class for OPDS */ class Util { /** - * @brief Authenticate user by HTTP Basic Authentication - * with user name and password + * @brief Authenticate user by HTTP Basic Authentication with username and password or token + * + * Supports login as well as app passwords (tokens). + * NC: only app passwords are accepted when 2FA is enforced for $user + * + * @throws OC\Authentication\Exceptions\PasswordLoginForbiddenException; + * @throws OC\User\LoginException; */ public static function authenticateUser() { - if (!isset($_SERVER['PHP_AUTH_USER'])) { + $request = \OC::$server->getRequest(); + + // force basic auth, enables access through browser + if (!isset($request->server['PHP_AUTH_USER'])) { $defaults = new \OC_Defaults(); $realm = $defaults->getName(); header ("HTTP/1.0 401 Unauthorized"); @@ -30,28 +41,49 @@ class Util exit(); } - $userName = $_SERVER['PHP_AUTH_USER']; + $user = $request->server['PHP_AUTH_USER']; + $pass = $request->server['PHP_AUTH_PW']; - // Check the password in the ownCloud database - return self::checkPassword($userName, $_SERVER['PHP_AUTH_PW']); + try { + //if (!\OC::$server->getUserSession()->logClientIn($user, $pass, $request, $throttler)) { + if (!self::logClientIn($user, $pass, $request)) { + // unknown user and/or password + self::changeHttpStatus(401); + exit(); + } + } catch (PasswordLoginForbiddenException $ex) { + // 2FA active and enforced for user so only app passwords are allowed + self::changeHttpStatus(401); + exit(); + } catch (LoginException $ex) { + // login cancelled or user forbidden + self::changeHttpStatus(403); + exit(); + } } - /** - * @brief Checks the password of a user. - * @param string $userName ownCloud user name whose password will be checked. - * @param string $password ownCloud password. - * @return bool True if the password is correct, false otherwise. - * - */ - private static function checkPassword($userName, $password) { - - // Check password normally - if (\OCP\User::checkPassword($userName, $password) != false) { - return true; - } - - return false; - } + /** + * @brief attempt to login using $user and $pass (password or token) + * + * Login using username and password, supports both traditional passwords as well as + * token-based login ('app passwords'). + * + * @param string $user + * @param string $pass + * @param IRequest $request + * @throws PasswordLoginForbiddenException + * @throws LoginException + * @return boolean + * + */ + public static function logClientIn($user, $pass, $request) { + if (class_exists('OC\Security\Bruteforce\Throttler')) { + $throttler = \OC::$server->getBruteForceThrottler(); + return \OC::$server->getUserSession()->logClientIn($user, $pass, $request, $throttler); + } else { + return \OC::$server->getUserSession()->logClientIn($user, $pass, $request); + } + } /** * @brief Change HTTP response code.