use of com.zimbra.cs.mailbox.calendar.RecurId in project zm-mailbox by Zimbra.
the class ModifyInvitePartStat method redo.
@Override
public void redo() throws Exception {
Mailbox mbox = MailboxManager.getInstance().getMailboxById(getMailboxId());
CalendarItem calItem = mbox.getCalendarItemById(null, mCalItemId);
RecurId recurId = null;
if (mRecurIdDt != null)
recurId = new RecurId(ParsedDateTime.parse(mRecurIdDt, calItem.getTimeZoneMap()), mRecurIdRange);
mbox.modifyPartStat(getOperationContext(), mCalItemId, recurId, mCnStr, mAddressStr, mCUTypeStr, mRoleStr, mPartStatStr, mRsvp, mSeqNo, mDtStamp);
}
use of com.zimbra.cs.mailbox.calendar.RecurId in project zm-mailbox by Zimbra.
the class CalendarItem method requirePrivateCheck.
// If we're adding a private invite, we must make sure the authenticated user has permission to
// access private data. If we're adding a public invite but the appointment currently has
// some private data, private access permission is not needed as long as the instance(s) being
// updated aren't currently private.
private boolean requirePrivateCheck(Invite newInvite) {
if (!newInvite.isPublic()) {
// adding a private invite
return true;
}
if (!isPublic()) {
RecurId rid = newInvite.getRecurId();
// If canceling whole series, requester must have private access permission.
if (rid == null && newInvite.isCancel())
return true;
Invite current = getInvite(rid);
// If no matching recurrence-id was found, look at the current series.
if (current == null && rid != null)
current = getInvite((RecurId) null);
if (current != null && !current.isPublic()) {
// updating a currently private invite to public
return true;
} else {
// no matching rid found, or current is public
return false;
}
} else {
// Both old and new are public.
return false;
}
}
use of com.zimbra.cs.mailbox.calendar.RecurId 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.RecurId in project zm-mailbox by Zimbra.
the class Mailbox method processICalReplies.
private void processICalReplies(OperationContext octxt, ZVCalendar cal, String sender) throws ServiceException {
// Reply from Outlook will usually have PRODID set to the following:
//
// Outlook2007+ZCO: PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN
// Outlook2010+ZCO: PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
// Outlook20xx+Exchange: PRODID:Microsoft Exchange Server 2007
// (if Exchange is Exchange 2007; Exchange 2010 probably works similarly)
//
// Lowest common denominator is "Microsoft" substring.
String prodId = cal.getPropVal(ICalTok.PRODID, null);
boolean fromOutlook = prodId != null && prodId.toLowerCase().contains("microsoft");
AccountAddressMatcher acctMatcher = new AccountAddressMatcher(getAccount());
List<Invite> components = Invite.createFromCalendar(getAccount(), null, cal, false);
for (Invite inv : components) {
String orgAddress;
if (inv.hasOrganizer()) {
ZOrganizer org = inv.getOrganizer();
orgAddress = org.getAddress();
} else {
ZimbraLog.calendar.warn("No ORGANIZER found in REPLY. Assuming current mailbox.");
orgAddress = getAccount().getName();
}
if (acctMatcher.matches(orgAddress)) {
// RECURRENCE-ID.
if (fromOutlook && !inv.isAllDayEvent() && inv.hasRecurId()) {
RecurId rid = inv.getRecurId();
if (rid.getDt() != null && rid.getDt().hasZeroTime()) {
CalendarItem calItem = getCalendarItemByUid(octxt, inv.getUid());
if (calItem != null) {
Invite seriesInv = calItem.getDefaultInviteOrNull();
if (seriesInv != null) {
ParsedDateTime seriesDtStart = seriesInv.getStartTime();
if (seriesDtStart != null) {
ParsedDateTime fixedDt = seriesDtStart.cloneWithNewDate(rid.getDt());
RecurId fixedRid = new RecurId(fixedDt, rid.getRange());
ZimbraLog.calendar.debug("Fixed up invalid RECURRENCE-ID with zero time; before=[%s], after=[%s]", rid, fixedRid);
inv.setRecurId(fixedRid);
}
}
}
}
}
processICalReply(octxt, inv, sender);
} else {
Account orgAccount = inv.getOrganizerAccount();
// Unknown organizer
if (orgAccount == null) {
ZimbraLog.calendar.warn("Unknown organizer " + orgAddress + " in REPLY");
continue;
}
if (Provisioning.onLocalServer(orgAccount)) {
// Run in the context of organizer's mailbox.
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(orgAccount);
OperationContext orgOctxt = new OperationContext(mbox);
mbox.processICalReply(orgOctxt, inv, sender);
} else {
// Organizer's mailbox is on a remote server.
String uri = AccountUtil.getSoapUri(orgAccount);
if (uri == null) {
ZimbraLog.calendar.warn("Unable to determine URI for organizer account %s", orgAddress);
continue;
}
try {
// TODO: Get the iCalendar data from the
// MIME part since we already have it.
String ical;
StringWriter sr = null;
try {
sr = new StringWriter();
inv.setMethod(ICalTok.REPLY.toString());
inv.newToICalendar(true).toICalendar(sr);
ical = sr.toString();
} finally {
if (sr != null) {
sr.close();
}
}
Options options = new Options();
AuthToken authToken = AuthToken.getCsrfUnsecuredAuthToken(getAuthToken(octxt));
options.setAuthToken(authToken.toZAuthToken());
options.setTargetAccount(orgAccount.getName());
options.setTargetAccountBy(AccountBy.name);
options.setUri(uri);
options.setNoSession(true);
ZMailbox zmbox = ZMailbox.getMailbox(options);
zmbox.setAccountId(orgAccount.getId());
zmbox.iCalReply(ical, sender);
} catch (IOException e) {
throw ServiceException.FAILURE("Error while posting REPLY to organizer mailbox host", e);
}
}
}
}
}
use of com.zimbra.cs.mailbox.calendar.RecurId in project zm-mailbox by Zimbra.
the class CalendarUtils method parseReplyList.
public static List<ReplyInfo> parseReplyList(Element element, TimeZoneMap tzMap) throws ServiceException {
List<ReplyInfo> list = new ArrayList<ReplyInfo>();
for (Iterator<Element> iter = element.elementIterator(MailConstants.E_CAL_REPLY); iter.hasNext(); ) {
Element riElem = iter.next();
String addr = riElem.getAttribute(MailConstants.A_CAL_ATTENDEE);
ZAttendee at = new ZAttendee(addr);
String sentBy = riElem.getAttribute(MailConstants.A_CAL_SENTBY, null);
if (sentBy != null)
at.setSentBy(sentBy);
String partStat = riElem.getAttribute(MailConstants.A_CAL_PARTSTAT, null);
if (partStat != null)
at.setPartStat(partStat);
int seq = (int) riElem.getAttributeLong(MailConstants.A_SEQ);
long dtStamp = riElem.getAttributeLong(MailConstants.A_DATE);
RecurId recurId = RecurId.fromXml(riElem, tzMap);
ReplyInfo ri = new ReplyInfo(at, seq, dtStamp, recurId);
list.add(ri);
}
return list;
}
Aggregations