ERGroupware

1,106 views

Published on

Learn about how you can connect to CalDAV, MS Exchange and Zimbra servers with his upcoming Project Wonder framework.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,106
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

ERGroupware

  1. 1. ERGroupwarePascal RobertDruide informatique
  2. 2. • Let you generate iCalendar files, à la ERCalendar• Let you connect to groupware solutions• CalDAV• MS Exchange 2007/2010• Zimbra• Many Bothans have died to provide this frameworkWhat is ERGroupware?
  3. 3. iCalendar generation
  4. 4. iCalendar• iCalendar is a standard (RFC 2445, written in 1998).• A iCalendar object can have multiple components (VEVENT,VTODO, etc.)• Text file, with Base64 encoding for binary• Key value• You can add your own keys
  5. 5. iCalendar exampleBEGIN:VCALENDARVERSION:2.0PRODID:-//Apple Inc.//Mac OS X 10.8.4//ENCALSCALE:GREGORIANBEGIN:VEVENTTRANSP:OPAQUEDTEND:20130623T101500UID:DB0E22EA-0828-40A3-BCFD-5A8CC9866CE4DTSTAMP:20130514T135551ZLOCATION:Verdun/Lachine/LasalleX-MOZ-GENERATION:1URL;VALUE=URI:http://www.wocommunity.org/wowodc13/cayenne.htmlSEQUENCE:10SUMMARY:Cayenne Training DayLAST-MODIFIED:20130509T165550ZDTSTART:20130623T091500CREATED:20130505T001152ZEND:VEVENTEND:VCALENDAR
  6. 6. UID• Each component must have a UID• UID:DB0E22EA-0828-40A3-BCFD-5A8CC9866CE4• And it must be unique!
  7. 7. Attendees• Attendees are invitees.• Can be a individual, group, resource or room. (CUType)• Also have status: needs action, accepted, etc. (Partstat)• If you have attendees, you also need an organizer!
  8. 8. iCalendar in ERGroupware• Similar to ERCalendar, but more modern and better validation.• Using iCal4j, a solid iCalendar library for Java.• Component to generate the file.• Will generate a text/calendar response
  9. 9. iCalendar file generationERGWCalendar aCalendar = new ERGWCalendar();ERGWEvent event = new ERGWEvent(aCalendar);java.util.Calendar startTime = GregorianCalendar.getInstance();event.setStartTime(new NSTimestamp(startTime.getTimeInMillis()));java.util.Calendar endTime = GregorianCalendar.getInstance();endTime.add(java.util.Calendar.HOUR, 2);event.setEndTime(new NSTimestamp(endTime.getTimeInMillis()));event.setClassification(ERGWClassification.PUBLIC);event.setFreeBusyStatus(ERGWFreeBusyStatus.BUSY_TENTATIVE);event.setLocation("Montreal");event.setCategories(new NSArray<String>(new String[] { "Category 1", "Category 2" }));event.setPriority(ERGWPriority.HIGH);event.setSummary("WOWODC 2013");event.setTransparency(ERGWTransparency.TRANSPARENT);Calendar calendarData = ERGWCalendar.transformToICalObject(aCalendar);ERGWPublishCalendarPage nextPage = (ERGWPublishCalendarPage)pageWithName(ERGWPublishCalendarPage.class);nextPage.setCalendar(calendarData);return nextPage;
  10. 10. CalDAV/CardDAV• Both based on WebDAV• Will store iCalendar objects (CalDAV) or vCard objects(CardDAV)• Many many server implementations• But some of them are really basic (Google Calendar...)• iCal Server is the best implementation• Many clients too
  11. 11. CalDAV• Open standard, defined in RFC 4791• Servers must implements this RFC• Many extensions• Scheduling• Delegations• Sharing• etc.
  12. 12. CalDAV• Calendars are DAV collections.• DAV collections have properties (ACL, owner, etc.).• Can create as many collections as you want.• Other DAV collections exists too.
  13. 13. Features/extensions• CalDAV servers must send the supported features set in theresponse.• Can do a OPTIONS request to see them.• Check the DAV header in the response.
  14. 14. OPTIONS request$ curl --digest --user probert -X OPTIONS -v http://localhost:8008< DAV: 1, access-control, calendar-access, calendar-schedule, calendar-auto-schedule, calendar-availability, inbox-availability, calendar-proxy, calendarserver-private-events, calendarserver-private-comments,calendarserver-sharing, calendarserver-sharing-no-scheduling, calendar-query-extended, calendar-default-alarms, addressbook, extended-mkcol,calendarserver-principal-property-search, calendarserver-principal-search
  15. 15. CalDAV and HTTP• Almost REST-like• Use HTTP verbs• GET: fetch a object• PUT: create OR update a object• DELETE: delete a object• MKCALENDAR: create a calendar collection• Use headers, HTTP authentication (Basic, Digest, Kerberos...)
  16. 16. iCalendar objects• You store iCalendar objects in calendar collections.• But you can only store ONE component (VTODO,VEVENT,etc.) per object.
  17. 17. PUT• CalDAV dont use POST to create objects.• Must use PUT• If URL and UID already exists, will update the object.• If URL and UID dont exists, will create the object.• If URL dont exist but UID exist, will conflict.• Creating a object will return a 201 status code.• If you copy an object, dont forget to change the UID.
  18. 18. Example of creating eventPUT /calendars/__uids__/AD04C60B-3704-447B-8997-24F5ACF589C7/calendar/C440-473C-8FAD-D3E606159F40.ics HTTP/1.1If-None-Match: 1f9e6e30-dfdb-4e5c-baf6-6dd107126a68Content-Type: text/calendarBEGIN:VCALENDARVERSION:2.0PRODID:-//Apple Inc.//Mac OS X 10.8.4//ENCALSCALE:GREGORIANBEGIN:VEVENTATTENDEE;CN="probert@macti.ca";CUTYPE=INDIVIDUAL:mailto:probert@macti.caATTENDEE;CN="Pascal Robert";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED:urn:uuid:AD04C60B-3704-447B-8997-24F5ACF589C7DTEND;VALUE=DATE:20130616TRANSP:TRANSPARENTORGANIZER;CN="Pascal Robert":urn:uuid:AD04C60B-3704-447B-8997-24F5ACF589C7UID:B54100D2-C440-473C-8FAD-D3E606159F40DTSTAMP:20130615T123551ZLOCATION:Hilton Montréal BonaventureSEQUENCE:9SUMMARY:Test for presentationDTSTART;VALUE=DATE:20130615CREATED:20130615T123241ZEND:VEVENTEND:VCALENDAR
  19. 19. CalDAV support in ERGroupware• Based on iCal4j-connector, which I contributed to.• Support for most CalDAV operations.• Get calendars (collections)• Create calendars• Fetch/delete/update calendar objects• Delete collections• Fetch events by time-range
  20. 20. Connectingimport net.fortuna.ical4j.connector.ObjectStoreException;import net.fortuna.ical4j.connector.dav.PathResolver;import er.groupware.caldav.CalDAVStore;import java.net.URL;CalDAVStore store = null;try {store = new CalDAVStore("probert", "somepassword", new URL("http://127.0.0.1"),PathResolver.ICAL_SERVER);}catch (MalformedURLException e) {e.printStackTrace();}catch (ObjectStoreException e) {e.printStackTrace();}
  21. 21. Fetching calendar collections and objectsNSArray<CalDAVCollection> collections = store.getCollections();for (CalDAVCollection collection: collections) {NSLog.out.appendln(collection.displayName());// Fetch all events (e.g, VEVENT objects)NSArray<ERGWCalendar> events = collection.events();// Fetch all tasks (e.g, VTOTO objects)NSArray<ERGWCalendar> tasks = collection.tasks();}
  22. 22. Manipuling calendar objects// Create a new event and send it to the serverERGWCalendar aCalendar = new ERGWCalendar();ERGWEvent event = new ERGWEvent(aCalendar);java.util.Calendar startTime = GregorianCalendar.getInstance();event.setStartTime(new NSTimestamp(startTime.getTimeInMillis()));java.util.Calendar endTime = GregorianCalendar.getInstance();endTime.add(java.util.Calendar.HOUR, 2);event.setEndTime(new NSTimestamp(endTime.getTimeInMillis()));event.setSummary("WOWODC 2013");collection.addCalendarObject(aCalendar);// Update the event and send it to the serveraCalendar.events().objectAtIndex(0).setSummary("WOWODC 2014");collection.updateCalendarObject(aCalendar);// Delete the eventcollection.removeCalendarObject(aCalendar.events().objectAtIndex(0));
  23. 23. Queries• REPORT request is the same idea as a SQL SELECT query.• Lets you find calendar objects with a qualifier.• "Find all todos that are completed"• "Find events from June 22 to June 24"• "Find all rooms"• Wont work for custom properties
  24. 24. Find events by time rangeREPORT /bernard/work/ HTTP/1.1Depth: 1Content-Type: application/xml; charset="utf-8"<?xml version="1.0" encoding="utf-8" ?><C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav"><D:prop><C:calendar-data><C:limit-recurrence-set start="20060103T000000Z" end="20060105T000000Z"/></C:calendar-data></D:prop><C:filter><C:comp-filter name="VCALENDAR"><C:comp-filter name="VEVENT"><C:time-range start="20060103T000000Z" end="20060105T000000Z"/></C:comp-filter></C:comp-filter></C:filter></C:calendar-query>
  25. 25. Find participants that didnt not accept invitationsREPORT /bernard/work/ HTTP/1.1Depth: 1Content-Type: application/xml; charset="utf-8"<?xml version="1.0" encoding="utf-8" ?><C:calendar-query xmlns:C="urn:ietf:params:xml:ns:caldav"><D:prop xmlns:D="DAV:"><D:getetag/><C:calendar-data/></D:prop><C:filter><C:comp-filter name="VCALENDAR"><C:comp-filter name="VEVENT"><C:prop-filter name="ATTENDEE"><C:param-filter name="PARTSTAT"><C:text-match collation="i;ascii-casemap">NEEDS-ACTION</C:text-match></C:param-filter></C:prop-filter></C:comp-filter></C:comp-filter></C:filter></C:calendar-query>
  26. 26. Queries support in ERGroupware• Query by time range• CalDavCollection.eventsForTimePeriod(java.util.Date startTime,java.util.Date endTime)• Find all individuals• store.getIndividuals(String name);• Find rooms or resources• store.getAllRooms()• store.getAllResources()
  27. 27. DEMO
  28. 28. MS Exchange• Exchange Web Service (EWS)• Based on SOAP• Same protocol that Outlook 2011 uses• Most EWS attributes are similar to iCalendar and DAVcollections attributes
  29. 29. Example of request---[HTTP request - https://webmail.sherweb2010.com/EWS/Exchange.asmx]---Content-type: text/xml;charset="utf-8"Soapaction: "http://schemas.microsoft.com/exchange/services/2006/messages/SyncFolderHierarchy"Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Header><MailboxCulture xmlns="..." xmlns:ns2="...">en-US</MailboxCulture><RequestServerVersion xmlns="..." xmlns:ns2="..." Version="Exchange2007_SP1"/></S:Header><S:Body><ns2:SyncFolderHierarchy xmlns="..." xmlns:ns2="..."><ns2:FolderShape><BaseShape>IdOnly</BaseShape><AdditionalProperties><FieldURI FieldURI="folder:DisplayName"/><FieldURI FieldURI="folder:FolderClass"/><ExtendedFieldURI PropertyType="Boolean" PropertyTag="0x10F4"/></AdditionalProperties></ns2:FolderShape></ns2:SyncFolderHierarchy></S:Body></S:Envelope>
  30. 30. Example of response<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><h:ServerVersionInfo ... Version="Exchange2010_SP2" /></s:Header><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><m:SyncFolderHierarchyResponse xmlns:m="..." xmlns:t="..."><m:ResponseMessages><m:SyncFolderHierarchyResponseMessage ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:SyncState>H4sIAAAAAAAEAO29B2AcSZYlJi9tynt...</m:SyncState><m:Changes><t:Create><t:Folder><t:FolderId Id="AAMkAGEw...=" ChangeKey="AQAAABYAAACT3PaCL/2ASLnqcq9Sv0/DAAAAp5Bv"/><t:FolderClass>IPF.Note</t:FolderClass><t:DisplayName>INBOX</t:DisplayName><t:ExtendedProperty><t:ExtendedFieldURI PropertyTag="0x10f4" PropertyType="Boolean"/><t:Value>false</t:Value></t:ExtendedProperty></t:Folder></t:Create></m:Changes>...
  31. 31. EWS support in ERGroupware• Generated with JAXB.• Very basic support outside the generated classes:• Open connection• Create folders• Create task• Create contact• Create event
  32. 32. Opening a connection and fetch foldersURL urlToWSDL = ERXApplication.application().resourceManager().pathURLForResourceNamed("Services.wsdl","ERGroupware", null);ExchangeStore store = new ExchangeStore(urlToWSDL, "https://myserver/EWS/Exchange.asmx", "aUser","aPassword", "AD.DOMAIN");store.setServerVersionForRequest(ExchangeVersionType.EXCHANGE_2010_SP_1);store.setTimeZone(TimeZone.getDefault());NSArray<ExchangeBaseFolder> folders = store.folders();for (ExchangeBaseFolder folder: folders) {NSLog.out.appendln(folder.displayName());}
  33. 33. Adding an eventfor (ExchangeBaseFolder folder: store.folders()) {if (folder.displayName().equals("Calendar")) {ERGWCalendar calendar = new ERGWCalendar();calendar.setCalendarName("Test");calendar.setTimeZone(TimeZone.getDefault());Calendar later = GregorianCalendar.getInstance();later.add(Calendar.HOUR_OF_DAY, 1);event.setEndTime(new NSTimestamp(later.getTime()));UidGenerator uidGen = new UidGenerator("allo");event.setUid(uidGen.generateUid().getValue());ERGWEvent event = new ERGWEvent(calendar);event.setIsFullDay(false);event.setStartTime(new NSTimestamp());event.setSummary("WOWODC 2013");event.setLastModifiedDate(new NSTimestamp());calendar.addEvent(event);exchangeStore.createCalendarEvent(calendar, (ExchangeCalendarFolder) folder);}}
  34. 34. Adding an eventfor (ExchangeBaseFolder folder: store.folders()) {if (folder.displayName().equals("Tasks")) {ERGWCalendar calendar = new ERGWCalendar();calendar.setCalendarName("Test");calendar.setTimeZone(TimeZone.getDefault());Calendar later = GregorianCalendar.getInstance();later.add(Calendar.HOUR_OF_DAY, 1);task.setDueDate(new NSTimestamp(later.getTime()));UidGenerator uidGen = new UidGenerator("allo");event.setUid(uidGen.generateUid().getValue());ERGWTask task = new ERGWTask(calendar);task.setSummary("Finish that presentation");task.setLastModifiedDate(new NSTimestamp());calendar.addEvent(event);exchangeStore.createTask(calendar, (ExchangeCalendarFolder) folder);}}
  35. 35. Adding a contactfor (ExchangeBaseFolder folder: store.folders()) {if (folder.displayName().equals("Contacts")) {ERGWContact contact = new ERGWContact();contact.setGivenName("Pascal");contact.setFamilyName("Robert");ERGWContactEmail personalEmail = new ERGWContactEmail();personalEmail.setEmail("probert@macti.ca");personalEmail.isPrefered(true);personalEmail.setTypes(new NSArray<ERGWContactEmailType>(new ERGWContactEmailType[]{ ERGWContactEmailType.HOME }));contact.setEmails(new NSArray<ERGWContactEmail>(new ERGWContactEmail[] { personalEmail }));exchangeStore.createContact(contact, (ExchangeCalendarFolder) folder);}}
  36. 36. Create folders// Create a folder of a specific type// ERGWFolderType values are: CALENDAR, CONTACTS, TASKS, SEARCH, PLAIN, etc.store.createFolder("New calendar folder", ERGWFolderType.CALENDAR);store.createFolder("New contacts folder", ERGWFolderType.CONTACTS);// Shortcut to create a calendar folderstore.createCalendarFolder(String displayName)// Shortcut to create a contacts folderstore.createContactsFolder(String displayName)
  37. 37. Zimbra• SOAP and REST-based API.• Have API for everything: management, data and Web client(Zimlets).• Very basic support in ERGroupware (need to migrate a lot ofcode)• Connect to store• Add folder
  38. 38. Example of requestPOST /service/soap/CreateAppointmentRequest HTTP/1.1Content-Type: text/xml; charset=utf-8<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Header> <context xmlns="urn:zimbra"><authToken>0_b6e206e6c3eee19a7e89f717d5972d9d6b9db224</authToken>...</context> </soap:Header> <soap:Body> <CreateAppointmentRequest xmlns="urn:zimbraMail"> <m l="10"> <inv> <comp status="CONF" allDay="0" name="Titre de la rencontre" loc="Montr[0xc3][0xa9]al" class="PUB" transp="O" fb="B"> <s d="20130619T050858" tz="America/Montreal"/> <e d="20130619T070858" tz="America/Montreal"/> <or d="Pascal Robert" a="root@zimbra.macti.lan"/> <at d="Pascal Robert" cutype="IND" a="probert@macti.ca"/> <at d="Salle 1" cutype="ROO" a="Room1@zimbra.macti.lan"/> <xprop name="X-RELATED-TO" value="281-280"/> </comp> </inv> <su>Titre de la rencontre</su> <mp ct="multipart/mixed"><mp ct="text/plain"> <content>Une plus long description</content> </mp> <mp ct="text/html"> <content>&lt;html>&lt;body> Une plus long description&lt;/body>&lt;/html></content> </mp> </m> </CreateAppointmentRequest> </soap:Body></soap:Envelope>
  39. 39. Example responseHTTP/1.1 200 OKContent-Type: text/xml;charset=UTF-8<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Header> <context xmlns="urn:zimbra"><session id="11">11</session><change token="602"/> <notify seq="2"> <created> <appt id="283" uid="4ec78d56-0061-451d-9825-cb17b43b010b" d="1371632938000" rev="602" s="0" l="10"> <inv id="282" seq="0" compNum="0" type="appt"> <tz id="America/Montreal" stdoff="-300" dayname="EDT" dayoff="-240" stdname="EST">...</tz> <comp uid="4ec78d56-0061-451d-9825-cb17b43b010b" d="1371632938000" status="CONF" ...> <at d="Pascal Robert" cutype="IND" a="probert@macti.ca" url="probert@macti.ca"/> <at d="Salle 1" cutype="ROO" a="Room1@zimbra.macti.lan" url="Room1@zimbra.macti.lan"/> <xprop name="X-RELATED-TO" value="281-280"/> <desc>Une plus long description</desc> <descHtml>&lt;html>&lt;body> Une plus long description&lt;/body>&lt;/html></descHtml> <or d="Pascal Robert" a="admin@linux.conatus.lan" url="root@zimbra.macti.lan"/> <s u="1371632938000" d="20130619T050858" tz="America/Montreal"/> <e d="20130619T070858" u="1371640138000" tz="America/Montreal"/> </comp> </inv> </appt> </created> <modified><folder id="10" i4next="284" s="0" i4ms="602" n="3" uuid="6630b004-40cd-49b4-af4b-eca7bac45be6"/></modified> </notify> </context> </soap:Header> <soap:Body> <CreateAppointmentResponse rev="602" ms="602" invId="283-282" apptId="283" calItemId="283" xmlns="urn:zimbraMail"/> </soap:Body></soap:Envelope>
  40. 40. TODO• Move away from ical4j-connector• Complete CalDAV and CardDAV support• Complete calendar, contacts and email support for Zimbra• Management API for Kerio, CGP and Zimbra
  41. 41. Resources• https://github.com/pascalrobert/ERGroupware/• http://www.macti.ca/wiki/• http://www.calconnect.org• http://wiki.modularity.net.au/ical4j/• http://msdn.microsoft.com/en-us/library/exchange/bb204119(v=exchg.140).aspx
  42. 42. Q&A

×