protected void fixAlarm(VObject vObject, boolean fromServer) { if (vObject.vObjects != null) { if (Settings.getBooleanProperty("davmail.caldavDisableReminders", false)) { ArrayList<VObject> vAlarms = null; for (VObject vAlarm : vObject.vObjects) { if ("VALARM".equals(vAlarm.type)) { if (vAlarms == null) { vAlarms = new ArrayList<VObject>(); } vAlarms.add(vAlarm); } } // remove all vAlarms if (vAlarms != null) { for (VObject vAlarm : vAlarms) { vObject.vObjects.remove(vAlarm); } } } else { for (VObject vAlarm : vObject.vObjects) { if ("VALARM".equals(vAlarm.type)) { String action = vAlarm.getPropertyValue("ACTION"); if (fromServer && "DISPLAY".equals(action) // convert DISPLAY to AUDIO only if user defined an alarm sound && Settings.getProperty("davmail.caldavAlarmSound") != null) { // Convert alarm to audio for iCal vAlarm.setPropertyValue("ACTION", "AUDIO"); if (vAlarm.getPropertyValue("ATTACH") == null) { // Add defined sound into the audio alarm VProperty vProperty = new VProperty("ATTACH", Settings.getProperty("davmail.caldavAlarmSound")); vProperty.addParam("VALUE", "URI"); vAlarm.addProperty(vProperty); } } else if (!fromServer && "AUDIO".equals(action)) { // Use the alarm action that exchange (and blackberry) understand // (exchange and blackberry don't understand audio actions) vAlarm.setPropertyValue("ACTION", "DISPLAY"); } } } } } }
/** * Get property value from first VEVENT in VCALENDAR. * * @param name property name * @return property value */ public String getFirstVeventPropertyValue(String name) { if (firstVevent == null) { return null; } else { return firstVevent.getPropertyValue(name); } }
private void fixTimezone() { if (vTimezone != null && vTimezone.vObjects != null && vTimezone.vObjects.size() > 2) { VObject standard = null; VObject daylight = null; for (VObject vObject : vTimezone.vObjects) { if ("STANDARD".equals(vObject.type)) { if (standard == null || (vObject .getPropertyValue("DTSTART") .compareTo(standard.getPropertyValue("DTSTART")) > 0)) { standard = vObject; } } if ("DAYLIGHT".equals(vObject.type)) { if (daylight == null || (vObject .getPropertyValue("DTSTART") .compareTo(daylight.getPropertyValue("DTSTART")) > 0)) { daylight = vObject; } } } vTimezone.vObjects.clear(); vTimezone.vObjects.add(standard); vTimezone.vObjects.add(daylight); } // fix 3569922: quick workaround for broken Israeli Timezone issue if (vTimezone != null && vTimezone.vObjects != null) { for (VObject vObject : vTimezone.vObjects) { VProperty rrule = vObject.getProperty("RRULE"); if (rrule != null && rrule.getValues().size() == 3 && "BYDAY=-2SU".equals(rrule.getValues().get(1))) { rrule.getValues().set(1, "BYDAY=4SU"); } } } }
protected void setServerAllday(VProperty property) { if (vTimezone != null) { // set TZID param if (!property.hasParam("TZID")) { property.addParam("TZID", vTimezone.getPropertyValue("TZID")); } // remove VALUE property.removeParam("VALUE"); String value = property.getValue(); if (value.length() != 8) { LOGGER.warn("Invalid date value in allday event: " + value); } property.setValue(property.getValue() + "T000000"); } }
private void fixTzid(VProperty property) { if (property != null && !property.hasParam("TZID")) { property.addParam("TZID", vTimezone.getPropertyValue("TZID")); } }
protected void fixVCalendar(boolean fromServer) { // set iCal 4 global X-CALENDARSERVER-ACCESS from CLASS if (fromServer) { setPropertyValue("X-CALENDARSERVER-ACCESS", getCalendarServerAccess()); } // iCal 4 global X-CALENDARSERVER-ACCESS String calendarServerAccess = getPropertyValue("X-CALENDARSERVER-ACCESS"); String now = ExchangeSession.getZuluDateFormat().format(new Date()); // fix method from iPhone if (!fromServer && getPropertyValue("METHOD") == null) { setPropertyValue("METHOD", "PUBLISH"); } // rename TZID for maximum iCal/iPhone compatibility String tzid = null; if (fromServer) { // get current tzid VObject vObject = vTimezone; if (vObject != null) { String currentTzid = vObject.getPropertyValue("TZID"); // fix TZID with \n (Exchange 2010 bug) if (currentTzid != null && currentTzid.endsWith("\n")) { currentTzid = currentTzid.substring(0, currentTzid.length() - 1); vObject.setPropertyValue("TZID", currentTzid); } if (currentTzid != null && currentTzid.indexOf(' ') >= 0) { try { tzid = ResourceBundle.getBundle("timezones").getString(currentTzid); vObject.setPropertyValue("TZID", tzid); } catch (MissingResourceException e) { LOGGER.debug("Timezone " + currentTzid + " not found in rename table"); } } } } if (!fromServer) { fixTimezone(); } // iterate over vObjects for (VObject vObject : vObjects) { if ("VEVENT".equals(vObject.type)) { if (calendarServerAccess != null) { vObject.setPropertyValue("CLASS", getEventClass(calendarServerAccess)); // iCal 3, get X-CALENDARSERVER-ACCESS from local VEVENT } else if (vObject.getPropertyValue("X-CALENDARSERVER-ACCESS") != null) { vObject.setPropertyValue( "CLASS", getEventClass(vObject.getPropertyValue("X-CALENDARSERVER-ACCESS"))); } if (fromServer) { // remove organizer line for event without attendees for iPhone if (vObject.getProperty("ATTENDEE") == null) { vObject.setPropertyValue("ORGANIZER", null); } // detect allday and update date properties if (isCdoAllDay(vObject)) { setClientAllday(vObject.getProperty("DTSTART")); setClientAllday(vObject.getProperty("DTEND")); setClientAllday(vObject.getProperty("RECURRENCE-ID")); } String cdoBusyStatus = vObject.getPropertyValue("X-MICROSOFT-CDO-BUSYSTATUS"); if (cdoBusyStatus != null) { vObject.setPropertyValue( "TRANSP", !"FREE".equals(cdoBusyStatus) ? "OPAQUE" : "TRANSPARENT"); } // Apple iCal doesn't understand this key, and it's entourage // specific (i.e. not needed by any caldav client): strip it out vObject.removeProperty("X-ENTOURAGE_UUID"); splitExDate(vObject); // remove empty properties if ("".equals(vObject.getPropertyValue("LOCATION"))) { vObject.removeProperty("LOCATION"); } if ("".equals(vObject.getPropertyValue("DESCRIPTION"))) { vObject.removeProperty("DESCRIPTION"); } if ("".equals(vObject.getPropertyValue("CLASS"))) { vObject.removeProperty("CLASS"); } // rename TZID if (tzid != null) { VProperty dtStart = vObject.getProperty("DTSTART"); if (dtStart != null && dtStart.getParam("TZID") != null) { dtStart.setParam("TZID", tzid); } VProperty dtEnd = vObject.getProperty("DTEND"); if (dtEnd != null && dtStart.getParam("TZID") != null) { dtEnd.setParam("TZID", tzid); } VProperty reccurrenceId = vObject.getProperty("RECURRENCE-ID"); if (reccurrenceId != null && reccurrenceId.getParam("TZID") != null) { reccurrenceId.setParam("TZID", tzid); } } // remove unsupported attachment reference if (vObject.getProperty("ATTACH") != null) { List<String> toRemoveValues = null; List<String> values = vObject.getProperty("ATTACH").getValues(); for (String value : values) { if (value.indexOf("CID:") >= 0) { if (toRemoveValues == null) { toRemoveValues = new ArrayList<String>(); } toRemoveValues.add(value); } } if (toRemoveValues != null) { values.removeAll(toRemoveValues); if (values.size() == 0) { vObject.removeProperty("ATTACH"); } } } } else { // add organizer line to all events created in Exchange for active sync String organizer = getEmailValue(vObject.getProperty("ORGANIZER")); if (organizer == null) { vObject.setPropertyValue("ORGANIZER", "MAILTO:" + email); } else if (!email.equalsIgnoreCase(organizer) && vObject.getProperty("X-MICROSOFT-CDO-REPLYTIME") == null) { vObject.setPropertyValue("X-MICROSOFT-CDO-REPLYTIME", now); } // set OWA allday flag vObject.setPropertyValue( "X-MICROSOFT-CDO-ALLDAYEVENT", isAllDay(vObject) ? "TRUE" : "FALSE"); vObject.setPropertyValue( "X-MICROSOFT-CDO-BUSYSTATUS", !"TRANSPARENT".equals(vObject.getPropertyValue("TRANSP")) ? "BUSY" : "FREE"); if (isAllDay(vObject)) { // convert date values to outlook compatible values setServerAllday(vObject.getProperty("DTSTART")); setServerAllday(vObject.getProperty("DTEND")); } else { fixTzid(vObject.getProperty("DTSTART")); fixTzid(vObject.getProperty("DTEND")); } } fixAttendees(vObject, fromServer); fixAlarm(vObject, fromServer); } } }
protected boolean isCdoAllDay(VObject vObject) { return "TRUE".equals(vObject.getPropertyValue("X-MICROSOFT-CDO-ALLDAYEVENT")); }