I am trying to access a calendar on SOGo over CalDAV using ical4j 1.0.1.
The SOGo instance I am accessing is version 1.3.9.
Here is the piece of java code:
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true);
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true);
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION, true);
URL url = new URL("https", "sogo.mycompany.com", -1, "/");
CalDavCalendarStore store = new CalDavCalendarStore("-//MacTI//WOCal//EN", url, new PathResolver() {
@Override
public String getPrincipalPath(String username) {
return "/SOGo/dav/" + username + "/";
}
@Override
public String getUserPath(String username) {
return "/SOGo/dav/" + username + "/";
});
store.connect("gazda", "********".toCharArray());
CalDavCalendarCollection col =
store.getCollection("/SOGo/dav/gazda/Calendar/personal/");
The problem is that store.getCollection() internally tries to check if the collection exists with a GET request which fails throwing an ObjectStoreException. Here is the relevant piece of SOGo log:
The question is: Who is wrong? ical4j using GET to test existence of a collection or SOGo not supporting GET requests for that purpose?
Could you please tell me the relevant RFC section?
I posted the same question on the SOGo list yesterday, but there is no reply so far.
Workaround:
The whole thing works if I avoid the invocation of net.fortuna.ical4j.connector.dav.AbstractDavObjectCollection<T>.exists()
Unfortunately the API does not allow such a thing. I either have to change the source or I must change the accessibility of the two argument constructor of CalDavCalendarCollection using java reflection to call it directly.
Can you see a better way to avoid that GET request?
Thanks in advance,
Gazda
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I guess it should try to do a HEAD instead of a GET to see if the resource exists. Can you try it manually to see if it works with a HEAD?
Are you running the latest version of SoGo? I didn't even know that groupware so I will install it in a VM to see how it works, and I would like to run the same version as you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just did some tests, and even HEAD is not supported. So far, I have tried GET, HEAD, PROPFIND and PROPPATCH, and both PROPFIND and PROPPATCH is supported by SOGo. So I guess we should change the GET call to a PROPFIND call.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
mbp-pascal-robert-4:ical4j probert$ curl -X OPTIONS -u xxx:yyyy -v http://wwwww/SOGo/dav/xxxx/Calendar/personal/
* About to connect() to xxx:yyyy port 80 (#0)
* Server auth using Basic with user 'xxx'
> OPTIONS /SOGo/dav/probert/Calendar/personal/ HTTP/1.1
> Authorization: Basic xxxxxxxx==
> User-Agent: curl/7.23.1 (x86_64-apple-darwin11.2.0) libcurl/7.23.1 OpenSSL/1.0.0e zlib/1.2.5 libidn/1.22
> Host: xxx.yyyy
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 01 Dec 2011 20:09:10 GMT
< content-length: 0
< content-type: text/plain; charset=UTF-8
< dav: 1, 2, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-proxy, calendar-query-extended, extended-mkcol, calendarserver-principal-property-search
< allow: GET, HEAD, POST, OPTIONS, MKCOL, MKCALENDAR, DELETE, PUT, LOCK, UNLOCK, COPY, MOVE, PROPFIND, SEARCH
< Connection: close
<
* Closing connection #0
So an OPTIONS call says that GET is supported, but asking for it returns a 501 error. I didn't find anything in the RFC to check if a collection exists or not, so I will change the request to use OPTIONS instead of GET.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
An OPTIONS method on a non existing collection will return a HTTP 200, so it's not an alternative. I just tried with a PROPFIND method on a non existing collection, and same thing, I'm getting a 200 and 207. I didn't see anything in the RFC to check if a collection exists, so I have sent an email to the ietf-caldav mailing list to see if someone have an answer.
Couple of options:
- Trapping "Not Implemented" errors and if such error is throw, we just assume that the collection exists
- Trapping "Not Implemented" and sending a different exception (NotImplemented) that we can handle differently
- We don't check if the collection exist, and errors will be throw when you try to change the collection (when you add a new icalendar file, etc.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ok, so I'm told that the best way of checking if a collection exists is with a PROPFIND method, and an 404 error should be returned if the collection don't exist. This is the behavior I get on iCloud (I assume it's based on CalendarServer), but on CommuniGate Pro 5.3, it returns a 200.
Anyway, I'm sending a patch so that it use PROPFIND. For cases like CommuniGate Pro, errors will occurs later, e.g. when you try to modify the collection. For example, if I try to PUT a new calendar object in a non existing collection on CommuniGate Pro, I get:
net.fortuna.ical4j.connector.ObjectStoreException: Error creating calendar on server: HTTP/1.1 500 mailbox does not exist
Which is correct.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
According to the discussions in the ietf mailing list, not having GET support is fine. The problem is more that they advertise GET as an allowed method, that's the thing they should change.
BTW, I added a SOGo path resolver to ical4j-connector, and I was able to find events, create a new event and to check for delegated collections (calendar-proxy) so basic support for SOGo should be fine.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
What does your PathResolver look like? Do you return return "/SOGo/dav/" + username + "/" for both user and principal paths in accordance with my uneducated quess?
Gentlemen,
I am trying to access a calendar on SOGo over CalDAV using ical4j 1.0.1.
The SOGo instance I am accessing is version 1.3.9.
Here is the piece of java code:
The problem is that store.getCollection() internally tries to check if the collection exists with a GET request which fails throwing an ObjectStoreException. Here is the relevant piece of SOGo log:
The question is: Who is wrong? ical4j using GET to test existence of a collection or SOGo not supporting GET requests for that purpose?
Could you please tell me the relevant RFC section?
I posted the same question on the SOGo list yesterday, but there is no reply so far.
Workaround:
The whole thing works if I avoid the invocation of net.fortuna.ical4j.connector.dav.AbstractDavObjectCollection<T>.exists()
Unfortunately the API does not allow such a thing. I either have to change the source or I must change the accessibility of the two argument constructor of CalDavCalendarCollection using java reflection to call it directly.
Can you see a better way to avoid that GET request?
Thanks in advance,
Gazda
I guess it should try to do a HEAD instead of a GET to see if the resource exists. Can you try it manually to see if it works with a HEAD?
Are you running the latest version of SoGo? I didn't even know that groupware so I will install it in a VM to see how it works, and I would like to run the same version as you.
Just did some tests, and even HEAD is not supported. So far, I have tried GET, HEAD, PROPFIND and PROPPATCH, and both PROPFIND and PROPPATCH is supported by SOGo. So I guess we should change the GET call to a PROPFIND call.
Further findings. Doing a OPTIONS call:
mbp-pascal-robert-4:ical4j probert$ curl -X OPTIONS -u xxx:yyyy -v http://wwwww/SOGo/dav/xxxx/Calendar/personal/
* About to connect() to xxx:yyyy port 80 (#0)
* Server auth using Basic with user 'xxx'
> OPTIONS /SOGo/dav/probert/Calendar/personal/ HTTP/1.1
> Authorization: Basic xxxxxxxx==
> User-Agent: curl/7.23.1 (x86_64-apple-darwin11.2.0) libcurl/7.23.1 OpenSSL/1.0.0e zlib/1.2.5 libidn/1.22
> Host: xxx.yyyy
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 01 Dec 2011 20:09:10 GMT
< content-length: 0
< content-type: text/plain; charset=UTF-8
< dav: 1, 2, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-proxy, calendar-query-extended, extended-mkcol, calendarserver-principal-property-search
< allow: GET, HEAD, POST, OPTIONS, MKCOL, MKCALENDAR, DELETE, PUT, LOCK, UNLOCK, COPY, MOVE, PROPFIND, SEARCH
< Connection: close
<
* Closing connection #0
So an OPTIONS call says that GET is supported, but asking for it returns a 501 error. I didn't find anything in the RFC to check if a collection exists or not, so I will change the request to use OPTIONS instead of GET.
An OPTIONS method on a non existing collection will return a HTTP 200, so it's not an alternative. I just tried with a PROPFIND method on a non existing collection, and same thing, I'm getting a 200 and 207. I didn't see anything in the RFC to check if a collection exists, so I have sent an email to the ietf-caldav mailing list to see if someone have an answer.
Couple of options:
- Trapping "Not Implemented" errors and if such error is throw, we just assume that the collection exists
- Trapping "Not Implemented" and sending a different exception (NotImplemented) that we can handle differently
- We don't check if the collection exist, and errors will be throw when you try to change the collection (when you add a new icalendar file, etc.)
Ok, so I'm told that the best way of checking if a collection exists is with a PROPFIND method, and an 404 error should be returned if the collection don't exist. This is the behavior I get on iCloud (I assume it's based on CalendarServer), but on CommuniGate Pro 5.3, it returns a 200.
Anyway, I'm sending a patch so that it use PROPFIND. For cases like CommuniGate Pro, errors will occurs later, e.g. when you try to modify the collection. For example, if I try to PUT a new calendar object in a non existing collection on CommuniGate Pro, I get:
net.fortuna.ical4j.connector.ObjectStoreException: Error creating calendar on server: HTTP/1.1 500 mailbox does not exist
Which is correct.
Many thanks for your efforts, Elvis.
I have tried to reproduce your curl findings with my SOGo 1.3.9 instance.
For /SOGo/dav/nosuch/Calendar/personal/ which does not exist I am getting
404 for all of PROPFIND, OPTIONS and GET
And for /SOGo/dav/gazda/Calendar/personal/ which exists I am getting
207 for PROPFIND
200 for OPTIONS
501 for GET
So both PROPFIND and OPTIONS seem to be usable for testing the existence of a collection on SOGo 1.3.9.
As for GET, I tend to believe that it is a bug on the side of SOGo. I will post this info back to them.
According to the discussions in the ietf mailing list, not having GET support is fine. The problem is more that they advertise GET as an allowed method, that's the thing they should change.
BTW, I added a SOGo path resolver to ical4j-connector, and I was able to find events, create a new event and to check for delegated collections (calendar-proxy) so basic support for SOGo should be fine.
Thank you again, Pascal.
What does your PathResolver look like? Do you return return "/SOGo/dav/" + username + "/" for both user and principal paths in accordance with my uneducated quess?
I have filed a bug for the 501 issue: http://www.sogo.nu/bugs/view.php?id=1528
Exactly, it returns "/SOGo/dav/" + username + "/" for both. In my tests, this works fine:
URL url = new URL("http", "192.168.3.46", 80, "");
CalDavCalendarStore store = new CalDavCalendarStore("//ERGroupware/EN", url, PathResolver.SOGO);
store.connect("probert","xxxxxxx".toCharArray());
store.getCollections();
store.getDelegatedCollections();