In a previous question, I asked about syncing data with a DaviCal server. I ended up concluding that there was a bug on DaviCal as when querying a CalDav server with an invalid sync token, the server should return an error but, instead, it returns the whole set of events on the server.
So I started looking for an alternative CalDav server. I use SabreDav. I followed their very handy tutorial here.
On there it says:
Caveats
Note that a server is free to 'forget' any sync-tokens that have been previously issued. In this case it may be needed to do a full-sync again.
In case the supplied sync-token is not recognized by the server, a HTTP error is emitted. SabreDAV emits a 403.
That looks promising : exactly what I need !
So what I do is getting my sync-token which is http://sabre.io/ns/sync/15
.
I then submit my REPORT
query as follows (maybe that's where I do things wrong?!)
string syncToken = "http://sabre.io/ns/sync/15";
string body = " <d:sync-collection xmlns:d=\"DAV:\"> " +
" <d:sync-token>" + syncToken + "</d:sync-token> " +
" <d:sync-level>1</d:sync-level> " +
" <d:prop> " +
" <d:getetag/> " +
" </d:prop> " +
" </d:sync-collection> ";
Request = (HttpWebRequest)HttpWebRequest.Create("http://my.sabredav.com/calendars/example/home/");
Request.Credentials = new NetworkCredential("my_user", "my_pwd");
Request.Method = "REPORT";
Request.ContentType = "application/xml";
// set the body of the request...
Request.ContentLength = body.Length;
using (Stream reqStream = Request.GetRequestStream()) {
// Write the string to the destination as a text file.
byte[] encodedBody = Encoding.UTF8.GetBytes(body);
reqStream.Write(encodedBody, 0, encodedBody.Length);
reqStream.Close();
}
// Send the method request and get the response from the server.
Response = (HttpWebResponse)Request.GetResponse();
So when I send the request using the valid sync-token http://sabre.io/ns/sync/15
I just got, I get an empty response:
<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.or /ns/">
<d:sync-token>http://sabre.io/ns/sync/15</d:sync-token>
</d:multistatus>
So far so good.
If I use a previous sync-token that I know was valid at some point (http://sabre.io/ns/sync/14
in this case - by chance it is the previous number...) I get changes as expected:
<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
<d:response>
<d:href>/calendarserver.php/calendars/admin/default/23b351ee-7677-46e3-b5c5-5263e8fca351.ics</d:href>
<d:propstat>
<d:prop>
<d:getetag>"8d8d122a66625ca990252fae652cd2e5"</d:getetag>
</d:prop>
<d:status>HTTP/1.1 200 OK</d:status>
</d:propstat>
</d:response>
<d:sync-token>http://sabre.io/ns/sync/15</d:sync-token>
</d:multistatus>
But the issue is, that if I use a RANDOM sync token that I definitely know has never been issued: http://sabre.io/ns/sync/1234312231344324
I get the SAME answer as when I was using the latest (current) token:
<?xml version="1.0"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
<d:sync-token>http://sabre.io/ns/sync/15</d:sync-token>
</d:multistatus>
SabreDav says it's supposed to throw an error 403, but clearly, it's not what I get here... However, if I use INVALID sync-token format, say token1234
, I do indeed get an error 403...
So the question is: HOW can I make sure my sync-token is still valid ? So, if the token is valid and nothing is returned, I know my local cache is up to date or, in case the sync-token is INVALID, I need to do full sync!
This is indeed a bug in sabre/dav. Feel free to open a bug report so it's on our radar. It's never been a major concern, as 'well behaved clients' would never supply a sync-token that was never issued by us.
The reason it's happening, is because the digit is simply an ever increasing record id in our database. To fetch all the changes a simple sql query with a
>
is done.If you explicitly want to test invalid tokens in your client, I would recommend to simply supply a sync-token with a completely different format (something that doesn't start with
http://sabre.io/ns/sync
).