use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class AutoScheduler method getAutoScheduler.
public static AutoScheduler getAutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, int flags, String[] tags, SetCalendarItemData scidDefault, SetCalendarItemData[] scidExceptions, List<ReplyInfo> replies, DavContext context) {
if (!DavResource.isCalendarAutoSchedulingEnabled()) {
return null;
}
if (calendarMailbox == null) {
// We don't know who to act as
return null;
}
ZOrganizer organizer = null;
Account organizerAcct = null;
try {
if (scidDefault == null || scidDefault.invite == null) {
if (isEmpty(origInvites)) {
// No new or old invites!
return null;
}
organizer = origInvites[0].getOrganizer();
organizerAcct = origInvites[0].getOrganizerAccount();
} else {
organizer = scidDefault.invite.getOrganizer();
organizerAcct = scidDefault.invite.getOrganizerAccount();
}
if (organizer == null) {
// no organizer means no scheduling
return null;
}
// TODO: Does the auth user have scheduling capability for the calendar
if (calendarMailbox.getAccount().sameAccount(organizerAcct)) {
return new OrganizerAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, context);
} else {
return new AttendeeAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, context);
}
} catch (ServiceException e) {
ZimbraLog.dav.debug("Hit this whilst getting AutoScheduler", e);
}
return null;
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class ScheduleOutbox method adjustOrganizer.
/**
* For Vanilla CalDAV access where Apple style delegation has not been enabled, attempts by the delegate
* to use a shared calendar acting as themselves are translated to appear as if acting as a delegate,
* otherwise the experience can be very poor.
* @throws ServiceException
*/
private void adjustOrganizer(DavContext ctxt, ZCalendar.ZVCalendar cal, ZComponent req, DelegationInfo delegationInfo) throws ServiceException {
// BusyCal 2.5.3 seems to post with the wrong organizer even if ical delegation is switched on - even though
// it uses the right ORGANIZER in the calendar entry.
// if (ctxt.useIcalDelegation()) { return; }
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(ctxt.getAuthAccount());
String uid = req.getPropVal(ICalTok.UID, null);
CalendarItem matchingCalendarEntry = mbox.getCalendarItemByUid(ctxt.getOperationContext(), uid);
if (matchingCalendarEntry == null) {
List<com.zimbra.cs.mailbox.Mountpoint> sharedCalendars = mbox.getCalendarMountpoints(ctxt.getOperationContext(), SortBy.NONE);
if (sharedCalendars == null) {
// Can't work out anything useful
return;
}
Set<Account> accts = Sets.newHashSet();
for (com.zimbra.cs.mailbox.Mountpoint sharedCalendar : sharedCalendars) {
accts.add(Provisioning.getInstance().get(AccountBy.id, sharedCalendar.getOwnerId()));
}
for (Account acct : accts) {
Mailbox sbox = MailboxManager.getInstance().getMailboxByAccount(acct);
matchingCalendarEntry = sbox.getCalendarItemByUid(ctxt.getOperationContext(), uid);
if (matchingCalendarEntry != null) {
break;
}
}
}
if (matchingCalendarEntry == null) {
return;
}
Invite[] invites = matchingCalendarEntry.getInvites();
if (invites == null) {
return;
}
for (Invite inv : invites) {
ZOrganizer org = inv.getOrganizer();
if (org != null) {
delegationInfo.setOwner(org.getAddress());
if (Strings.isNullOrEmpty(org.getCn())) {
Account ownerAcct = Provisioning.getInstance().get(AccountBy.name, org.getAddress());
if (!Strings.isNullOrEmpty(ownerAcct.getDisplayName())) {
delegationInfo.setOwnerCn(ownerAcct.getDisplayName());
}
} else {
delegationInfo.setOwnerCn(org.getCn());
}
break;
}
}
if (delegationInfo.getOwner() == null) {
return;
}
AccountAddressMatcher acctMatcher = new AccountAddressMatcher(ctxt.getAuthAccount());
boolean originatorIsCalEntryOrganizer = acctMatcher.matches(delegationInfo.getOwnerEmail());
if (originatorIsCalEntryOrganizer) {
return;
}
for (ZComponent component : cal.getComponents()) {
ZProperty organizerProp = component.getProperty(ICalTok.ORGANIZER);
if (organizerProp != null) {
organizerProp.setValue(delegationInfo.getOwner());
ZParameter cn = organizerProp.getParameter(ICalTok.CN);
if (cn == null) {
organizerProp.addParameter(new ZParameter(ICalTok.CN, delegationInfo.getOwnerCn()));
} else {
cn.setValue(delegationInfo.getOwnerCn());
}
ZParameter sentBy = organizerProp.getParameter(ICalTok.SENT_BY);
if (sentBy == null) {
organizerProp.addParameter(new ZParameter(ICalTok.SENT_BY, delegationInfo.getOriginator()));
} else {
sentBy.setValue(delegationInfo.getOriginator());
}
}
}
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class CalendarItem method organizerChangeCheck.
/**
* Check to make sure the new invite doesn't change the organizer in a disallowed way.
* @param newInvite
* @return true if organizer change was detected, false if no change
* @throws ServiceException
*/
private boolean organizerChangeCheck(Invite newInvite, boolean denyChange) throws ServiceException {
Invite originalInvite = null;
if (!newInvite.hasRecurId()) {
// New invite is not for an exception.
originalInvite = getDefaultInviteOrNull();
} else {
// New invite is for an exception.
boolean found = false;
RecurId newRid = newInvite.getRecurId();
for (Invite inv : mInvites) {
if (inv.hasRecurId() && newRid.equals(inv.getRecurId())) {
originalInvite = inv;
found = true;
break;
}
}
if (!found) {
// If no invite with matching RECURRENCE-ID was found, use the default invite.
originalInvite = getDefaultInviteOrNull();
}
}
if (originalInvite == null) {
// If no "default" invite was found, use the first one.
if (mInvites.size() > 0)
originalInvite = mInvites.get(0);
if (originalInvite == null) {
// checks in this method.
return false;
}
}
boolean updatingSameComponent = true;
if (newInvite.hasRecurId()) {
if (originalInvite.hasRecurId()) {
updatingSameComponent = newInvite.getRecurId().equals(originalInvite.getRecurId());
} else {
updatingSameComponent = false;
}
}
boolean changed = false;
ZOrganizer originalOrganizer = originalInvite.getOrganizer();
if (!originalInvite.isOrganizer()) {
// This account WAS NOT the organizer. Prevent organizer change.
if (newInvite.hasOrganizer()) {
String newOrgAddr = newInvite.getOrganizer().getAddress();
if (originalOrganizer == null) {
if (denyChange) {
newInvite.isTodo();
if (updatingSameComponent) {
throw BadOrganizerException.ADD_ORGANIZER_NOT_ALLOWED(newOrgAddr, calDesc(newInvite));
} else {
throw BadOrganizerException.ORGANIZER_INTRODUCED_FOR_EXCEPTION(newOrgAddr, calDesc(newInvite));
}
} else {
changed = true;
}
} else {
// Both old and new organizers are set. They must be the same address.
String origOrgAddr = originalOrganizer.getAddress();
if (newOrgAddr == null || !CalendarUtils.belongToSameAccount(origOrgAddr, newOrgAddr)) {
if (denyChange) {
if (updatingSameComponent) {
throw BadOrganizerException.CHANGE_ORGANIZER_NOT_ALLOWED(origOrgAddr, newOrgAddr, calDesc(newInvite));
} else {
throw BadOrganizerException.DIFF_ORGANIZER_IN_COMPONENTS(origOrgAddr, newOrgAddr, calDesc(newInvite));
}
} else {
changed = true;
}
}
}
} else if (originalOrganizer != null) {
// No organizer for new newInvite but there is one in the original
String origOrgAddr = originalOrganizer.getAddress();
if (denyChange) {
if (updatingSameComponent) {
throw BadOrganizerException.DEL_ORGANIZER_NOT_ALLOWED(origOrgAddr, calDesc(newInvite));
} else {
throw BadOrganizerException.MISSING_ORGANIZER_IN_SINGLE_INSTANCE(origOrgAddr, calDesc(newInvite));
}
} else {
changed = true;
}
}
} else {
// Still don't allow changing the organizer field to an arbitrary address.
if (newInvite.hasOrganizer()) {
if (!newInvite.isOrganizer()) {
String newOrgAddr = newInvite.getOrganizer().getAddress();
String origOrgAddr = (originalOrganizer != null) ? originalOrganizer.getAddress() : null;
if (newOrgAddr.equalsIgnoreCase(origOrgAddr)) {
/* Speculative fix for Bug 83261. Had gotten to this point with the same address but
* thought that wasn't the organizer for the new invite even though that organizer
* passed the test for originalInvite. Ideally, should track down why the value was wrong
* but don't have a full repro scenario.
*/
newInvite.setIsOrganizer(true);
}
if (!newInvite.isOrganizer()) {
if (denyChange) {
if (originalOrganizer != null) {
if (updatingSameComponent) {
throw BadOrganizerException.CHANGE_ORGANIZER_NOT_ALLOWED(origOrgAddr, newOrgAddr, calDesc(newInvite));
} else {
throw BadOrganizerException.DIFF_ORGANIZER_IN_COMPONENTS(origOrgAddr, newOrgAddr, calDesc(newInvite));
}
} else {
if (updatingSameComponent) {
throw BadOrganizerException.ADD_ORGANIZER_NOT_ALLOWED(newOrgAddr, calDesc(newInvite));
} else {
throw BadOrganizerException.ORGANIZER_INTRODUCED_FOR_EXCEPTION(newOrgAddr, calDesc(newInvite));
}
}
} else {
changed = true;
}
}
}
}
}
if (changed) {
String origOrg = originalOrganizer != null ? originalOrganizer.getAddress() : null;
ZOrganizer newOrganizer = newInvite.getOrganizer();
String newOrg = newOrganizer != null ? newOrganizer.getAddress() : null;
boolean wasOrganizer = originalInvite.isOrganizer();
boolean isOrganizer = newInvite.isOrganizer();
ZimbraLog.calendar.info("Changed organizer: old=" + origOrg + ", new=" + newOrg + ", wasOrg=" + wasOrganizer + ", isOrg=" + isOrganizer + ", UID=\"" + newInvite.getUid() + "\", invId=" + newInvite.getMailItemId());
}
return changed;
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class CalendarItem method create.
static CalendarItem create(int id, Folder folder, int flags, Tag.NormalizedTags ntags, String uid, ParsedMessage pm, Invite firstInvite, long nextAlarm, CustomMetadata custom) throws ServiceException {
firstInvite.sanitize(false);
if (!folder.canAccess(ACL.RIGHT_INSERT)) {
throw ServiceException.PERM_DENIED("you do not have the required rights on the folder");
}
if (!firstInvite.isPublic() && !folder.canAccess(ACL.RIGHT_PRIVATE)) {
throw ServiceException.PERM_DENIED("you do not have permission to create private calendar item in this folder");
}
Mailbox mbox = folder.getMailbox();
if (pm != null && pm.hasAttachments()) {
firstInvite.setHasAttachment(true);
flags |= Flag.BITMASK_ATTACHED;
} else {
firstInvite.setHasAttachment(false);
flags &= ~Flag.BITMASK_ATTACHED;
}
if (firstInvite.isDraft()) {
flags |= Flag.BITMASK_DRAFT;
} else {
flags &= ~Flag.BITMASK_DRAFT;
}
if (firstInvite.isHighPriority()) {
flags |= Flag.BITMASK_HIGH_PRIORITY;
} else {
flags &= ~Flag.BITMASK_HIGH_PRIORITY;
}
if (firstInvite.isLowPriority()) {
flags |= Flag.BITMASK_LOW_PRIORITY;
} else {
flags &= ~Flag.BITMASK_LOW_PRIORITY;
}
MailItem.Type type = firstInvite.isEvent() ? Type.APPOINTMENT : Type.TASK;
String sender = null;
ZOrganizer org = firstInvite.getOrganizer();
if (org != null) {
sender = org.getIndexString();
}
sender = Strings.nullToEmpty(sender);
String subject = Strings.nullToEmpty(firstInvite.getName());
List<Invite> invites = new ArrayList<Invite>();
invites.add(firstInvite);
Recurrence.IRecurrence recur = firstInvite.getRecurrence();
long startTime, endTime;
if (recur != null) {
ParsedDateTime dtStart = recur.getStartTime();
startTime = dtStart != null ? dtStart.getUtcTime() : 0;
ParsedDateTime dtEnd = recur.getEndTime();
endTime = dtEnd != null ? dtEnd.getUtcTime() : 0;
} else {
ParsedDateTime dtStart = firstInvite.getStartTime();
startTime = dtStart != null ? dtStart.getUtcTime() : 0;
ParsedDateTime dtEnd = firstInvite.getEffectiveEndTime();
endTime = dtEnd != null ? dtEnd.getUtcTime() : startTime;
}
Account account = mbox.getAccount();
firstInvite.updateMyPartStat(account, firstInvite.getPartStat());
UnderlyingData data = new UnderlyingData();
data.id = id;
data.type = type.toByte();
data.folderId = folder.getId();
if (!folder.inSpam() || mbox.getAccount().getBooleanAttr(Provisioning.A_zimbraJunkMessagesIndexingEnabled, false)) {
data.indexId = IndexStatus.DEFERRED.id();
}
data.imapId = id;
data.date = mbox.getOperationTimestamp();
data.setFlags(flags & (Flag.FLAGS_CALITEM | Flag.FLAGS_GENERIC));
data.setTags(ntags);
data.setSubject(subject);
data.metadata = encodeMetadata(DEFAULT_COLOR_RGB, 1, 1, custom, uid, startTime, endTime, recur, invites, firstInvite.getTimeZoneMap(), new ReplyList(), null);
data.contentChanged(mbox, false);
if (!firstInvite.hasRecurId()) {
ZimbraLog.calendar.info("Adding CalendarItem: id=%d, Message-ID=\"%s\", folderId=%d, subject=\"%s\", UID=%s", data.id, pm != null ? pm.getMessageID() : "(none)", folder.getId(), firstInvite.isPublic() ? firstInvite.getName() : "(private)", firstInvite.getUid());
} else {
ZimbraLog.calendar.info("Adding CalendarItem: id=%d, Message-ID=\"%s\", folderId=%d, subject=\"%s\", UID=%s, recurId=%s", data.id, pm != null ? pm.getMessageID() : "(none)", folder.getId(), firstInvite.isPublic() ? firstInvite.getName() : "(private)", firstInvite.getUid(), firstInvite.getRecurId().getDtZ());
}
new DbMailItem(mbox).setSender(sender).create(data);
CalendarItem item = type == Type.APPOINTMENT ? new Appointment(mbox, data) : new Task(mbox, data);
Invite defInvite = item.getDefaultInviteOrNull();
if (defInvite != null) {
Collection<Instance> instances = item.expandInstances(CalendarUtils.MICROSOFT_EPOC_START_MS_SINCE_EPOC, Long.MAX_VALUE, false);
if (instances.isEmpty()) {
ZimbraLog.calendar.info("CalendarItem has effectively zero instances: id=%d, folderId=%d, subject=\"%s\", UID=%s ", data.id, folder.getId(), firstInvite.isPublic() ? firstInvite.getName() : "(private)", firstInvite.getUid());
item.delete();
throw ServiceException.FORBIDDEN("Recurring series has effectively zero instances");
}
}
// If we're creating an invite during email delivery, always default to NEEDS_ACTION state.
// If not email delivery, we assume the requesting client knows what it's doing and has set the
// correct partstat in the invite.
String defaultPartStat;
if (mbox.getOperationContext() == null) {
// octxt == null implies we're in email delivery. (There needs to be better way to determine this...)
defaultPartStat = IcalXmlStrMap.PARTSTAT_NEEDS_ACTION;
} else {
defaultPartStat = firstInvite.getPartStat();
}
item.processPartStat(firstInvite, pm != null ? pm.getMimeMessage() : null, true, defaultPartStat);
item.finishCreation(null);
folder.updateHighestMODSEQ();
if (pm != null) {
item.createBlob(pm, firstInvite);
}
item.mEndTime = item.recomputeRecurrenceEndTime(item.mEndTime);
if (firstInvite.hasAlarm()) {
item.recomputeNextAlarm(nextAlarm, false, false);
item.saveMetadata();
AlarmData alarmData = item.getAlarmData();
if (alarmData != null) {
long newNextAlarm = alarmData.getNextAtBase();
if (newNextAlarm > 0 && newNextAlarm < item.mStartTime) {
item.mStartTime = newNextAlarm;
}
}
}
DbMailItem.addToCalendarItemTable(item);
Callback cb = getCallback();
if (cb != null) {
cb.created(item);
}
return item;
}
use of com.zimbra.cs.mailbox.calendar.ZOrganizer in project zm-mailbox by Zimbra.
the class CalendarItem method getSender.
@Override
public String getSender() {
String sender = null;
Invite firstInvite = getDefaultInviteOrNull();
if (firstInvite != null) {
ZOrganizer org = firstInvite.getOrganizer();
if (org != null)
sender = org.getIndexString();
}
return Strings.nullToEmpty(sender);
}
Aggregations