use of com.zimbra.cs.mailbox.Appointment in project zm-mailbox by Zimbra.
the class FreeBusyQuery method prepareRequests.
private void prepareRequests(ArrayList<FreeBusy> local, RemoteFreeBusyProvider remote, ArrayList<String> external) {
for (String id : mTargets.keySet()) {
Account acct = mTargets.get(id);
try {
if (acct == null || acct.isAccountExternal() || acct.getBooleanAttr(Provisioning.A_zimbraFreebusyLocalMailboxNotActive, false)) {
external.add(id);
continue;
}
int folder = mTargetFolder.get(id);
if (Provisioning.onLocalServer(acct)) {
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(acct);
OperationContext octxt = null;
if (mCtxt != null && mCtxt.getAuthToken() != null)
octxt = new OperationContext(mCtxt.getAuthToken());
else if (mRequestor != null)
octxt = new OperationContext(mRequestor);
else
octxt = new OperationContext(GuestAccount.ANONYMOUS_ACCT);
Appointment exAppt = null;
if (mExApptUid != null) {
CalendarItem ci = mbox.getCalendarItemByUid(octxt, mExApptUid);
if (ci instanceof Appointment)
exAppt = (Appointment) ci;
}
local.add(mbox.getFreeBusy(octxt, id, mStart, mEnd, folder, exAppt));
} else {
remote.addFreeBusyRequest(mRequestor, acct, id, mStart, mEnd, folder);
}
} catch (ServiceException e) {
ZimbraLog.fb.error("cannot get free/busy for " + id, e);
}
}
}
use of com.zimbra.cs.mailbox.Appointment in project zm-mailbox by Zimbra.
the class ArchiveFormatter method saveItem.
private ArchiveOutputStream saveItem(UserServletContext context, MailItem mi, Map<Integer, String> fldrs, Map<Integer, Integer> cnts, boolean version, ArchiveOutputStream aos, CharsetEncoder charsetEncoder, Set<String> names) throws ServiceException {
String ext = null, name = null;
String extra = null;
Integer fid = mi.getFolderId();
String fldr;
InputStream is = null;
String metaParam = context.params.get(UserServlet.QP_META);
boolean meta = metaParam == null ? getDefaultMeta() : !metaParam.equals("0");
if (!version && mi.isTagged(Flag.FlagInfo.VERSIONED)) {
for (MailItem rev : context.targetMailbox.getAllRevisions(context.opContext, mi.getId(), mi.getType())) {
if (mi.getVersion() != rev.getVersion())
aos = saveItem(context, rev, fldrs, cnts, true, aos, charsetEncoder, names);
}
}
switch(mi.getType()) {
case APPOINTMENT:
Appointment appt = (Appointment) mi;
if (!appt.isPublic() && !appt.allowPrivateAccess(context.getAuthAccount(), context.isUsingAdminPrivileges())) {
return aos;
}
if (meta) {
name = appt.getSubject();
ext = "appt";
} else {
ext = "ics";
}
break;
case CHAT:
ext = "chat";
break;
case CONTACT:
Contact ct = (Contact) mi;
name = ct.getFileAsString();
if (!meta) {
ext = "vcf";
}
break;
case FLAG:
return aos;
case FOLDER:
case MOUNTPOINT:
case SEARCHFOLDER:
if (mi.getId() == Mailbox.ID_FOLDER_ROOT) {
name = "ROOT";
} else if (mi.getId() == Mailbox.ID_FOLDER_USER_ROOT) {
name = "USER_ROOT";
} else {
name = mi.getName();
}
break;
case MESSAGE:
Message msg = (Message) mi;
if (msg.hasCalendarItemInfos()) {
Set<ItemId> calItems = Sets.newHashSet();
for (Iterator<CalendarItemInfo> it = msg.getCalendarItemInfoIterator(); it.hasNext(); ) {
ItemId iid = it.next().getCalendarItemId();
if (iid != null) {
calItems.add(iid);
}
}
for (ItemId i : calItems) {
if (extra == null) {
extra = "calendar=" + i.toString();
} else {
extra += ',' + i.toString();
}
}
}
ext = "eml";
break;
case NOTE:
ext = "note";
break;
case TASK:
Task task = (Task) mi;
if (!task.isPublic() && !task.allowPrivateAccess(context.getAuthAccount(), context.isUsingAdminPrivileges())) {
return aos;
}
ext = "task";
break;
case VIRTUAL_CONVERSATION:
return aos;
case WIKI:
ext = "wiki";
break;
}
fldr = fldrs.get(fid);
if (fldr == null) {
Folder f = mi.getMailbox().getFolderById(context.opContext, fid);
cnts.put(fid, 1);
fldr = f.getPath();
if (fldr.startsWith("/")) {
fldr = fldr.substring(1);
}
fldr = sanitize(fldr, charsetEncoder);
fldr = ILLEGAL_FOLDER_CHARS.matcher(fldr).replaceAll("_");
fldrs.put(fid, fldr);
} else if (!(mi instanceof Folder)) {
final int BATCH = 500;
int cnt = cnts.get(fid) + 1;
cnts.put(fid, cnt);
cnt /= BATCH;
if (cnt > 0) {
fldr = fldr + '!' + cnt;
}
}
int targetBaseLength = 0;
if (context.noHierarchy()) {
// Parent hierarchy is not needed, so construct the folder names without parent hierarchy.
// e.g> represent "inbox/subfolder/target" as "target".
String targetPath = null;
if (context.itemPath.endsWith("/")) {
// inbox/subfolder/target/
targetPath = context.itemPath.substring(0, context.itemPath.lastIndexOf("/"));
} else {
// inbox/subfolder/target
targetPath = context.itemPath;
}
// "inbox/subfolder".length()
targetBaseLength = targetPath.lastIndexOf('/');
if (targetBaseLength >= fldr.length()) {
// fldr is "inbox/subfolder"
fldr = "";
} else if (targetBaseLength > 0) {
// fldr is "inbox/subfolder/target"
fldr = fldr.substring(targetBaseLength + 1);
}
}
try {
ArchiveOutputEntry aoe;
byte[] data = null;
String path = mi instanceof Contact ? getEntryName(mi, fldr, name, ext, charsetEncoder, names) : getEntryName(mi, fldr, name, ext, charsetEncoder, !(mi instanceof Document));
long miSize = mi.getSize();
if (miSize == 0 && mi.getDigest() != null) {
ZimbraLog.misc.debug("blob db size 0 for item %d", mi.getId());
return aos;
}
try {
is = mi.getContentStream();
} catch (Exception e) {
ZimbraLog.misc.error("missing blob for item %d: expected %d", mi.getId(), miSize);
return aos;
}
if (aos == null) {
aos = getOutputStream(context, charsetEncoder.charset().name());
}
if ((mi instanceof CalendarItem) && (context.getStartTime() != TIME_UNSPECIFIED || context.getEndTime() != TIME_UNSPECIFIED)) {
Collection<Instance> instances = ((CalendarItem) mi).expandInstances(context.getStartTime(), context.getEndTime(), false);
if (instances.isEmpty()) {
return aos;
}
}
aoe = aos.newOutputEntry(path + ".meta", mi.getType().toString(), mi.getType().toByte(), mi.getDate());
if (mi instanceof Message && (mi.getFlagBitmask() & Flag.ID_UNREAD) != 0) {
aoe.setUnread();
}
if (meta) {
ItemData itemData = new ItemData(mi, extra);
if (context.noHierarchy()) {
// itemData.path is of the form /Inbox/subfolder/target and after this step it becomes /target.
if (targetBaseLength > 0 && ((targetBaseLength + 1) < itemData.path.length())) {
itemData.path = itemData.path.substring(targetBaseLength + 1);
}
}
byte[] metaData = itemData.encode();
aoe.setSize(metaData.length);
aos.putNextEntry(aoe);
aos.write(metaData);
aos.closeEntry();
} else if (mi instanceof CalendarItem) {
Browser browser = HttpUtil.guessBrowser(context.req);
List<CalendarItem> calItems = new ArrayList<CalendarItem>();
boolean needAppleICalHacks = Browser.APPLE_ICAL.equals(browser);
boolean useOutlookCompatMode = Browser.IE.equals(browser);
OperationContext octxt = new OperationContext(context.getAuthAccount(), context.isUsingAdminPrivileges());
StringWriter writer = new StringWriter();
calItems.add((CalendarItem) mi);
context.targetMailbox.writeICalendarForCalendarItems(writer, octxt, calItems, useOutlookCompatMode, true, needAppleICalHacks, true);
data = writer.toString().getBytes(charsetEncoder.charset());
} else if (mi instanceof Contact) {
VCard vcf = VCard.formatContact((Contact) mi);
data = vcf.getFormatted().getBytes(charsetEncoder.charset());
} else if (mi instanceof Message) {
if (context.hasPart()) {
MimeMessage mm = ((Message) mi).getMimeMessage();
Set<String> attachmentNames = new HashSet<String>();
for (String part : context.getPart().split(",")) {
BufferStream bs;
MimePart mp = Mime.getMimePart(mm, part);
long sz;
if (mp == null) {
throw MailServiceException.NO_SUCH_PART(part);
}
name = Mime.getFilename(mp);
if (!Normalizer.isNormalized(name, Normalizer.Form.NFC)) {
name = Normalizer.normalize(name, Normalizer.Form.NFC);
}
ext = null;
sz = mp.getSize();
if (sz == -1) {
sz = miSize;
}
if (name == null) {
name = "attachment";
} else {
int dot = name.lastIndexOf('.');
if (dot != -1 && dot < name.length() - 1) {
ext = name.substring(dot + 1);
name = name.substring(0, dot);
}
}
bs = new BufferStream(sz, 1024 * 1024);
InputStream stream = mp.getInputStream();
try {
bs.readFrom(stream);
} finally {
// close the stream, it could be an instance of PipedInputStream.
ByteUtil.closeStream(stream);
}
aoe = aos.newOutputEntry(getEntryName(mi, "", name, ext, charsetEncoder, attachmentNames), mi.getType().toString(), mi.getType().toByte(), mi.getDate());
sz = bs.getSize();
aoe.setSize(sz);
aos.putNextEntry(aoe);
bs.copyTo(aos.getOutputStream());
bs.close();
aos.closeEntry();
}
return aos;
}
}
aoe = aos.newOutputEntry(path, mi.getType().toString(), mi.getType().toByte(), mi.getDate());
if (data != null) {
aoe.setSize(data.length);
aos.putNextEntry(aoe);
aos.write(data);
aos.closeEntry();
} else if (is != null) {
if (context.shouldReturnBody()) {
byte[] buf = new byte[aos.getRecordSize() * 20];
int in;
long remain = miSize;
aoe.setSize(miSize);
aos.putNextEntry(aoe);
while (remain > 0 && (in = is.read(buf)) >= 0) {
aos.write(buf, 0, remain < in ? (int) remain : in);
remain -= in;
}
if (remain != 0) {
ZimbraLog.misc.error("mismatched blob size for item %d: expected %d", mi.getId(), miSize);
if (remain > 0) {
Arrays.fill(buf, (byte) ' ');
while (remain > 0) {
aos.write(buf, 0, remain < buf.length ? (int) remain : buf.length);
remain -= buf.length;
}
}
aos.closeEntry();
aoe = aos.newOutputEntry(path + ".err", mi.getType().toString(), mi.getType().toByte(), mi.getDate());
aoe.setSize(0);
aos.putNextEntry(aoe);
}
} else {
// Read headers into memory to compute size
byte[] headerData = HeadersOnlyInputStream.getHeaders(is);
aoe.setSize(headerData.length);
aos.putNextEntry(aoe);
aos.write(headerData);
}
aos.closeEntry();
}
} catch (Exception e) {
throw ServiceException.FAILURE("archive error", e);
} finally {
ByteUtil.closeStream(is);
}
return aos;
}
use of com.zimbra.cs.mailbox.Appointment in project zm-mailbox by Zimbra.
the class ToXML method encodeCalendarItemSummary.
/**
* Encode the metadata for a calendar item.
*
* The content for the calendar item is a big multipart/digest containing each
* invite in the calendar item as a sub-mimepart -- it can be retreived from the content
* servlet:
* http://servername/service/content/get?id=<calItemId>
*
* The client can ALSO request just the content for each individual invite using a
* compound item-id request:
* http://servername/service/content/get?id=<calItemId>-<invite-mail-item-id>
*
* DO NOT use the raw invite-mail-item-id to fetch the content: since the invite is a
* standard mail-message it can be deleted by the user at any time!
*/
public static Element encodeCalendarItemSummary(Element parent, ItemIdFormatter ifmt, OperationContext octxt, CalendarItem calItem, int fields, boolean includeInvites, boolean includeContent) throws ServiceException {
final int MAX_RETRIES = LC.calendar_item_get_max_retries.intValue();
Element elem = null;
Mailbox mbox = calItem.getMailbox();
int changeId = calItem.getSavedSequence();
int numTries = 0;
while (numTries < MAX_RETRIES) {
numTries++;
if (calItem instanceof Appointment) {
elem = parent.addNonUniqueElement(MailConstants.E_APPOINTMENT);
} else {
elem = parent.addNonUniqueElement(MailConstants.E_TASK);
}
try {
setCalendarItemFields(elem, ifmt, octxt, calItem, fields, includeInvites, includeContent, true);
if (needToOutput(fields, Change.METADATA)) {
encodeAllCustomMetadata(elem, calItem, fields);
}
return elem;
} catch (ServiceException e) {
// Problem writing the structure to the response
// (this case generally means that the blob backing the Calendar item disappeared halfway through)
elem.detach();
elem = null;
try {
calItem = mbox.getCalendarItemById(octxt, calItem.getId());
if (calItem.getSavedSequence() != changeId) {
// just fetch the new item and try again
changeId = calItem.getSavedSequence();
ZimbraLog.soap.info("caught calendar item content change while serializing; will retry");
continue;
}
} catch (NoSuchItemException nsie) {
// the message has been deleted, so don't include data in the response
throw nsie;
}
// Were unable to write calendar item structure & not clear what went wrong. Try again a few times
// in case it was related to underlying modifications
ZimbraLog.soap.warn("Could not serialize full calendar item structure in response", e);
}
}
// Still failing after several retries...
throw NoSuchItemException.NO_SUCH_CALITEM("Problem encoding calendar item. Maybe corrupt");
}
use of com.zimbra.cs.mailbox.Appointment in project zm-mailbox by Zimbra.
the class SnoozeCalendarItemAlarm method handle.
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Mailbox mbox = getRequestedMailbox(zsc);
String acctId = mbox.getAccountId();
Account authAcct = getAuthenticatedAccount(zsc);
OperationContext octxt = getOperationContext(zsc, context);
Element response = getResponseElement(zsc);
for (String calItemElement : sCalItemElems) {
for (Iterator<Element> iter = request.elementIterator(calItemElement); iter.hasNext(); ) {
Element calItemElem = iter.next();
ItemId iid = new ItemId(calItemElem.getAttribute(MailConstants.A_ID), zsc);
long snoozeUntil = calItemElem.getAttributeLong(MailConstants.A_CAL_ALARM_SNOOZE_UNTIL);
// trace logging
ZimbraLog.calendar.info("<SnoozeCalendarItemAlarm> id=%s,until=%d", iid.toString(), snoozeUntil);
// mailbox for this calendar item; not necessarily same as requested mailbox
Mailbox ciMbox = null;
String ciAcctId = iid.getAccountId();
if (ciAcctId == null || ciAcctId.equals(acctId)) {
ciMbox = mbox;
} else {
// Let's see if the account is a Desktop account.
if (AccountUtil.isZDesktopLocalAccount(zsc.getAuthtokenAccountId()))
ciMbox = MailboxManager.getInstance().getMailboxByAccountId(ciAcctId, false);
if (ciMbox == null)
throw MailServiceException.PERM_DENIED("cannot snooze alarms of a shared calendar");
}
int calItemId = iid.getId();
ItemIdFormatter ifmt = new ItemIdFormatter(authAcct.getId(), acctId, false);
try {
ciMbox.snoozeCalendarItemAlarm(octxt, calItemId, snoozeUntil);
CalendarItem calItem = ciMbox.getCalendarItemById(octxt, calItemId);
Element calItemRespElem;
if (calItem instanceof Appointment)
calItemRespElem = response.addElement(MailConstants.E_APPOINTMENT);
else
calItemRespElem = response.addElement(MailConstants.E_TASK);
calItemRespElem.addAttribute(MailConstants.A_CAL_ID, iid.toString(ifmt));
boolean hidePrivate = !calItem.allowPrivateAccess(authAcct, zsc.isUsingAdminPrivileges());
boolean showAll = !hidePrivate || calItem.isPublic();
if (showAll) {
AlarmData alarmData = calItem.getAlarmData();
if (alarmData != null)
ToXML.encodeAlarmData(calItemRespElem, calItem, alarmData);
}
} catch (NoSuchItemException nsie) {
// item must not exist in db anymore.
// this can happen if an alarm is snoozed while a big sync is happening which deletes the item (e.g. bug 48560)
// since item is not in db, it has effectively been snoozed; return ok and no further alarms
Element calItemRespElem = response.addElement(calItemElement);
calItemRespElem.addAttribute(MailConstants.A_CAL_ID, iid.toString(ifmt));
}
}
}
return response;
}
use of com.zimbra.cs.mailbox.Appointment in project zm-mailbox by Zimbra.
the class SearchResponse method add.
/**
* The encoded element OR NULL if the search params contained a calItemExpand
* range AND the calendar item did not have any instances in the specified range.
*
* @return could be NULL
*/
private Element add(CalendarItemHit hit) throws ServiceException {
CalendarItem item = hit.getCalendarItem();
Account acct = DocumentHandler.getRequestedAccount(zsc);
long rangeStart = params.getCalItemExpandStart();
long rangeEnd = params.getCalItemExpandEnd();
if (rangeStart == -1 && rangeEnd == -1 && (item instanceof Appointment)) {
// If no time range was given, force first instance only. (bug 51267)
rangeStart = item.getStartTime();
rangeEnd = rangeStart + 1;
}
EncodeCalendarItemResult encoded = GetCalendarItemSummaries.encodeCalendarItemInstances(zsc, octxt, item, acct, rangeStart, rangeEnd, true);
Element el = encoded.element;
if (el != null) {
element.addElement(el);
ToXML.setCalendarItemFields(el, ifmt, octxt, item, PendingModifications.Change.ALL_FIELDS, false, params.getNeuterImages());
el.addAttribute(MailConstants.A_CONTENTMATCHED, true);
}
return el;
}
Aggregations