diff --git a/config.example.php b/config.example.php index 0c93e1dc..ef9a2444 100644 --- a/config.example.php +++ b/config.example.php @@ -14,7 +14,10 @@ 'url' => 'https://...', 'user' => '', 'password' => '', - // 'authentication' => 'digest' // uncomment for digest auth + 'http' => [ // http client options are directly passed to Guzzle http client + // 'verify' => false, // uncomment to disable certificate check + // 'auth' => 'digest', // uncomment for digest auth + ] ], /* add as many as you need [ @@ -31,6 +34,9 @@ 'user' => '', 'password' => '', 'fonpix' => '/[YOURUSBSTICK]/FRITZ/fonpix', // the storage on your usb stick for uploading images + 'http' => [ // http client options are directly passed to Guzzle http client + // 'verify' => false, // uncomment to disable certificate check + ] ], 'filters' => [ diff --git a/src/CardDav/Backend.php b/src/CardDav/Backend.php index fc9c7f76..fb9e69e8 100644 --- a/src/CardDav/Backend.php +++ b/src/CardDav/Backend.php @@ -2,9 +2,7 @@ namespace Andig\CardDav; -use GuzzleHttp\Client; -use GuzzleHttp\Psr7\Request; -use Ringcentral\Psr7; +use Andig\Http\ClientTrait; use Andig\Vcard\Parser; /** @@ -15,6 +13,8 @@ class Backend { + use ClientTrait; + /** * CardDAV server url * @@ -29,39 +29,11 @@ class Backend */ private $url_vcard_extension = '.vcf'; - /** - * Authentication: username - * - * @var string - */ - private $username; - - /** - * Authentication: password - * - * @var string - */ - private $password; - - /** - * Authentication: method - * - * @var string|null - */ - private $authentication; - /** * Progress callback */ private $callback; - /** - * Do not use this directly! Rather use {@see getClient()} - * - * @var Client - */ - private $client; - /** * Set substitutions of links to embedded data */ @@ -120,15 +92,6 @@ public function setProgress($callback = null) $this->callback = $callback; } - /** - * Set credentials - */ - public function setAuth(string $username, string $password, string $method = null) - { - $this->username = $username; - $this->password = $password; - $this->authentication = $method; - } /** * Gets all vCards including additional information from the CardDAV server @@ -137,43 +100,9 @@ public function setAuth(string $username, string $password, string $method = nul */ public function getVcards() { - $response = $this->query($this->url, 'PROPFIND'); - - if (in_array($response->getStatusCode(), [200,207])) { - $body = (string)$response->getBody(); - return $this->processPropFindResponse($body); - } - - throw new \Exception('Received HTTP ' . $response->getStatusCode()); - } - - /** - * Get initialized HTTP client - * - * @return Client - */ - private function getClient(): Client - { - if (!$this->client) { - $this->client = new Client($this->getClientOptions()); - } - - return $this->client; - } - - /** - * HTTP client options - * - * @param array $options - * @return array - */ - private function getClientOptions($options = []): array - { - if ($this->username) { - $options['auth'] = [$this->username, $this->password, $this->authentication]; - } - - return $options; + $response = $this->getClient()->request('PROPFIND', $this->url); + $body = (string)$response->getBody(); + return $this->processPropFindResponse($body); } /** @@ -230,31 +159,20 @@ private function embedBase64($vcard, $substituteID, $server) */ public function getLinkedData($uri) { - $request = new Request('GET', $uri); - - if ($this->username) { - $credentials = base64_encode($this->username . ':' . $this->password); - $request = $request->withHeader('Authorization', 'Basic ' . $credentials); - } - $response = $this->getClient()->send($request); - - if (200 !== $response->getStatusCode()) { - throw new \Exception('Received HTTP ' . $response->getStatusCode()); - } else { - $contentType = $response->getHeader('Content-Type'); - - @list($mimeType, $parameters) = explode(';', $contentType[0], 2); - @list($type, $subType) = explode('/', $mimeType); - - $externalData = [ - 'mimetype' => $mimeType ?? '', - 'type' => $type ?? '', - 'subtype' => $subType ?? '', - 'parameters' => $parameters ?? '', - 'data' => (string)$response->getBody(), - ]; - return $externalData; - } + $response = $this->getClient()->request('GET', $uri); + $contentType = $response->getHeader('Content-Type'); + + @list($mimeType, $parameters) = explode(';', $contentType[0], 2); + @list($type, $subType) = explode('/', $mimeType); + + $externalData = [ + 'mimetype' => $mimeType ?? '', + 'type' => $type ?? '', + 'subtype' => $subType ?? '', + 'parameters' => $parameters ?? '', + 'data' => (string)$response->getBody(), + ]; + return $externalData; } /** @@ -266,27 +184,23 @@ public function getLinkedData($uri) public function getVcard($vcard_id) { $vcard_id = str_replace($this->url_vcard_extension, null, $vcard_id); - $response = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'GET'); + $response = $this->getClient()->request('GET', $this->url . $vcard_id . $this->url_vcard_extension); - if (in_array($response->getStatusCode(), [200,207])) { - $body = (string)$response->getBody(); + $body = (string)$response->getBody(); - $parser = new Parser($body); - $vcard = $parser->getCardAtIndex(0); + $parser = new Parser($body); + $vcard = $parser->getCardAtIndex(0); - if (isset($this->substitutes)) { - foreach ($this->substitutes as $substitute) { - $vcard = $this->embedBase64($vcard, $substitute, $this->url); - } - } - if (is_callable($this->callback)) { - ($this->callback)(); + if (isset($this->substitutes)) { + foreach ($this->substitutes as $substitute) { + $vcard = $this->embedBase64($vcard, $substitute, $this->url); } - - return $vcard; + } + if (is_callable($this->callback)) { + ($this->callback)(); } - throw new \Exception('Received HTTP ' . $response->getStatusCode()); + return $vcard; } /** @@ -331,31 +245,4 @@ private function cleanResponse($response) return $response; } - - /** - * Query the CardDAV server via curl and returns the response - * - * @param string $url CardDAV server URL - * @param string $method HTTP method like (OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE) - * @param string $content Content for CardDAV queries - * @param string $content_type Set content type - * @return array Raw CardDAV Response and http status code - */ - private function query($url, $method, $content = null, $content_type = null) - { - $request = new Request($method, $url, [ - 'Depth' => '1' - ]); - - if ($content_type) { - $request = $request->withHeader('Content-type', $content_type); - } - - if ($content) { - $request = $request->withBody($content); - } - - $response = $this->getClient()->send($request); - return $response; - } } diff --git a/src/FritzBox/Api.php b/src/FritzBox/Api.php index 3fe7d064..433cdd66 100644 --- a/src/FritzBox/Api.php +++ b/src/FritzBox/Api.php @@ -2,9 +2,9 @@ namespace Andig\FritzBox; -use GuzzleHttp\Client; -use GuzzleHttp\Psr7\Request; -use Ringcentral\Psr7; +use Andig\Http\ClientTrait; + +define('EMPTY_SID', '0000000000000000'); /** * Copyright (c) 2019 Andreas Götz @@ -12,31 +12,28 @@ */ class Api { - private $username; - private $password; - private $url; + use ClientTrait; - protected $sid = '0000000000000000'; + /** @var string */ + protected $username; - /** - * Do not use this directly! Rather use {@see getClient()} - * - * @var Client - */ - private $client; + /** @var string */ + protected $password; + + /** @var string */ + protected $url; + + /** @var string */ + protected $sid = EMPTY_SID; /** * Execute fb login * * @access public */ - public function __construct($url = 'https://fritz.box', $username = false, $password = false) + public function __construct($url = 'https://fritz.box') { $this->url = rtrim($url, '/'); - $this->username = $username; - $this->password = $password; - - $this->initSID(); } /** @@ -49,31 +46,6 @@ public function getSID() return $this->sid; } - /** - * Get initialized HTTP client - * - * @return Client - */ - private function getClient(): Client - { - if (!$this->client) { - $this->client = new Client($this->getClientOptions()); - } - - return $this->client; - } - - /** - * HTTP client options - * - * @param array $options - * @return array - */ - private function getClientOptions($options = []): array - { - return $options; - } - /** * Multi-part file uploads * @@ -124,19 +96,14 @@ public function postFile(array $formFields, array $fileFields) * * @throws Exception */ - protected function initSID() + protected function login() { $url = $this->url . '/login_sid.lua'; // read the current status $resp = $this->getClient()->request('GET', $url); - if (200 !== $resp->getStatusCode()) { - throw new \Exception('Received HTTP ' . $resp->getStatusCode()); - } - - // process response $xml = simplexml_load_string((string)$resp->getBody()); - if ($xml->SID != '0000000000000000') { + if ($xml->SID != EMPTY_SID) { $this->sid = (string)$xml->SID; return; } @@ -151,13 +118,10 @@ protected function initSID() 'response' => $response, ] ]); - if (200 !== $resp->getStatusCode()) { - throw new \Exception('Received HTTP ' . $resp->getStatusCode()); - } - // finger out the SID from the response + // retrieve SID from response $xml = simplexml_load_string((string)$resp->getBody()); - if ($xml->SID != '0000000000000000') { + if ($xml->SID != EMPTY_SID) { $this->sid = (string)$xml->SID; return; } diff --git a/src/Http/ClientTrait.php b/src/Http/ClientTrait.php new file mode 100644 index 00000000..709e4553 --- /dev/null +++ b/src/Http/ClientTrait.php @@ -0,0 +1,82 @@ + + * @copyright Andreas Götz + * @license MIT + */ + +trait ClientTrait +{ + /** @var string|null */ + protected $username; + + /** @var string|null */ + protected $password; + + /** @var array */ + protected $clientOptions = []; + + /** @var Client */ + private $client; + + /** + * Set credentials + */ + public function setAuth(string $username, string $password) + { + $this->username = $username; + $this->password = $password; + } + + /** + * Get initialized HTTP client + * + * @return Client + */ + protected function getClient(): Client + { + if (!$this->client) { + $this->client = new Client($this->getClientOptions()); + } + + return $this->client; + } + + /** + * Set default HTTP client options + * + * @param array $options + */ + + public function setClientOptions(array $options = []) + { + $this->clientOptions = $options; + } + + /** + * HTTP client options + * + * @param array $options + * @return array + */ + protected function getClientOptions($options = []): array + { + // merge default options + $options = array_merge($this->clientOptions, $options); + + if ($this->username) { + $method = $this->clientOptions['auth'] ?? 'basic'; + $options['auth'] = [$this->username, $this->password, $method]; + } else { + unset($options['auth']); + } + + return $options; + } + +} diff --git a/src/functions.php b/src/functions.php index 88624355..3ed64b56 100644 --- a/src/functions.php +++ b/src/functions.php @@ -18,12 +18,11 @@ */ function backendProvider(array $config): Backend { - $server = $config['server'] ?? $config; - $authentication = $server['authentication'] ?? null; + $options = $config['server'] ?? $config; - $backend = new Backend(); - $backend->setUrl($server['url']); - $backend->setAuth($server['user'], $server['password'], $authentication); + $backend = new Backend($options['url']); + $backend->setAuth($options['user'], $options['password']); + $backend->setClientOptions($options['http'] ?? []); return $backend; } @@ -354,9 +353,12 @@ function xml_adopt(SimpleXMLElement $to, SimpleXMLElement $from) */ function upload(string $xml, $config) { - $fritzbox = $config['fritzbox']; + $options = $config['fritzbox']; - $fritz = new Api($fritzbox['url'], $fritzbox['user'], $fritzbox['password']); + $fritz = new Api($options['url']); + $fritz->setAuth($options['user'], $options['password']); + $fritz->setClientOptions($options['http'] ?? []); + $fritz->login(); $formfields = array( 'PhonebookId' => $config['phonebook']['id']