CalDav sync-token expiry

1.4k views Asked by At

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>&quot;8d8d122a66625ca990252fae652cd2e5&quot;</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!

1

There are 1 answers

4
Evert On

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).