, * Michael Stilkerich * * This file is part of RCMCardDAV. * * RCMCardDAV is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * RCMCardDAV is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RCMCardDAV. If not, see . */ declare(strict_types=1); namespace MStilkerich\RCMCardDAV; use Exception; use Psr\Log\{LoggerInterface,LogLevel}; use MStilkerich\CardDavClient\{Account,WebDavResource}; use MStilkerich\CardDavClient\Services\{Discovery,Sync}; use MStilkerich\RCMCardDAV\Db\{Database, AbstractDatabase}; use MStilkerich\RCMCardDAV\Frontend\{RcmInterface, AdminSettings, AddressbookManager, Utils}; use rcube; use rcube_cache; /** * This class is intended as a central point to inject dependencies to infrastructure classes. * * This allows replacing dependencies in unit tests with mock objects. * * @psalm-import-type AccountSettings from AddressbookManager */ class Config { /** @var ?Config The single instance of this class - can be exchanged by tests */ public static $inst; /** @var ?RcmInterface Adapter to roundcube */ protected $rc; /** * The admin settings configured in the config.inc.php file. * @var AdminSettings */ protected $admPrefs; /** @var LoggerInterface */ protected $logger; /** @var LoggerInterface */ protected $httpLogger; /** @var AbstractDatabase */ protected $db; /** @var ?rcube_cache */ protected $cache; public static function inst(): Config { if (!isset(self::$inst)) { self::$inst = new Config(); } return self::$inst; } public function __construct() { $this->logger = new RoundcubeLogger("carddav", LogLevel::ERROR); $this->httpLogger = new RoundcubeLogger("carddav_http", LogLevel::ERROR); $this->admPrefs = new AdminSettings(__DIR__ . '/../config.inc.php', $this->logger, $this->httpLogger); $rcube = rcube::get_instance(); $this->db = new Database($this->logger, $rcube->db); } public function db(): AbstractDatabase { return $this->db; } public function logger(): LoggerInterface { return $this->logger; } public function httpLogger(): LoggerInterface { return $this->httpLogger; } public function rc(?RcmInterface $rc = null): RcmInterface { if (!isset($this->rc)) { if (isset($rc)) { $this->rc = $rc; } else { throw new Exception("Roundcube adapter not set"); } } return $this->rc; } public function admPrefs(): AdminSettings { return $this->admPrefs; } /** * Returns a handle to the roundcube cache for the user. * * Note: this must be called when the user is already logged on, specifically it must not be called * during the constructor of the plugin. */ public function cache(): rcube_cache { if (!isset($this->cache)) { // TODO make TTL and cache type configurable $rcube = rcube::get_instance(); $this->cache = $rcube->get_cache("carddav", "db", "1w"); } if (!isset($this->cache)) { throw new Exception("Attempt to request cache where not available yet"); } return $this->cache; } public function makeDiscoveryService(): Discovery { return new Discovery(); } public function makeSyncService(): Sync { return new Sync(); } public function makeWebDavResource(string $uri, Account $account): WebDavResource { return WebDavResource::createInstance($uri, $account); } /** * Creates an Account object from the credentials in rcmcarddav. * * Particularly, this takes care of setting up the credentials information properly. * * @param AccountSettings $accountCfg */ public static function makeAccount(array $accountCfg): Account { $password = Utils::replacePlaceholdersPassword($accountCfg['password'] ?? ''); if ($password == "%b") { if ( isset($_SESSION['oauth_token']) && is_array($_SESSION['oauth_token']) && isset($_SESSION['oauth_token']['access_token']) && is_string($_SESSION['oauth_token']['access_token']) ) { $httpOptions = [ 'bearertoken' => $_SESSION['oauth_token']['access_token'] ]; } else { throw new Exception("OAUTH2 bearer authentication requested, but no token available in roundcube"); } } else { $username = Utils::replacePlaceholdersUsername($accountCfg['username'] ?? ''); $httpOptions = [ 'username' => $username, 'password' => $password ]; } $httpOptions['preemptive_basic_auth'] = (bool) ($accountCfg['preemptive_basic_auth'] ?? false); $httpOptions['verify'] = !((bool) ($accountCfg['ssl_noverify'] ?? false)); $discUrl = Utils::replacePlaceholdersUrl($accountCfg['discovery_url'] ?? ''); return new Account($discUrl, $httpOptions); } } // vim: ts=4:sw=4:expandtab:fenc=utf8:ff=unix:tw=120