diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php index 65f8a267e..8f972abdb 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php @@ -139,7 +139,7 @@ class PdoAddressBook { $aMatch = array(); if (\preg_match('/\/([^\/?]+)$/', $sKey, $aMatch) && !empty($aMatch[1]) && - (!$aItem['{dav:}resourcetype'] || !$aItem['{dav:}resourcetype']->is('{DAV:}collection'))) + (!$aItem['{dav:}resourcetype'] || !\in_array('{DAV:}collection', $aItem['{dav:}resourcetype']))) { $sVcfFileName = \urldecode(\urldecode($aMatch[1])); $sKeyID = \preg_replace('/\.vcf$/i', '', $sVcfFileName); @@ -280,9 +280,7 @@ class PdoAddressBook if (empty($sNextPath)) { - $oResourceType = isset($aItem['{DAV:}resourcetype']) ? $aItem['{DAV:}resourcetype'] : null; - /* @var $oResourceType \Sabre\DAV\Property\ResourceType */ - if ($oResourceType && $oResourceType->is('{DAV:}collection')) + if (isset($aItem['{DAV:}resourcetype']) && \in_array('{DAV:}collection', $aItem['{DAV:}resourcetype'])) { $sNextPath = $sKey; continue; @@ -403,15 +401,10 @@ class PdoAddressBook { if (!empty($sKey) && $aItem && isset($aItem['{DAV:}resourcetype'])) { - $oResourceType = $aItem['{DAV:}resourcetype']; - /* @var $oResourceType \Sabre\DAV\Property\ResourceType */ - - if ($oResourceType && $oResourceType->is('{DAV:}collection')) + if (\in_array('{DAV:}collection', $aItem['{DAV:}resourcetype']) + && \in_array('{urn:ietf:params:xml:ns:carddav}addressbook', $aItem['{DAV:}resourcetype'])) { - if ($oResourceType->is('{urn:ietf:params:xml:ns:carddav}addressbook')) - { - $aContactsPaths[$sKey] = isset($aItem['{DAV:}displayname']) ? \trim($aItem['{DAV:}displayname']) : ''; - } + $aContactsPaths[$sKey] = isset($aItem['{DAV:}displayname']) ? \trim($aItem['{DAV:}displayname']) : ''; } } } @@ -451,11 +444,8 @@ class PdoAddressBook { if (!empty($sKey) && isset($aItem['{DAV:}resourcetype'])) { - $oResourceType = $aItem['{DAV:}resourcetype']; - /* @var $oResourceType \Sabre\DAV\Property\ResourceType */ - - if ($oResourceType && $oResourceType->is('{DAV:}collection') && - $oResourceType->is('{urn:ietf:params:xml:ns:carddav}addressbook')) + if (\in_array('{DAV:}collection', $aItem['{DAV:}resourcetype']) + && \in_array('{urn:ietf:params:xml:ns:carddav}addressbook', $aItem['{DAV:}resourcetype'])) { $bGood = true; } @@ -471,7 +461,7 @@ class PdoAddressBook return $bGood; } - public function getDavClientFromUrl(string $sUrl, string $sUser, string $sPassword, string $sProxy = '') : DAVClient + private function getDavClientFromUrl(string $sUrl, string $sUser, string $sPassword, string $sProxy = '') : DAVClient { if (!\preg_match('/^http[s]?:\/\//i', $sUrl)) { @@ -515,7 +505,7 @@ class PdoAddressBook return $oClient; } - public function getDavClient(string $sUrl, string $sUser, string $sPassword, string $sProxy = '') : ?DAVClient + private function getDavClient(string $sUrl, string $sUser, string $sPassword, string $sProxy = '') : ?DAVClient { $aMatch = array(); $sUserAddressBookNameName = ''; diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/dav/client.php b/snappymail/v/0.0.0/app/libraries/snappymail/dav/client.php index 2bcff53d5..33428533e 100644 --- a/snappymail/v/0.0.0/app/libraries/snappymail/dav/client.php +++ b/snappymail/v/0.0.0/app/libraries/snappymail/dav/client.php @@ -10,21 +10,7 @@ namespace SnappyMail\DAV; class Client { - /** - * The propertyMap is a key-value array. - * - * If you use the propertyMap, any {DAV:}multistatus responses with the - * proeprties listed in this array, will automatically be mapped to a - * respective class. - * - * The {DAV:}resourcetype property is automatically added. This maps to - * Sabre\DAV\Property\ResourceType - * - * @var array - */ - public $propertyMap = array( -// '{DAV:}resourcetype' => 'SnappyMail\\DAV\\Property\\ResourceType' - ); +// public $__UrlPath__; protected $baseUri; @@ -62,6 +48,40 @@ class Client $this->HTTP->verify_peer = $value; } + /** + * Performs an actual HTTP request, and returns the result. + * + * If the specified url is relative, it will be expanded based on the base url. + */ + public function request(string $method, string $url = '', string $body = null, array $headers = array()) : \SnappyMail\HTTP\Response + { + if (!\preg_match('@^(https?:)?//@', $url)) { + // If the url starts with a slash, we must calculate the url based off + // the root of the base url. + if (0 === \strpos($url, '/')) { + $parts = \parse_url($this->baseUri); + $url = $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port'])?':' . $parts['port']:'') . $url; + } else { + $url = $this->baseUri . $url; + } + } + $response = $this->HTTP->doRequest('PROPFIND', $url, $body, $headers); + if (301 == $response->status) { + // Like: RewriteRule ^\.well-known/carddav /nextcloud/remote.php/dav [R=301,L] + $location = $response->getRedirectLocation(); + \trigger_error("Redirect {$url} to {$location}"); + $url = \preg_replace('@^(https?:)?//[^/]+[/$]@', '/', $location); + $parts = \parse_url($this->baseUri); + $url = $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port'])?':' . $parts['port']:'') . $url; + $response = $this->HTTP->doRequest('PROPFIND', $url, $body, $headers); + } + if (300 <= $response->status) { + throw new \SnappyMail\HTTP\Exception("PROPFIND {$url}", $response->status, $response); + } + + return $response; + } + /** * Does a PROPFIND request * @@ -98,35 +118,10 @@ class Client $body .= ' ' . "\n"; $body .= ''; - if (!\preg_match('@^(https?:)?//@', $url)) { - // If the url starts with a slash, we must calculate the url based off - // the root of the base url. - if (0 === \strpos($url, '/')) { - $parts = \parse_url($this->baseUri); - $url = $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port'])?':' . $parts['port']:'') . $url; - } else { - $url = $this->baseUri . $url; - } - } - $response = $this->HTTP->doRequest('PROPFIND', $url, $body, array( + $response = $this->request('PROPFIND', $url, $body, array( "Depth: {$depth}", 'Content-Type: application/xml' )); - if (301 == $response->status) { - // Like: RewriteRule ^\.well-known/carddav /nextcloud/remote.php/dav [R=301,L] - $location = $response->getRedirectLocation(); - \trigger_error("Redirect {$url} to {$location}"); - $url = \preg_replace('@^(https?:)?//[^/]+[/$]@', '/', $location); - $parts = \parse_url($this->baseUri); - $url = $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port'])?':' . $parts['port']:'') . $url; - $response = $this->HTTP->doRequest('PROPFIND', $url, $body, array( - "Depth: {$depth}", - 'Content-Type: application/xml' - )); - } - if (300 <= $response->status) { - throw new \SnappyMail\HTTP\Exception("PROPFIND {$url}", $response->status, $response); - } /** * Parse the WebDAV multistatus response body @@ -148,26 +143,21 @@ class Client throw new \InvalidArgumentException('The passed data is not valid XML'); } - $responseXML->registerXPathNamespace('d', 'urn:DAV'); + $ns = \array_search('urn:DAV', $responseXML->getNamespaces(true)); +// $ns_card = \array_search('urn:ietf:params:xml:ns:carddav', $responseXML->getNamespaces(true)); $result = array(); - foreach ($responseXML->xpath('d:response') as $response) { - $response->registerXPathNamespace('d', 'urn:DAV'); - $href = $response->xpath('d:href'); + foreach ($responseXML->xpath("{$ns}:response") as $response) { + $href = $response->xpath("{$ns}:href"); $href = (string) $href[0]; $properties = array(); - - foreach ($response->xpath('d:propstat') as $propStat) { - $propStat->registerXPathNamespace('d', 'urn:DAV'); - $status = $propStat->xpath('d:status'); + foreach ($response->xpath("{$ns}:propstat") as $propStat) { + $status = $propStat->xpath("{$ns}:status"); list($httpVersion, $statusCode, $message) = \explode(' ', (string)$status[0], 3); - // Only using the propertymap for results with status 200. - $propertyMap = $statusCode === '200' ? $this->propertyMap : array(); - - $properties[$statusCode] = static::parseProperties(\dom_import_simplexml($propStat), $propertyMap); + $properties[$statusCode] = static::parseProperties(\dom_import_simplexml($propStat)); } $result[$href] = $properties; @@ -218,14 +208,10 @@ class Client * If no value was given (self-closing element) null will be used as the * value. This is used in for example PROPFIND requests. * - * Complex values are supported through the propertyMap argument. The - * propertyMap should have the clark-notation properties as it's keys, and - * classnames as values. - * * When any of these properties are found, the fromDOMElement() method will be * (statically) called. The result of this method is used as the value. */ - protected static function parseProperties(\DOMElement $parentNode, array $propertyMap = array()) : array + protected static function parseProperties(\DOMElement $parentNode) : array { $propList = array(); foreach ($parentNode->childNodes as $propNode) { @@ -234,8 +220,11 @@ class Client /* If there are no elements in here, we actually get 1 text node, this special case is dedicated to netdrive */ if (XML_ELEMENT_NODE == $propNodeData->nodeType) { $propertyName = self::toClarkNotation($propNodeData); - if (isset($propertyMap[$propertyName])) { - $propList[$propertyName] = \call_user_func(array($propertyMap[$propertyName], 'fromDOMElement'), $propNodeData); + if ('{DAV:}resourcetype' === $propertyName) { + $propList[$propertyName] = []; + foreach ($propNodeData->childNodes as $resourcetype) { + $propList[$propertyName][] = self::toClarkNotation($resourcetype); + } } else { $propList[$propertyName] = $propNodeData->textContent; } @@ -245,5 +234,4 @@ class Client } return $propList; } - }