forwardemail / caldav-adapter

CalDAV server for Node.js and Koa. Modernized and maintained for @forwardemail
https://forwardemail.net
MIT License
27 stars 9 forks source link

ETag with Android #3

Closed lixaotec closed 3 years ago

lixaotec commented 4 years ago

Dear @sedenardi ! It me again.

I was trying to use your tool with android devices. Found out that they do not have native support for caldav protocol as iOS does.

So I did a research for the most acceptable open and free solution, for it, and discovered that there are only few stable, and one of most promising is the OpenSync. (https://play.google.com/store/apps/details?id=com.deependhulla.opensync)

However I had trouble in order to get it working, as it says something with ETag missing.

Can you provide any tip so that I can adjust it?

Thanks again!

--- BEGIN DEBUG INFO --- SYNCHRONIZATION INFO Synchronization phase: 8 Account name: user@ex Authority: com.android.calendar

CURRENT REMOTE RESOURCE: https://192.168.100.11:3001/caldav/cal/user@ex.co/exampleCal2/EE6BCBAF-C85B-49F5-A5C4-6EFB9F5090FF.ics

EXCEPTION: at.bitfire.dav4android.exception.DavException: Server didn't provide ETag at com.deependhulla.opensync.syncadapter.SyncManager.compareLocalRemote(SyncManager.java:439) at com.deependhulla.opensync.syncadapter.SyncManager.performSync(SyncManager.java:175) at com.deependhulla.opensync.syncadapter.CalendarsSyncAdapterService$SyncAdapter.onPerformSync(CalendarsSyncAdapterService.java:70) at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:334)

SOFTWARE INFORMATION OpenSync version: 1.5.0.3-ose (145) Tue Apr 18 04:03:24 GMT-03:00 2017 Installed from: com.android.vending JB Workaround installed: no

CONFIGURATION Power saving disabled: no android.permission.READ_CONTACTS permission: denied android.permission.WRITE_CONTACTS permission: denied android.permission.READ_CALENDAR permission: granted android.permission.WRITE_CALENDAR permission: granted org.dmfs.permission.READ_TASKS permission: denied org.dmfs.permission.WRITE_TASKS permission: denied System-wide synchronization: automatically Account: user@ex Address book sync. interval: — Calendar sync. interval: 240 min OpenTasks sync. interval: — WiFi only: false [CardDAV] Contact group method: GROUP_VCARDS [CalDAV] Time range (past days): 90 Manage calendar colors: true

SQLITE DUMP android_metadata | locale | | ***** |

settings | setting | value |

services | _id | accountName | service | principal | | 1 | user@ex | caldav | https://192.168.100.11:3001/caldav/p/user@ex.co/ |

sqlite_sequence | name | seq | | services | 1 | | homesets | 2 | | collections | 2 |

homesets | _id | serviceID | url | | 2 | 1 | https://192.168.100.11:3001/caldav/cal/user@ex.co/ |

collections | _id | serviceID | url | readOnly | displayName | description | color | timezone | supportsVEVENT | supportsVTODO | sync | | 1 | 1 | https://192.168.100.11:3001/caldav/cal/user@ex.co/exampleCal2/ | 0 | Example Calendar 2 | | | | 1 | 0 | 1 | | 2 | 1 | https://192.168.100.11:3001/caldav/cal/user@ex.co/exampleCal1/ | 1 | Example Calendar 1 | | | | 1 | 0 | 0 |

SYSTEM INFORMATION Android version: 10 (QP1A.190711.020.A705MNXXU5BTC2) Device: Samsung SM-A705MN (a70q)

--- END DEBUG INFO ---

sedenardi commented 4 years ago

Can you post the XML response that the server is sending that's jamming up the Android app?

aharter commented 3 years ago

I took the adapter on a test drive using davx5 on Android as a client. To me, it seems like it requests an E-Tag using <getetag/> during a propfind request, which is not fulfilled by the response. This is the output:

[...]
2020-12-15 20:59:19:829 verbose [server]:   PROPFIND /caldav/cal/user@ex.co/exampleCal1/ 207 - - 26.303 ms
2020-12-15 20:59:19:923 verbose [server]:   user: user@ex, pass: pass
2020-12-15 20:59:19:924 verbose [index]:    REQUEST BODY: 
<?xml version="1.0" encoding="UTF-8"?>
<CAL:calendar-query xmlns="DAV:" xmlns:CAL="urn:ietf:params:xml:ns:caldav">
  <prop>
    <getetag/>
  </prop>
  <CAL:filter>
    <CAL:comp-filter name="VCALENDAR">
      <CAL:comp-filter name="VEVENT">
        <CAL:time-range start="20200916T185919Z"/>
      </CAL:comp-filter>
    </CAL:comp-filter>
  </CAL:filter>
</CAL:calendar-query>
2020-12-15 20:59:19:928 verbose [index]:    RESPONSE BODY: 
<?xml version="1.0"?>
<D:multistatus xmlns:D="DAV:" xmlns:CAL="urn:ietf:params:xml:ns:caldav" xmlns:CS="http://calendarserver.org/ns/" xmlns:ICAL="http://apple.com/ns/ical/">
  <D:response>
    <D:href>/caldav/cal/user@ex.co/exampleCal1/</D:href>
    <D:propstat>
      <D:status>HTTP/1.1 200 OK</D:status>
      <D:prop>
        <D:supported-report-set>
          <D:supported-report>
            <D:report>
              <CAL:calendar-query/>
            </D:report>
          </D:supported-report>
          <D:supported-report>
            <D:report>
              <CAL:calendar-multiget/>
            </D:report>
          </D:supported-report>
          <D:supported-report>
            <D:report>
              <CAL:sync-collection/>
            </D:report>
          </D:supported-report>
        </D:supported-report-set>
      </D:prop>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>/caldav/cal/user@ex.co/exampleCal1/41c6fcc0-aea7-304f-983a-a6fb7e568109.ics</D:href>
    <D:propstat>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>/caldav/cal/user@ex.co/exampleCal1/faf52014-372e-44ed-9eba-2fc1a2b8d82d.ics</D:href>
    <D:propstat>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
  <D:response>
    <D:href>/caldav/cal/user@ex.co/exampleCal1/895a04b2-30df-4927-ba03-dfc55514f6e7.ics</D:href>
    <D:propstat>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>
2020-12-15 20:59:19:933 verbose [server]:   REPORT /caldav/cal/user@ex.co/exampleCal1/ 207 - - 9.741 ms
sedenardi commented 3 years ago

<D:getetag> is present on the actual event objects in the response. Are you expecting them on the actual calendars?

aharter commented 3 years ago

I digged a bit deeper and edited the log entry to only contain the request that seem to cause the problem. I also forgot to mention, that I only tested it with Example Calendar 1. There are several things that come into play: First, the request payload is ignored. This is due to the hard-coded /D:propfind/D:prop in getWithChildren as described by HeikoTheissen in #6. After that, the request only defines start for time-range. The example retrieve function uses (v.startDate >= start && v.endDate <= end), which causes no events to returned. However, this triggers issue #8. Since the nsMap of the previous request is used, all events show up in the payload. However, without the etag, triggering the issue.

I modified the code accordingly. This causes the recurring events (as defined by Testing Event 5) to not be part of the payload. From what I can tell, this is due to the check v.weekly in examples/data.js, which is always undefined.

I hope I can hand in a PR soon. Just thought I share my findings for transparency.