@Override public CalendarItem getCalendarItemByUid(OperationContext octxt, String uid) throws ServiceException { lock.lock(); try { CalendarItem item = super.getCalendarItemByUid(octxt, uid); if (item == null && Db.supports(Capability.CASE_SENSITIVE_COMPARISON) && Invite.isOutlookUid(uid)) { if (!uid.toLowerCase().equals(uid)) { // maybe stored in db in lower case item = super.getCalendarItemByUid(octxt, uid.toLowerCase()); if (item != null) { OfflineLog.offline.debug( "coercing Outlook calitem [%d] UID to upper case", item.getId()); boolean success = false; try { beginTransaction("forceUpperAppointment", octxt); uncache(item); DbOfflineMailbox.forceUidUpperCase(this, uid.toLowerCase()); item = super.getCalendarItemByUid(octxt, uid); assert (item != null); success = true; } finally { endTransaction(success); } } } else { // possible that we're receiving update from unpatched zcs which is in lower case and our // db is // already correct return the upper case equivalent; server will keep sending lower until // it's // patched but should handle pushes in upper since MySQL is case insensitive item = super.getCalendarItemByUid(octxt, uid.toUpperCase()); if (item != null) { OfflineLog.offline.debug("received lower case UID but our DB is already in upper case"); } } } return item; } finally { lock.release(); } }
@Override public Element handle(Element request, Map<String, Object> context) throws ServiceException { ZimbraSoapContext zsc = getZimbraSoapContext(context); Mailbox mbox = getRequestedMailbox(zsc); OperationContext octxt = getOperationContext(zsc, context); ItemIdFormatter ifmt = new ItemIdFormatter(zsc); int flags = Flag.toBitmask(request.getAttribute(MailConstants.A_FLAGS, null)); String[] tags = TagUtil.parseTags(request, mbox, octxt); mbox.lock.lock(); try { int defaultFolder = getItemType() == MailItem.Type.TASK ? Mailbox.ID_FOLDER_TASKS : Mailbox.ID_FOLDER_CALENDAR; String defaultFolderStr = Integer.toString(defaultFolder); String folderIdStr = request.getAttribute(MailConstants.A_FOLDER, defaultFolderStr); ItemId iidFolder = new ItemId(folderIdStr, zsc); Folder folder = mbox.getFolderById(octxt, iidFolder.getId()); SetCalendarItemParseResult parsed = parseSetAppointmentRequest(request, zsc, octxt, folder, getItemType(), false); CalendarItem calItem = mbox.setCalendarItem( octxt, iidFolder.getId(), flags, tags, parsed.defaultInv, parsed.exceptions, parsed.replies, parsed.nextAlarm); Element response = getResponseElement(zsc); if (parsed.defaultInv != null) { response .addElement(MailConstants.A_DEFAULT) .addAttribute( MailConstants.A_ID, ifmt.formatItemId(parsed.defaultInv.invite.getMailItemId())); } if (parsed.exceptions != null) { for (SetCalendarItemData cur : parsed.exceptions) { Element e = response.addElement(MailConstants.E_CAL_EXCEPT); e.addAttribute(MailConstants.A_CAL_RECURRENCE_ID, cur.invite.getRecurId().toString()); e.addAttribute(MailConstants.A_ID, ifmt.formatItemId(cur.invite.getMailItemId())); } } String itemId = ifmt.formatItemId(calItem == null ? 0 : calItem.getId()); response.addAttribute(MailConstants.A_CAL_ID, itemId); try { Element inv = request .getElement(MailConstants.A_DEFAULT) .getElement(MailConstants.E_MSG) .getElement(MailConstants.E_INVITE); Element comp = inv.getOptionalElement(MailConstants.E_INVITE_COMPONENT); if (comp != null) { inv = comp; } String reqCalItemId = inv.getAttribute(MailConstants.A_CAL_ID); String uid = inv.getAttribute(MailConstants.A_UID); boolean uidSame = (calItem == null || (calItem.getUid() == null && uid == null) || (calItem.getUid() != null && (calItem.getUid().equals(uid) || (Invite.isOutlookUid(calItem.getUid()) && calItem .getUid() .equalsIgnoreCase( uid))))); // new or same as requested, or Outlook and // case-insensitive equal if (ZimbraLog.calendar.isInfoEnabled()) { StringBuilder logBuf = new StringBuilder(); if (!reqCalItemId.equals(itemId)) { logBuf .append("Mapped requested id ") .append(reqCalItemId) .append(" -> ") .append(itemId); } if (!uidSame) { logBuf .append(" ?? requested UID ") .append(uid) .append(" differs from mapped ") .append(calItem.getUid()); ZimbraLog.calendar.warn(logBuf.toString()); } else if (logBuf.length() > 0) { ZimbraLog.calendar.info(logBuf.toString()); } } assert (uidSame); } catch (ServiceException se) { // one of the elements we wanted to use doesn't exist; ignore; no log/assertion possible } if (!parsed.isTodo) response.addAttribute(MailConstants.A_APPT_ID_DEPRECATE_ME, itemId); // for backward compat return response; } finally { mbox.lock.release(); } }