mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-05-01 16:11:20 +00:00
Compare commits
7 Commits
63128ae2fd
...
35c8d78a15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35c8d78a15 | ||
|
|
8f38332fce | ||
|
|
1fec8fd111 | ||
|
|
f6547bd376 | ||
|
|
b4bcc6cc25 | ||
|
|
c1cfd8eb0d | ||
|
|
5920fe1efe |
@ -1,6 +1,9 @@
|
||||
2025-01-22 Andrew Ruthven <andrew@etc.gen.nz>
|
||||
* Using a Ticket ID requires public.php
|
||||
|
||||
2024-12-13 Andrew Ruthven <andrew@etc.gen.nz>
|
||||
* Fix iPhone's accessing other principal's collections.
|
||||
|
||||
2024-04-15 Andrew Ruthven <andrew@etc.gen.nz>
|
||||
* Add caching of user credential success/failure
|
||||
|
||||
|
||||
@ -363,13 +363,19 @@ class DAVResource
|
||||
|
||||
$this->FetchCollection();
|
||||
if ( $this->_is_collection ) {
|
||||
if ( $this->_is_principal || $this->collection->type == 'principal' ) $this->FetchPrincipal();
|
||||
if ( $this->_is_principal || $this->collection->type == 'principal' )
|
||||
$this->FetchPrincipal();
|
||||
}
|
||||
else {
|
||||
$this->FetchResource();
|
||||
}
|
||||
dbg_error_log( 'DAVResource', ':FromPath: Path "%s" is%s a collection%s.',
|
||||
$this->dav_name, ($this->_is_collection?' '.$this->resourcetypes:' not'), ($this->_is_principal?' and a principal':'') );
|
||||
$this->dav_name,
|
||||
($this->_is_collection ? ' ' . $this->resourcetypes
|
||||
: ' not'),
|
||||
($this->_is_principal ? ' and a principal'
|
||||
: '')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -569,29 +575,34 @@ EOSQL;
|
||||
$cache_ns = 'collection-'.preg_replace( '{/[^/]*$}', '/', $this->dav_name);
|
||||
$cache_key = 'dav_resource'.$session->user_no;
|
||||
$this->collection = $cache->get( $cache_ns, $cache_key );
|
||||
|
||||
if ( $this->collection === false ) {
|
||||
$this->ReadCollectionFromDatabase();
|
||||
|
||||
if ( $this->collection->type != 'principal' && $this->_collection_is_cacheable ) {
|
||||
$cache_ns = 'collection-'.$this->collection->dav_name;
|
||||
@dbg_error_log( 'Cache', ':FetchCollection: Setting cache ns "%s" key "%s". Type: %s', $cache_ns, $cache_key, $this->collection->type );
|
||||
$cache->set( $cache_ns, $cache_key, $this->collection );
|
||||
}
|
||||
|
||||
@dbg_error_log( 'DAVResource', ':FetchCollection: Found collection named "%s" of type "%s".', $this->collection->dav_name, $this->collection->type );
|
||||
}
|
||||
else {
|
||||
@dbg_error_log( 'Cache', ':FetchCollection: Got cache ns "%s" key "%s". Type: %s', $cache_ns, $cache_key, $this->collection->type );
|
||||
if ( preg_match( '#^(/[^/]+)/?$#', $this->dav_name, $matches)
|
||||
|| preg_match( '#^((/principals/[^/]+/)[^/]+)/?$#', $this->dav_name, $matches) ) {
|
||||
@dbg_error_log( 'Cache', ':FetchCollection: Got cache ns "%s" key "%s". dav_name: "%s", Type: %s', $cache_ns, $cache_key, $this->collection->dav_name, $this->collection->type );
|
||||
|
||||
if ($this->collection->type == 'principal') {
|
||||
$this->_is_principal = true;
|
||||
$this->FetchPrincipal();
|
||||
$this->collection->is_principal = true;
|
||||
$this->collection->type = 'principal';
|
||||
} else {
|
||||
if ($this->collection->type == 'proxy') {
|
||||
$this->_is_proxy_resource = true;
|
||||
$this->proxy_type = $this->collection->proxy_type;
|
||||
}
|
||||
|
||||
} else if ($this->collection->type == 'calendar') {
|
||||
$this->_is_calendar = true;
|
||||
|
||||
} else if ($this->collection->type == 'proxy') {
|
||||
$this->_is_proxy_resource = true;
|
||||
$this->proxy_type = $this->collection->proxy_type;
|
||||
}
|
||||
|
||||
@dbg_error_log( 'DAVResource', ':FetchCollection: Read cached collection named "%s" of type "%s".', $this->collection->dav_name, $this->collection->type );
|
||||
}
|
||||
|
||||
@ -1881,8 +1892,15 @@ EOQRY;
|
||||
$prop->NewElement( 'principal-collection-set', $reply->href( ConstructURL('/') ) );
|
||||
break;
|
||||
|
||||
# iPhone devices incorrectly implement DAV:current-user-principal from
|
||||
# RFC 5397. They assume that current-user-principal is the href for the
|
||||
# resource being queried. The RFC says it should be the current resource.
|
||||
# See: https://gitlab.com/davical-project/davical/-/issues/335
|
||||
case 'DAV::current-user-principal':
|
||||
$prop->NewElement('current-user-principal', $reply->href( ConstructURL(DeconstructURL($session->principal->url())) ) );
|
||||
if ( preg_match('/iPhone/', $_SERVER['HTTP_USER_AGENT']) )
|
||||
$prop->NewElement('current-user-principal', $reply->href( ConstructURL(DeconstructURL($request->principal->url())) ) );
|
||||
else
|
||||
$prop->NewElement('current-user-principal', $reply->href( ConstructURL(DeconstructURL($session->principal->url())) ) );
|
||||
break;
|
||||
|
||||
case 'SOME-DENIED-PROPERTY': /** indicating the style for future expansion */
|
||||
|
||||
@ -125,6 +125,9 @@ function process_ace( $grantor, $by_principal, $by_collection, $ace ) {
|
||||
$principal_content = $principal_node->GetContent();
|
||||
if ( count($principal_content) != 1 ) $request->MalformedRequest('ACL request must contain exactly one principal per ACE');
|
||||
$principal_content = $principal_content[0];
|
||||
|
||||
dbg_error_log( 'ACE', 'NSTag: "%s", by_collection: %s, by_principal: %s', $principal_content->GetNSTag(), $by_collection ?? 'Null', $by_principal ?? 'Null');
|
||||
|
||||
switch( $principal_content->GetNSTag() ) {
|
||||
case 'DAV::property':
|
||||
$principal_property = $principal_content->GetContent();
|
||||
@ -142,8 +145,10 @@ function process_ace( $grantor, $by_principal, $by_collection, $ace ) {
|
||||
$principal_type = 'href';
|
||||
$grantee = new DAVResource( DeconstructURL($principal_content->GetContent()) );
|
||||
$grantee_id = $grantee->getProperty('principal_id');
|
||||
|
||||
if ( !$grantee->Exists() || !$grantee->IsPrincipal() )
|
||||
$request->PreconditionFailed(403,'recognized-principal', 'Principal "' . $principal_content->GetContent() . '" not found.');
|
||||
|
||||
$sqlparms = array( ':to_principal' => $grantee_id);
|
||||
$where = 'WHERE to_principal=:to_principal AND ';
|
||||
if ( isset($by_principal) ) {
|
||||
@ -154,6 +159,7 @@ function process_ace( $grantor, $by_principal, $by_collection, $ace ) {
|
||||
$sqlparms[':by_collection'] = $by_collection;
|
||||
$where .= 'by_collection = :by_collection';
|
||||
}
|
||||
|
||||
$qry = new AwlQuery('SELECT privileges FROM grants '.$where, $sqlparms);
|
||||
if ( $qry->Exec('ACL',__LINE__,__FILE__) && $qry->rows() == 1 && $current = $qry->Fetch() ) {
|
||||
$sql = 'UPDATE grants SET privileges=:privileges::INT::BIT(24) '.$where;
|
||||
@ -169,6 +175,15 @@ function process_ace( $grantor, $by_principal, $by_collection, $ace ) {
|
||||
Principal::cacheDelete('dav_name',$grantee->dav_name());
|
||||
Principal::cacheFlush('principal_id IN (SELECT member_id FROM group_member WHERE group_id = ?)', array($grantee_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically this has changed everyone's permissions now, so...
|
||||
*/
|
||||
$cache = getCacheInstance();
|
||||
$cache->flush();
|
||||
|
||||
#Principal::cacheFlush('TRUE');
|
||||
|
||||
break;
|
||||
|
||||
case 'DAV::authenticated':
|
||||
|
||||
@ -70,7 +70,7 @@ class CalDAVClient {
|
||||
protected $calendar_urls;
|
||||
|
||||
/**
|
||||
* The useragent which is send to the caldav server
|
||||
* The useragent which is sent to the caldav server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
||||
@ -26,7 +26,7 @@ class CalDAVClient {
|
||||
var $base_url, $user, $pass, $calendar, $entry, $protocol, $server, $port;
|
||||
|
||||
/**
|
||||
* The useragent which is send to the caldav server
|
||||
* The useragent which is sent to the caldav server
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
@ -119,12 +119,13 @@ class CalDAVClient {
|
||||
*/
|
||||
function ParseResponse( $response ) {
|
||||
$pos = strpos($response, '<?xml');
|
||||
$epos = strrpos($response, '>');
|
||||
if ($pos === false) {
|
||||
$this->httpResponse = trim($response);
|
||||
}
|
||||
else {
|
||||
$this->httpResponse = trim(substr($response, 0, $pos));
|
||||
$this->xmlResponse = trim(substr($response, $pos));
|
||||
$this->xmlResponse = trim(substr($response, $pos, $epos-$pos+1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
HTTP/1.1 200 OK
|
||||
Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
|
||||
SQL Query 1 Result:
|
||||
by_collection: >1609<
|
||||
by_principal: >NULL<
|
||||
displayname: >User 4<
|
||||
privileges: >000000000000000000100001<
|
||||
to_principal: >1005<
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
# Test for iPhone devices which incorrectly implement
|
||||
# DAV:current-user-principal from RFC 5397. They assume that
|
||||
# current-user-principal is the href for the resource being queried. The
|
||||
# RFC says it should be the current resource. #Sigh.
|
||||
#
|
||||
# See: https://gitlab.com/davical-project/davical/-/issues/335
|
||||
#
|
||||
# Ensure that user4 can access user1's address book.
|
||||
TYPE=ACL
|
||||
HEADER=User-Agent: RFC3744 Spec Tests
|
||||
HEADER=Content-Type: text/xml; charset="UTF-8"
|
||||
HEAD
|
||||
|
||||
BEGINDATA
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<acl xmlns="DAV:" xmlns:CalDAV="urn:ietf:params:xml:ns:caldav">
|
||||
<ace>
|
||||
<principal>
|
||||
<href>/caldav.php/user4/</href>
|
||||
</principal>
|
||||
<grant>
|
||||
<privilege><read/></privilege>
|
||||
<privilege><read-current-user-privilege-set/></privilege>
|
||||
</grant>
|
||||
</ace>
|
||||
<ace>
|
||||
<principal><authenticated/></principal>
|
||||
<grant>
|
||||
<privilege/>
|
||||
</grant>
|
||||
</ace>
|
||||
</acl>
|
||||
ENDDATA
|
||||
|
||||
URL=http://regression.host/caldav.php/user1/
|
||||
|
||||
# This is by_collection, and by_principal isn't set, shouldn't it be set?
|
||||
# WHERE p_by.dav_name = '/user1/'
|
||||
QUERY
|
||||
SELECT by_principal, by_collection, privileges, p_to.displayname, to_principal
|
||||
FROM grants JOIN dav_principal p_to ON (to_principal=principal_id)
|
||||
LEFT JOIN collection ON (by_collection=collection.collection_id)
|
||||
LEFT JOIN dav_principal p_by ON (by_principal=p_by.principal_id)
|
||||
WHERE by_collection = 1609
|
||||
AND p_to.dav_name = '/user4/'
|
||||
ORDER BY by_principal, to_principal
|
||||
ENDQUERY
|
||||
@ -0,0 +1,50 @@
|
||||
HTTP/1.1 207 Multi-Status
|
||||
Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
Content-Location: /caldav.php/user1/addresses/
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy
|
||||
ETag: "43765875e20eef2d841725645b2f3c95"
|
||||
Content-Length: 1129
|
||||
Content-Type: text/xml; charset="utf-8"
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
|
||||
<response>
|
||||
<href>/caldav.php/user1/addresses/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<getcontenttype>httpd/unix-directory</getcontenttype>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<C:addressbook/>
|
||||
</resourcetype>
|
||||
<displayname>user1 addresses</displayname>
|
||||
<getlastmodified>Sun, 15 Mar 1998 12:00:00 GMT</getlastmodified>
|
||||
<creationdate>19570725T120000Z</creationdate>
|
||||
<getcontentlanguage/>
|
||||
<supportedlock>
|
||||
<lockentry>
|
||||
<lockscope>
|
||||
<exclusive/>
|
||||
</lockscope>
|
||||
<locktype>
|
||||
<write/>
|
||||
</locktype>
|
||||
</lockentry>
|
||||
</supportedlock>
|
||||
<owner>
|
||||
<href>/caldav.php/user1/</href>
|
||||
</owner>
|
||||
<current-user-principal>
|
||||
<href>/caldav.php/user1/</href>
|
||||
</current-user-principal>
|
||||
<C:max-resource-size>6550000</C:max-resource-size>
|
||||
<C:supported-address-data>
|
||||
<C:address-data content-type="text/vcard" version="3.0"/>
|
||||
</C:supported-address-data>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
</multistatus>
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
# Test for iPhone devices which incorrectly implement
|
||||
# DAV:current-user-principal from RFC 5397. They assume that
|
||||
# current-user-principal is the href for the resource being queried. The
|
||||
# RFC says it should be the current resource. #Sigh.
|
||||
#
|
||||
# See: https://gitlab.com/davical-project/davical/-/issues/335
|
||||
#
|
||||
# Ensure that user4 has user1 as the current-user-principal as we're an
|
||||
# 'iPhone'.
|
||||
TYPE=PROPFIND
|
||||
AUTH=user4:user4
|
||||
HEADER=Content-Type: text/xml; charset="UTF-8"
|
||||
HEADER=User-Agent: DAVKit/4.0 (728.3); iCalendar/1 (34); iPhone/3.0
|
||||
HEAD
|
||||
|
||||
URL=http://regression.host/caldav.php/user1/addresses
|
||||
@ -0,0 +1,50 @@
|
||||
HTTP/1.1 207 Multi-Status
|
||||
Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
Content-Location: /caldav.php/user1/addresses/
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy
|
||||
ETag: "3f9506c10fe5b434f966d4c82f026c40"
|
||||
Content-Length: 1129
|
||||
Content-Type: text/xml; charset="utf-8"
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav">
|
||||
<response>
|
||||
<href>/caldav.php/user1/addresses/</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<getcontenttype>httpd/unix-directory</getcontenttype>
|
||||
<resourcetype>
|
||||
<collection/>
|
||||
<C:addressbook/>
|
||||
</resourcetype>
|
||||
<displayname>user1 addresses</displayname>
|
||||
<getlastmodified>Sun, 15 Mar 1998 12:00:00 GMT</getlastmodified>
|
||||
<creationdate>19570725T120000Z</creationdate>
|
||||
<getcontentlanguage/>
|
||||
<supportedlock>
|
||||
<lockentry>
|
||||
<lockscope>
|
||||
<exclusive/>
|
||||
</lockscope>
|
||||
<locktype>
|
||||
<write/>
|
||||
</locktype>
|
||||
</lockentry>
|
||||
</supportedlock>
|
||||
<owner>
|
||||
<href>/caldav.php/user1/</href>
|
||||
</owner>
|
||||
<current-user-principal>
|
||||
<href>/caldav.php/user4/</href>
|
||||
</current-user-principal>
|
||||
<C:max-resource-size>6550000</C:max-resource-size>
|
||||
<C:supported-address-data>
|
||||
<C:address-data content-type="text/vcard" version="3.0"/>
|
||||
</C:supported-address-data>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
</multistatus>
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
# Test for iPhone devices which incorrectly implement
|
||||
# DAV:current-user-principal from RFC 5397. They assume that
|
||||
# current-user-principal is the href for the resource being queried. The
|
||||
# RFC says it should be the current resource. #Sigh.
|
||||
#
|
||||
# See: https://gitlab.com/davical-project/davical/-/issues/335
|
||||
#
|
||||
# Ensure that user4 has user4 as the current-user-principal as we're not an
|
||||
# 'iPhone'.
|
||||
TYPE=PROPFIND
|
||||
AUTH=user4:user4
|
||||
HEADER=Content-Type: text/xml; charset="UTF-8"
|
||||
HEADER=User-Agent: Evolution/1.8.1
|
||||
HEAD
|
||||
|
||||
URL=http://regression.host/caldav.php/user1/addresses
|
||||
Loading…
x
Reference in New Issue
Block a user