+ All Categories
Home > Technology > ERGroupware

ERGroupware

Date post: 15-May-2015
Category:
Upload: wo-community
View: 831 times
Download: 1 times
Share this document with a friend
Description:
Learn about how you can connect to CalDAV, MS Exchange and Zimbra servers with his upcoming Project Wonder framework.
Popular Tags:
42
ERGroupware Pascal Robert Druide informatique
Transcript
Page 1: ERGroupware

ERGroupwarePascal RobertDruide informatique

Page 2: ERGroupware

• 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 framework

What is ERGroupware?

Page 3: ERGroupware

iCalendar generation

Page 4: ERGroupware

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

Page 5: ERGroupware

iCalendar example

BEGIN: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

Page 6: ERGroupware

UID

• Each component must have a UID

• UID:DB0E22EA-0828-40A3-BCFD-5A8CC9866CE4

• And it must be unique!

Page 7: ERGroupware

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!

Page 8: ERGroupware

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

Page 9: ERGroupware

iCalendar file generation

ERGWCalendar 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;

Page 10: ERGroupware

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

Page 11: ERGroupware

CalDAV

• Open standard, defined in RFC 4791

• Servers must implements this RFC

• Many extensions

• Scheduling

• Delegations

• Sharing

• etc.

Page 12: ERGroupware

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.

Page 13: ERGroupware

Features/extensions

• CalDAV servers must send the supported features set in the response.

• Can do a OPTIONS request to see them.

• Check the DAV header in the response.

Page 14: ERGroupware

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

Page 15: ERGroupware

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

Page 16: ERGroupware

iCalendar objects

• You store iCalendar objects in calendar collections.

• But you can only store ONE component (VTODO, VEVENT, etc.) per object.

Page 17: ERGroupware

PUT

• CalDAV don't use POST to create objects.

• Must use PUT

• If URL and UID already exists, will update the object.

• If URL and UID don't exists, will create the object.

• If URL don't exist but UID exist, will conflict.

• Creating a object will return a 201 status code.

• If you copy an object, don't forget to change the UID.

Page 18: ERGroupware

Example of creating event

PUT /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/calendar

BEGIN:VCALENDARVERSION:2.0PRODID:-//Apple Inc.//Mac OS X 10.8.4//ENCALSCALE:GREGORIANBEGIN:VEVENTATTENDEE;CN="[email protected]";CUTYPE=INDIVIDUAL:mailto:[email protected];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

Page 19: ERGroupware

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

Page 20: ERGroupware

Connecting

import 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();}

Page 21: ERGroupware

Fetching calendar collections and objects

NSArray<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(); }

Page 22: ERGroupware

Manipuling calendar objects

// Create a new event and send it to the server ERGWCalendar 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 server aCalendar.events().objectAtIndex(0).setSummary("WOWODC 2014"); collection.updateCalendarObject(aCalendar);

// Delete the event collection.removeCalendarObject(aCalendar.events().objectAtIndex(0));

Page 23: ERGroupware

Queries

• REPORT request is the same idea as a SQL SELECT query.

• Let's you find calendar objects with a qualifier.

• "Find all todos that are completed"

• "Find events from June 22 to June 24"

• "Find all rooms"

• Won't work for custom properties

Page 24: ERGroupware

Find events by time range

REPORT /bernard/work/ HTTP/1.1 Depth: 1 Content-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>

Page 25: ERGroupware

Find participants that didn't not accept invitations

REPORT /bernard/work/ HTTP/1.1 Depth: 1 Content-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>

Page 26: ERGroupware

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

Page 27: ERGroupware

DEMO

Page 28: ERGroupware

MS Exchange

• Exchange Web Service (EWS)

• Based on SOAP

• Same protocol that Outlook 2011 uses

• Most EWS attributes are similar to iCalendar and DAV collections attributes

Page 29: ERGroupware

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>

Page 30: ERGroupware

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

Page 31: ERGroupware

EWS support in ERGroupware

• Generated with JAXB.

• Very basic support outside the generated classes:

• Open connection

• Create folders

• Create task

• Create contact

• Create event

Page 32: ERGroupware

Opening a connection and fetch folders

URL 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()); }

Page 33: ERGroupware

Adding an event

for (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); }}

Page 34: ERGroupware

Adding an event

for (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); }}

Page 35: ERGroupware

Adding a contact

for (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("[email protected]"); 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); }}

Page 36: ERGroupware

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)

Page 37: ERGroupware

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 of code)

• Connect to store

• Add folder

Page 38: ERGroupware

Example of request

POST /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="[email protected]"/> <at d="Pascal Robert" cutype="IND" a="[email protected]"/> <at d="Salle 1" cutype="ROO" a="[email protected]"/> <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>

Page 39: ERGroupware

Example response

HTTP/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="[email protected]" url="[email protected]"/> <at d="Salle 1" cutype="ROO" a="[email protected]" url="[email protected]"/> <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="[email protected]" url="[email protected]"/> <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>

Page 40: ERGroupware

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

Page 42: ERGroupware

Q&A