mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Bugfix: DAV getContactsPaths() failed due to failures of (string) SimpleXMLElement
Added better logging of DAV connection for #653 and #680
This commit is contained in:
parent
28a70ccc8e
commit
28a7377f97
3 changed files with 87 additions and 102 deletions
|
|
@ -35,13 +35,13 @@ trait Contacts
|
||||||
$oAccount = $this->getAccountFromToken();
|
$oAccount = $this->getAccountFromToken();
|
||||||
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
||||||
if (!$oAddressBookProvider) {
|
if (!$oAddressBookProvider) {
|
||||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError);
|
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError, null, 'No AddressBookProvider');
|
||||||
}
|
}
|
||||||
\ignore_user_abort(true);
|
\ignore_user_abort(true);
|
||||||
\SnappyMail\HTTP\Stream::start(/*$binary = false*/);
|
\SnappyMail\HTTP\Stream::start(/*$binary = false*/);
|
||||||
\SnappyMail\HTTP\Stream::JSON(['messsage'=>'start']);
|
\SnappyMail\HTTP\Stream::JSON(['messsage'=>'start']);
|
||||||
if (!$oAddressBookProvider->Sync()) {
|
if (!$oAddressBookProvider->Sync()) {
|
||||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError);
|
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError, null, 'AddressBookProvider->Sync() failed');
|
||||||
}
|
}
|
||||||
return $this->TrueResponse(__FUNCTION__);
|
return $this->TrueResponse(__FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,11 @@ trait CardDAV
|
||||||
$aResponse = null;
|
$aResponse = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->oLogger->Write('PROPFIND '.$sPath, \LOG_INFO, 'DAV');
|
|
||||||
|
|
||||||
$aResponse = $oClient->propFind($sPath, array(
|
$aResponse = $oClient->propFind($sPath, array(
|
||||||
'{DAV:}getlastmodified',
|
'{DAV:}getlastmodified',
|
||||||
'{DAV:}resourcetype',
|
'{DAV:}resourcetype',
|
||||||
'{DAV:}getetag'
|
'{DAV:}getetag'
|
||||||
), 1);
|
), 1);
|
||||||
|
|
||||||
// $this->oLogger->WriteDump($aResponse);
|
|
||||||
}
|
}
|
||||||
catch (\Throwable $oException)
|
catch (\Throwable $oException)
|
||||||
{
|
{
|
||||||
|
|
@ -139,16 +135,12 @@ trait CardDAV
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->oLogger->Write('PROPFIND '.$sPath, \LOG_INFO, 'DAV');
|
|
||||||
|
|
||||||
$aResponse = $oClient->propFind($sPath, array(
|
$aResponse = $oClient->propFind($sPath, array(
|
||||||
'{DAV:}current-user-principal',
|
'{DAV:}current-user-principal',
|
||||||
'{DAV:}resourcetype',
|
'{DAV:}resourcetype',
|
||||||
'{DAV:}displayname',
|
'{DAV:}displayname',
|
||||||
'{urn:ietf:params:xml:ns:carddav}addressbook-home-set'
|
'{urn:ietf:params:xml:ns:carddav}addressbook-home-set'
|
||||||
), 1);
|
), 1);
|
||||||
|
|
||||||
// $this->oLogger->WriteDump($aResponse);
|
|
||||||
}
|
}
|
||||||
catch (\Throwable $oException)
|
catch (\Throwable $oException)
|
||||||
{
|
{
|
||||||
|
|
@ -158,49 +150,47 @@ trait CardDAV
|
||||||
return $aResponse;
|
return $aResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getContactsPaths(DAVClient $oClient, string $sUser, string $sPassword, string $sProxy = '') : array
|
private function getContactsPaths(DAVClient $oClient, string $sPath, string $sUser, string $sPassword, string $sProxy = '') : array
|
||||||
{
|
{
|
||||||
$aContactsPaths = array();
|
$aContactsPaths = array();
|
||||||
|
|
||||||
$sCurrentUserPrincipal = '';
|
$sCurrentUserPrincipal = '';
|
||||||
$sAddressbookHomeSet = '';
|
$sAddressbookHomeSet = '';
|
||||||
|
|
||||||
// [{DAV:}current-user-principal] => /cloud/remote.php/carddav/principals/admin/
|
$aResponse = $this->detectionPropFind($oClient, '/.well-known/carddav')
|
||||||
// [{urn:ietf:params:xml:ns:carddav}addressbook-home-set] => /cloud/remote.php/carddav/addressbooks/admin/
|
?: $this->detectionPropFind($oClient, $sPath);
|
||||||
|
|
||||||
$aResponse = $this->detectionPropFind($oClient, '/.well-known/carddav');
|
|
||||||
|
|
||||||
$sNextPath = '';
|
$sNextPath = '';
|
||||||
$sFirstNextPath = '';
|
$sFirstNextPath = '';
|
||||||
if (\is_array($aResponse))
|
if (\is_array($aResponse))
|
||||||
{
|
{
|
||||||
foreach ($aResponse as $sKey => $aItem)
|
foreach ($aResponse as $sPropPath => $aItem)
|
||||||
{
|
{
|
||||||
if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']) &&
|
if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'])
|
||||||
false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'], '/calendar-proxy'))
|
&& false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'], '/calendar-proxy'))
|
||||||
{
|
{
|
||||||
$sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'];
|
$sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($sCurrentUserPrincipal) && !empty($aItem['{DAV:}current-user-principal']))
|
if (empty($sCurrentUserPrincipal) && !empty($aItem['{DAV:}current-user-principal']['{DAV:}href']))
|
||||||
{
|
{
|
||||||
$sCurrentUserPrincipal = $aItem['{DAV:}current-user-principal'];
|
$sCurrentUserPrincipal = $aItem['{DAV:}current-user-principal']['{DAV:}href'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($sKey))
|
if (!empty($sPropPath))
|
||||||
{
|
{
|
||||||
if (empty($sFirstNextPath))
|
if (empty($sFirstNextPath))
|
||||||
{
|
{
|
||||||
$sFirstNextPath = $sKey;
|
$sFirstNextPath = $sPropPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($sNextPath))
|
if (empty($sNextPath))
|
||||||
{
|
{
|
||||||
if (static::hasDAVCollection($aItem))
|
if (static::hasDAVCollection($aItem))
|
||||||
{
|
{
|
||||||
$sNextPath = $sKey;
|
$sNextPath = $sPropPath;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,36 +209,32 @@ trait CardDAV
|
||||||
{
|
{
|
||||||
return $aContactsPaths;
|
return $aContactsPaths;
|
||||||
}
|
}
|
||||||
else
|
if (\preg_match('/^http[s]?:\/\//i', $sNextPath))
|
||||||
{
|
{
|
||||||
if (\preg_match('/^http[s]?:\/\//i', $sNextPath))
|
$oClient = $this->getDavClientFromUrl($sNextPath, $sUser, $sPassword, $sProxy);
|
||||||
|
if (!$oClient)
|
||||||
{
|
{
|
||||||
$oClient = $this->getDavClientFromUrl($sNextPath, $sUser, $sPassword, $sProxy);
|
return $aContactsPaths;
|
||||||
if ($oClient)
|
|
||||||
{
|
|
||||||
$sNextPath = $oClient->__UrlPath__;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $aContactsPaths;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$sNextPath = $oClient->__UrlPath__;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sPath != $sNextPath) {
|
||||||
$aResponse = $this->detectionPropFind($oClient, $sNextPath);
|
$aResponse = $this->detectionPropFind($oClient, $sNextPath);
|
||||||
if (\is_array($aResponse))
|
if (\is_array($aResponse))
|
||||||
{
|
{
|
||||||
foreach ($aResponse as $sKey => $aItem)
|
foreach ($aResponse as $aItem)
|
||||||
{
|
{
|
||||||
if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']) &&
|
if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href']) &&
|
||||||
false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'], '/calendar-proxy'))
|
false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'], '/calendar-proxy'))
|
||||||
{
|
{
|
||||||
$sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'];
|
$sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($sCurrentUserPrincipal) && !empty($aItem['{DAV:}current-user-principal']))
|
if (empty($sCurrentUserPrincipal) && !empty($aItem['{DAV:}current-user-principal']['{DAV:}href']))
|
||||||
{
|
{
|
||||||
$sCurrentUserPrincipal = $aItem['{DAV:}current-user-principal'];
|
$sCurrentUserPrincipal = $aItem['{DAV:}current-user-principal']['{DAV:}href'];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -262,32 +248,29 @@ trait CardDAV
|
||||||
{
|
{
|
||||||
return $aContactsPaths;
|
return $aContactsPaths;
|
||||||
}
|
}
|
||||||
else
|
if (\preg_match('/^http[s]?:\/\//i', $sCurrentUserPrincipal))
|
||||||
{
|
{
|
||||||
if (\preg_match('/^http[s]?:\/\//i', $sCurrentUserPrincipal))
|
$oClient = $this->getDavClientFromUrl($sCurrentUserPrincipal, $sUser, $sPassword, $sProxy);
|
||||||
|
if ($oClient)
|
||||||
{
|
{
|
||||||
$oClient = $this->getDavClientFromUrl($sCurrentUserPrincipal, $sUser, $sPassword, $sProxy);
|
$sCurrentUserPrincipal = $oClient->__UrlPath__;
|
||||||
if ($oClient)
|
|
||||||
{
|
|
||||||
$sCurrentUserPrincipal = $oClient->__UrlPath__;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $aContactsPaths;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
$aResponse = $this->detectionPropFind($oClient, $sCurrentUserPrincipal);
|
|
||||||
if (\is_array($aResponse))
|
|
||||||
{
|
{
|
||||||
foreach ($aResponse as $sKey => $aItem)
|
return $aContactsPaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aResponse = $this->detectionPropFind($oClient, $sCurrentUserPrincipal);
|
||||||
|
if (\is_array($aResponse))
|
||||||
|
{
|
||||||
|
foreach ($aResponse as $aItem)
|
||||||
|
{
|
||||||
|
if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href']) &&
|
||||||
|
false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'], '/calendar-proxy'))
|
||||||
{
|
{
|
||||||
if (empty($sAddressbookHomeSet) && !empty($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']) &&
|
$sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set']['{DAV:}href'];
|
||||||
false === \strpos($aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'], '/calendar-proxy'))
|
continue;
|
||||||
{
|
|
||||||
$sAddressbookHomeSet = $aItem['{urn:ietf:params:xml:ns:carddav}addressbook-home-set'];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -297,31 +280,28 @@ trait CardDAV
|
||||||
{
|
{
|
||||||
return $aContactsPaths;
|
return $aContactsPaths;
|
||||||
}
|
}
|
||||||
else
|
if (\preg_match('/^http[s]?:\/\//i', $sAddressbookHomeSet))
|
||||||
{
|
{
|
||||||
if (\preg_match('/^http[s]?:\/\//i', $sAddressbookHomeSet))
|
$oClient = $this->getDavClientFromUrl($sAddressbookHomeSet, $sUser, $sPassword, $sProxy);
|
||||||
|
if ($oClient)
|
||||||
{
|
{
|
||||||
$oClient = $this->getDavClientFromUrl($sAddressbookHomeSet, $sUser, $sPassword, $sProxy);
|
$sAddressbookHomeSet = $oClient->__UrlPath__;
|
||||||
if ($oClient)
|
|
||||||
{
|
|
||||||
$sAddressbookHomeSet = $oClient->__UrlPath__;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $aContactsPaths;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
$aResponse = $this->detectionPropFind($oClient, $sAddressbookHomeSet);
|
|
||||||
if (\is_array($aResponse))
|
|
||||||
{
|
{
|
||||||
foreach ($aResponse as $sKey => $aItem)
|
return $aContactsPaths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aResponse = $this->detectionPropFind($oClient, $sAddressbookHomeSet);
|
||||||
|
if (\is_array($aResponse))
|
||||||
|
{
|
||||||
|
foreach ($aResponse as $sPropPath => $aItem)
|
||||||
|
{
|
||||||
|
if (!empty($sPropPath) && static::hasDAVCollection($aItem)
|
||||||
|
&& \in_array('{urn:ietf:params:xml:ns:carddav}addressbook', $aItem['{DAV:}resourcetype']))
|
||||||
{
|
{
|
||||||
if (!empty($sKey) && static::hasDAVCollection($aItem)
|
$aContactsPaths[$sPropPath] = isset($aItem['{DAV:}displayname']) ? \trim($aItem['{DAV:}displayname']) : '';
|
||||||
&& \in_array('{urn:ietf:params:xml:ns:carddav}addressbook', $aItem['{DAV:}resourcetype']))
|
|
||||||
{
|
|
||||||
$aContactsPaths[$sKey] = isset($aItem['{DAV:}displayname']) ? \trim($aItem['{DAV:}displayname']) : '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -329,6 +309,9 @@ trait CardDAV
|
||||||
return $aContactsPaths;
|
return $aContactsPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if remote path resourcetype is an addressbook
|
||||||
|
*/
|
||||||
private function checkContactsPath(DAVClient $oClient, string $sPath) : bool
|
private function checkContactsPath(DAVClient $oClient, string $sPath) : bool
|
||||||
{
|
{
|
||||||
if (!$oClient)
|
if (!$oClient)
|
||||||
|
|
@ -336,16 +319,12 @@ trait CardDAV
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->oLogger->Write('PROPFIND '.$sPath, \LOG_INFO, 'DAV');
|
|
||||||
|
|
||||||
$aResponse = null;
|
$aResponse = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$aResponse = $oClient->propFind($sPath, array(
|
$aResponse = $oClient->propFind($sPath, array(
|
||||||
'{DAV:}resourcetype'
|
'{DAV:}resourcetype'
|
||||||
), 1);
|
), 1);
|
||||||
|
|
||||||
// $this->oLogger->WriteDump($aResponse);
|
|
||||||
}
|
}
|
||||||
catch (\Throwable $oException)
|
catch (\Throwable $oException)
|
||||||
{
|
{
|
||||||
|
|
@ -445,11 +424,13 @@ trait CardDAV
|
||||||
$bGood = true;
|
$bGood = true;
|
||||||
if ('' === $sPath || '/' === $sPath || !$this->checkContactsPath($oClient, $sPath))
|
if ('' === $sPath || '/' === $sPath || !$this->checkContactsPath($oClient, $sPath))
|
||||||
{
|
{
|
||||||
$sNewPath = '';
|
/**
|
||||||
|
* Path is not an addressbook, try to find it
|
||||||
$aPaths = $this->getContactsPaths($oClient, $sUser, $sPassword, $sProxy);
|
*/
|
||||||
|
$aPaths = $this->getContactsPaths($oClient, $sPath, $sUser, $sPassword, $sProxy);
|
||||||
$this->oLogger->WriteDump($aPaths);
|
$this->oLogger->WriteDump($aPaths);
|
||||||
|
|
||||||
|
$sNewPath = '';
|
||||||
if (\is_array($aPaths))
|
if (\is_array($aPaths))
|
||||||
{
|
{
|
||||||
if (1 < \count($aPaths))
|
if (1 < \count($aPaths))
|
||||||
|
|
@ -493,7 +474,7 @@ trait CardDAV
|
||||||
|
|
||||||
$sPath = $sNewPath;
|
$sPath = $sNewPath;
|
||||||
|
|
||||||
$bGood = $this->checkContactsPath($oClient, $sPath);
|
$bGood = $sPath && $this->checkContactsPath($oClient, $sPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bGood ? $oClient : null;
|
return $bGood ? $oClient : null;
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class Client
|
||||||
$this->HTTP->setAuth(3, $settings['userName'] ?? '', $settings['password'] ?? '');
|
$this->HTTP->setAuth(3, $settings['userName'] ?? '', $settings['password'] ?? '');
|
||||||
$this->HTTP->max_response_kb = 0;
|
$this->HTTP->max_response_kb = 0;
|
||||||
$this->HTTP->timeout = 15; // timeout in seconds.
|
$this->HTTP->timeout = 15; // timeout in seconds.
|
||||||
// $this->HTTP->max_redirects = 0;
|
$this->HTTP->max_redirects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -69,11 +69,12 @@ class Client
|
||||||
$url = $this->baseUri . $url;
|
$url = $this->baseUri . $url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
\SnappyMail\Log::debug('DAV', "{$method} {$url}" . ($body ? "\n\t" . \str_replace("\n", "\n\t", $body) : ''));
|
||||||
$response = $this->HTTP->doRequest($method, $url, $body, $headers);
|
$response = $this->HTTP->doRequest($method, $url, $body, $headers);
|
||||||
if (301 == $response->status) {
|
if (301 == $response->status) {
|
||||||
// Like: RewriteRule ^\.well-known/carddav /nextcloud/remote.php/dav [R=301,L]
|
// Like: RewriteRule ^\.well-known/carddav /nextcloud/remote.php/dav [R=301,L]
|
||||||
$location = $response->getRedirectLocation();
|
$location = $response->getRedirectLocation();
|
||||||
\trigger_error("Redirect {$url} to {$location}");
|
\SnappyMail\Log::info('DAV', "301 Redirect {$url} to {$location}");
|
||||||
$url = \preg_replace('@^(https?:)?//[^/]+[/$]@', '/', $location);
|
$url = \preg_replace('@^(https?:)?//[^/]+[/$]@', '/', $location);
|
||||||
$parts = \parse_url($this->baseUri);
|
$parts = \parse_url($this->baseUri);
|
||||||
$url = $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port'])?':' . $parts['port']:'') . $url;
|
$url = $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port'])?':' . $parts['port']:'') . $url;
|
||||||
|
|
@ -82,6 +83,7 @@ class Client
|
||||||
if (300 <= $response->status) {
|
if (300 <= $response->status) {
|
||||||
throw new \SnappyMail\HTTP\Exception("{$method} {$url}", $response->status, $response);
|
throw new \SnappyMail\HTTP\Exception("{$method} {$url}", $response->status, $response);
|
||||||
}
|
}
|
||||||
|
\SnappyMail\Log::debug('DAV', "{$response->status}: {$response->body}");
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
@ -104,23 +106,20 @@ class Client
|
||||||
*/
|
*/
|
||||||
public function propFind(string $url, array $properties, int $depth = 0) : array
|
public function propFind(string $url, array $properties, int $depth = 0) : array
|
||||||
{
|
{
|
||||||
$body = '<?xml version="1.0"?>' . "\n";
|
$body = '<?xml version="1.0"?>' . "\n" . '<d:propfind xmlns:d="DAV:"><d:prop>';
|
||||||
$body.= '<d:propfind xmlns:d="DAV:">' . "\n";
|
|
||||||
$body.= ' <d:prop>' . "\n";
|
|
||||||
|
|
||||||
foreach ($properties as $property) {
|
foreach ($properties as $property) {
|
||||||
if (!\preg_match('/^{([^}]*)}(.*)$/', $property, $match)) {
|
if (!\preg_match('/^{([^}]*)}(.*)$/', $property, $match)) {
|
||||||
throw new \InvalidArgumentException('\'' . $property . '\' is not a valid clark-notation formatted string');
|
throw new \InvalidArgumentException('\'' . $property . '\' is not a valid clark-notation formatted string');
|
||||||
}
|
}
|
||||||
if ('DAV:' === $match[1]) {
|
if ('DAV:' === $match[1]) {
|
||||||
$body .= " <d:{$match[2]} />\n";
|
$body .= "<d:{$match[2]}/>";
|
||||||
} else {
|
} else {
|
||||||
$body .= " <x:{$match[2]} xmlns:x=\"{$match[1]}\"/>\n";
|
$body .= "<x:{$match[2]} xmlns:x=\"{$match[1]}\"/>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$body .= ' </d:prop>' . "\n";
|
$body .= '</d:prop></d:propfind>';
|
||||||
$body .= '</d:propfind>';
|
|
||||||
|
|
||||||
$response = $this->request('PROPFIND', $url, $body, array(
|
$response = $this->request('PROPFIND', $url, $body, array(
|
||||||
"Depth: {$depth}",
|
"Depth: {$depth}",
|
||||||
|
|
@ -144,7 +143,7 @@ class Client
|
||||||
null, LIBXML_NOBLANKS | LIBXML_NOCDATA);
|
null, LIBXML_NOBLANKS | LIBXML_NOCDATA);
|
||||||
|
|
||||||
if (false === $responseXML) {
|
if (false === $responseXML) {
|
||||||
throw new \InvalidArgumentException('The passed data is not valid XML');
|
throw new \UnexpectedValueException("The passed data is not valid XML\n{$response->body}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$ns = \array_search('urn:DAV', $responseXML->getNamespaces(true)) ?: 'd';
|
$ns = \array_search('urn:DAV', $responseXML->getNamespaces(true)) ?: 'd';
|
||||||
|
|
@ -163,13 +162,18 @@ class Client
|
||||||
foreach ($propStat->xpath("{$ns}:prop") as $prop) {
|
foreach ($propStat->xpath("{$ns}:prop") as $prop) {
|
||||||
foreach ($prop->xpath("*") as $element) {
|
foreach ($prop->xpath("*") as $element) {
|
||||||
$propertyName = self::toClarkNotation($element);
|
$propertyName = self::toClarkNotation($element);
|
||||||
|
$propList[$propertyName] = [];
|
||||||
if ('{DAV:}resourcetype' === $propertyName) {
|
if ('{DAV:}resourcetype' === $propertyName) {
|
||||||
$propList[$propertyName] = [];
|
|
||||||
foreach ($element->xpath("*") as $resourcetype) {
|
foreach ($element->xpath("*") as $resourcetype) {
|
||||||
$propList[$propertyName][] = self::toClarkNotation($resourcetype);
|
$propList[$propertyName][] = self::toClarkNotation($resourcetype);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$propList[$propertyName] = (string) $element;
|
foreach ($element->xpath("*") as $child) {
|
||||||
|
$propList[$propertyName][self::toClarkNotation($child)] = (string) $child;
|
||||||
|
}
|
||||||
|
if (!$propList[$propertyName]) {
|
||||||
|
$propList[$propertyName] = (string) $element;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue