use of com.zimbra.common.calendar.ZCalendar.ZProperty in project zm-mailbox by Zimbra.
the class Attach method toZProperty.
public ZProperty toZProperty() {
ZProperty prop;
if (mUri != null) {
prop = new ZProperty(ICalTok.ATTACH, mUri);
} else {
prop = new ZProperty(ICalTok.ATTACH, mBinaryB64Data);
prop.addParameter(new ZParameter(ICalTok.VALUE, "BINARY"));
prop.addParameter(new ZParameter(ICalTok.ENCODING, "BASE64"));
}
if (mContentType != null) {
prop.addParameter(new ZParameter(ICalTok.FMTTYPE, mContentType));
}
if (fileName != null) {
/* We recognise X-FILENAME incoming as well from Microsoft documentation but CalDAV clients are more
* likely to use X-APPLE-FILENAME
*/
prop.addParameter(new ZParameter(ICalTok.X_APPLE_FILENAME, fileName));
}
return prop;
}
use of com.zimbra.common.calendar.ZCalendar.ZProperty in project zm-mailbox by Zimbra.
the class ParsedDateTime method toProperty.
public ZProperty toProperty(ICalTok tok, boolean useOutlookCompatMode) {
ZProperty toRet = new ZProperty(tok, getDateTimePartString(useOutlookCompatMode));
String tzName = getTZName();
if (!useOutlookCompatMode && !hasTime()) {
toRet.addParameter(new ZParameter(ICalTok.VALUE, ICalTok.DATE.toString()));
} else {
if (tzName != null) {
toRet.addParameter(new ZParameter(ICalTok.TZID, tzName));
}
}
return toRet;
}
use of com.zimbra.common.calendar.ZCalendar.ZProperty in project zm-mailbox by Zimbra.
the class CalDavDataImport method putAppointment.
private String putAppointment(CalendarItem calItem, DataSourceItem dsItem) throws ServiceException, IOException, DavException {
StringBuilder buf = new StringBuilder();
ArrayList<String> recipients = new ArrayList<String>();
buf.append("BEGIN:VCALENDAR\r\n");
buf.append("VERSION:").append(ZCalendar.sIcalVersion).append("\r\n");
buf.append("PRODID:").append(ZCalendar.sZimbraProdID).append("\r\n");
Iterator<ICalTimeZone> iter = calItem.getTimeZoneMap().tzIterator();
while (iter.hasNext()) {
ICalTimeZone tz = iter.next();
CharArrayWriter wr = new CharArrayWriter();
tz.newToVTimeZone().toICalendar(wr, true);
wr.flush();
buf.append(wr.toCharArray());
wr.close();
}
boolean appleICalExdateHack = LC.calendar_apple_ical_compatible_canceled_instances.booleanValue();
ZComponent[] vcomps = Invite.toVComponents(calItem.getInvites(), true, false, appleICalExdateHack);
if (vcomps != null) {
CharArrayWriter wr = new CharArrayWriter();
for (ZComponent vcomp : vcomps) {
ZProperty organizer = vcomp.getProperty(ZCalendar.ICalTok.ORGANIZER);
if (organizer != null)
organizer.setValue(getUsername());
vcomp.toICalendar(wr, true);
}
wr.flush();
buf.append(wr.toCharArray());
wr.close();
}
buf.append("END:VCALENDAR\r\n");
String etag = dsItem.md.get(METADATA_KEY_ETAG, null);
if (recipients.isEmpty())
recipients = null;
Appointment appt = new Appointment(dsItem.remoteId, etag, buf.toString(), recipients);
return getClient().sendCalendarData(appt);
}
use of com.zimbra.common.calendar.ZCalendar.ZProperty in project zm-mailbox by Zimbra.
the class CalDavUtils method removeAttendeeForOrganizer.
// Fixup for ATTENDEE properties set by Apple iCal
// Don't let the organizer to be also listed as an attendee.
public static void removeAttendeeForOrganizer(ZComponent comp) {
if (!DebugConfig.caldavAllowAttendeeForOrganizer && (ICalTok.VEVENT.equals(comp.getTok()) || ICalTok.VTODO.equals(comp.getTok()))) {
String organizer = comp.getPropVal(ICalTok.ORGANIZER, null);
if (organizer != null) {
organizer = organizer.trim();
AccountAddressMatcher acctMatcher = null;
String address = stripMailto(organizer);
if (address != null) {
try {
Account acct = Provisioning.getInstance().get(AccountBy.name, address);
if (acct != null) {
acctMatcher = new AccountAddressMatcher(acct);
}
} catch (ServiceException e) {
// ignore
ZimbraLog.dav.warn("could not get the account matcher for " + address, e);
}
}
for (Iterator<ZProperty> propIter = comp.getPropertyIterator(); propIter.hasNext(); ) {
ZProperty prop = propIter.next();
if (ICalTok.ATTENDEE.equals(prop.getToken())) {
String att = prop.getValue();
if (att != null) {
att = att.trim();
try {
// iCal has a habit of listing the organizer as an ATTENDEE. Undo it.
if (att.equalsIgnoreCase(organizer) || (acctMatcher != null && acctMatcher.matches(stripMailto(att)))) {
propIter.remove();
}
} catch (ServiceException e) {
// ignore
ZimbraLog.dav.warn("exception while matching the attendee address " + att, e);
}
} else {
// We haven't seen this case occur, but just in case.
propIter.remove();
}
}
}
}
}
}
use of com.zimbra.common.calendar.ZCalendar.ZProperty in project zm-mailbox by Zimbra.
the class ScheduleOutbox method handlePost.
@Override
public void handlePost(DavContext ctxt) throws DavException, IOException, ServiceException {
DelegationInfo delegationInfo = new DelegationInfo(ctxt.getRequest().getHeader(DavProtocol.HEADER_ORIGINATOR));
Enumeration<String> recipients = ctxt.getRequest().getHeaders(DavProtocol.HEADER_RECIPIENT);
InputStream in = ctxt.getUpload().getInputStream();
ZCalendar.ZVCalendar vcalendar = ZCalendar.ZCalendarBuilder.build(in, MimeConstants.P_CHARSET_UTF8);
Closeables.closeQuietly(in);
Iterator<ZComponent> iter = vcalendar.getComponentIterator();
ZComponent req = null;
while (iter.hasNext()) {
req = iter.next();
if (req.getTok() != ICalTok.VTIMEZONE)
break;
req = null;
}
if (req == null) {
throw new DavException("empty request", HttpServletResponse.SC_BAD_REQUEST);
}
ZimbraLog.dav.debug("originator: %s", delegationInfo.getOriginator());
boolean isVEventOrVTodo = ICalTok.VEVENT.equals(req.getTok()) || ICalTok.VTODO.equals(req.getTok());
boolean isOrganizerMethod = false, isCancel = false;
if (isVEventOrVTodo) {
String method = vcalendar.getPropVal(ICalTok.METHOD, null);
if (method != null) {
isOrganizerMethod = Invite.isOrganizerMethod(method);
isCancel = ICalTok.CANCEL.toString().equalsIgnoreCase(method);
;
}
// Apple iCal fixup
CalDavUtils.removeAttendeeForOrganizer(req);
}
// Get organizer and list of attendees. (mailto:email values)
ArrayList<String> attendees = new ArrayList<String>();
String organizer = null;
for (Iterator<ZProperty> propsIter = req.getPropertyIterator(); propsIter.hasNext(); ) {
ZProperty prop = propsIter.next();
ICalTok token = prop.getToken();
if (ICalTok.ATTENDEE.equals(token)) {
String val = prop.getValue();
if (val != null) {
attendees.add(val.trim());
}
} else if (ICalTok.ORGANIZER.equals(token)) {
String val = prop.getValue();
if (val != null) {
organizer = val.trim();
String addr = CalDavUtils.stripMailto(organizer);
// Rewrite the alias to primary address
Account acct = Provisioning.getInstance().get(AccountBy.name, addr);
if (acct != null) {
String newAddr = acct.getName();
if (!addr.equals(newAddr)) {
organizer = "mailto:" + newAddr;
prop.setValue(organizer);
}
}
}
}
}
// Apple iCal is very inconsistent about the user's identity when the account has aliases.
if (isVEventOrVTodo && delegationInfo.getOriginator() != null && ctxt.getAuthAccount() != null) {
AccountAddressMatcher acctMatcher = new AccountAddressMatcher(ctxt.getAuthAccount());
if (acctMatcher.matches(delegationInfo.getOriginatorEmail())) {
if (isOrganizerMethod) {
if (organizer != null) {
String organizerEmail = CalDavUtils.stripMailto(organizer);
if (!organizerEmail.equalsIgnoreCase(delegationInfo.getOriginatorEmail()) && acctMatcher.matches(organizerEmail)) {
delegationInfo.setOriginator(organizer);
ZimbraLog.dav.debug("changing originator to %s to match address/alias used in ORGANIZER", delegationInfo.getOriginator());
}
}
} else {
for (String at : attendees) {
String atEmail = CalDavUtils.stripMailto(at);
if (delegationInfo.getOriginatorEmail().equalsIgnoreCase(atEmail)) {
break;
} else if (acctMatcher.matches(atEmail)) {
delegationInfo.setOriginator(at);
ZimbraLog.dav.debug("changing originator to %s to match address/alias used in ATTENDEE", delegationInfo.getOriginator());
break;
}
}
}
}
}
// Get the recipients.
ArrayList<String> rcptArray = new ArrayList<String>();
while (recipients.hasMoreElements()) {
String rcptHdr = recipients.nextElement();
String[] rcpts = null;
if (rcptHdr.indexOf(',') > 0) {
rcpts = rcptHdr.split(",");
} else {
rcpts = new String[] { rcptHdr };
}
for (String rcpt : rcpts) {
if (rcpt != null) {
rcpt = rcpt.trim();
if (rcpt.length() != 0) {
// Workaround for Apple iCal: Ignore attendees with address "invalid:nomail".
if (rcpt.equalsIgnoreCase("invalid:nomail")) {
continue;
}
if (isVEventOrVTodo) {
// iCal can sometimes do that when organizer account has aliases.
if (isOrganizerMethod && rcpt.equalsIgnoreCase(organizer)) {
continue;
}
// as ATTENDEE in the CANCEL component being sent. (iCal does that part correctly, at least.)
if (isCancel) {
boolean isAttendee = false;
// Rcpt must be an attendee of the cancel component.
for (String at : attendees) {
if (rcpt.equalsIgnoreCase(at)) {
isAttendee = true;
break;
}
}
if (!isAttendee) {
ZimbraLog.dav.info("Ignoring non-attendee recipient '%s' of CANCEL request; likely a client bug", rcpt);
continue;
}
}
}
// All checks passed.
rcptArray.add(rcpt);
}
}
}
}
Element scheduleResponse = ctxt.getDavResponse().getTop(DavElements.E_SCHEDULE_RESPONSE);
for (String rcpt : rcptArray) {
ZimbraLog.dav.debug("recipient email: " + rcpt);
Element resp = scheduleResponse.addElement(DavElements.E_CALDAV_RESPONSE);
switch(req.getTok()) {
case VFREEBUSY:
handleFreebusyRequest(ctxt, req, delegationInfo.getOriginator(), rcpt, resp);
break;
case VEVENT:
// records.
if (isOrganizerMethod) {
adjustOrganizer(ctxt, vcalendar, req, delegationInfo);
}
validateRequest(isOrganizerMethod, delegationInfo, organizer, ctxt, req);
handleEventRequest(ctxt, vcalendar, req, delegationInfo, rcpt, resp);
break;
default:
throw new DavException("unrecognized request: " + req.getTok(), HttpServletResponse.SC_BAD_REQUEST);
}
}
}
Aggregations