use of com.zimbra.common.util.HttpUtil.Browser in project zm-mailbox by Zimbra.
the class GetICal method handle.
/* (non-Javadoc)
* @see com.zimbra.soap.DocumentHandler#handle(org.dom4j.Element, java.util.Map)
*/
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
Account authAccount = getAuthenticatedAccount(zsc);
Mailbox mbx = getRequestedMailbox(zsc);
OperationContext octxt = getOperationContext(zsc, context);
String iidStr = request.getAttribute(MailConstants.A_ID, null);
long rangeStart = request.getAttributeLong(MailConstants.A_CAL_START_TIME, -1);
long rangeEnd = request.getAttributeLong(MailConstants.A_CAL_END_TIME, -1);
// int compNum = (int)request.getAttributeLong(MailService.A_CAL_COMPONENT_NUM);
int compNum = 0;
Browser browser = HttpUtil.guessBrowser(zsc.getUserAgent());
boolean useOutlookCompatMode = Browser.IE.equals(browser);
try {
try {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
OutputStreamWriter wout = new OutputStreamWriter(buf);
ZVCalendar cal = null;
ItemId iid = iidStr != null ? new ItemId(iidStr, zsc) : null;
if (iid != null) {
CalendarItem calItem = mbx.getCalendarItemById(octxt, iid.getId());
if (calItem == null) {
throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
}
Invite inv = calItem.getInvite(iid.getSubpartId(), compNum);
if (inv == null) {
throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
}
boolean allowPrivateAccess = calItem.allowPrivateAccess(authAccount, zsc.isUsingAdminPrivileges());
cal = inv.newToICalendar(useOutlookCompatMode, allowPrivateAccess);
cal.toICalendar(wout);
} else {
mbx.writeICalendarForRange(wout, octxt, rangeStart, rangeEnd, Mailbox.ID_FOLDER_CALENDAR, useOutlookCompatMode, false, false);
}
wout.flush();
Element response = getResponseElement(zsc);
Element icalElt = response.addElement(MailConstants.E_CAL_ICAL);
if (iid != null)
icalElt.addAttribute(MailConstants.A_ID, new ItemIdFormatter(zsc).formatItemId(iid));
icalElt.addText(buf.toString());
return response;
} catch (MailServiceException.NoSuchItemException e) {
throw ServiceException.FAILURE("Error could get default invite for Invite: " + iidStr + "-" + compNum, e);
} catch (IOException e) {
throw ServiceException.FAILURE("IO Exception while outputing Calendar for Invite: " + iidStr + "-" + compNum, e);
}
} catch (MailServiceException.NoSuchItemException e) {
throw ServiceException.FAILURE("No Such Invite Message: " + iidStr, e);
}
}
use of com.zimbra.common.util.HttpUtil.Browser 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);
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.common.util.HttpUtil.Browser in project zm-mailbox by Zimbra.
the class IcsFormatter method formatCallback.
@Override
public void formatCallback(UserServletContext context) throws IOException, ServiceException {
Iterator<? extends MailItem> iterator = null;
List<CalendarItem> calItems = new ArrayList<CalendarItem>();
//ZimbraLog.mailbox.info("end = "+new Date(context.getEndTime()));
try {
long start = context.getStartTime();
long end = context.getEndTime();
boolean hasTimeRange = start != TIME_UNSPECIFIED && end != TIME_UNSPECIFIED;
iterator = getMailItems(context, start, end, Integer.MAX_VALUE);
// this is lame
while (iterator.hasNext()) {
MailItem item = iterator.next();
if (item instanceof CalendarItem) {
CalendarItem calItem = (CalendarItem) item;
if (hasTimeRange) {
Collection<Instance> instances = calItem.expandInstances(start, end, false);
if (!instances.isEmpty())
calItems.add(calItem);
} else {
calItems.add(calItem);
}
}
}
} finally {
if (iterator instanceof QueryResultIterator)
((QueryResultIterator) iterator).finished();
}
// todo: get from folder name
String filename = context.itemPath;
if (mayAttach(context)) {
if (filename == null || filename.length() == 0)
filename = "contacts";
// Let the client specify the filename to save as
String requestFilename = context.req.getParameter("filename");
if (requestFilename != null)
filename = requestFilename;
else
// Trim off leading non-word characters (e.g. forward slash)
filename = filename.replaceAll("^\\W", "");
if (filename.toLowerCase().endsWith(".ics") == false)
filename = filename + ".ics";
String cd = HttpUtil.createContentDisposition(context.req, Part.ATTACHMENT, filename);
context.resp.addHeader("Content-Disposition", cd);
}
Browser browser = HttpUtil.guessBrowser(context.req);
boolean useOutlookCompatMode = Browser.IE.equals(browser);
// bug 15549
boolean needAppleICalHacks = Browser.APPLE_ICAL.equals(browser);
// Use only htmlFormat when the file isn't supposed to be downloaded (ie. it's supposed to be shown in the browser). Mangles the code so it can be displayed correctly, especially by IE
boolean htmlFormat = !mayAttach(context) && Browser.IE.equals(browser);
context.resp.setCharacterEncoding(MimeConstants.P_CHARSET_UTF8);
String contentType;
if (htmlFormat) {
contentType = MimeConstants.CT_TEXT_HTML;
} else if (mayAttach(context)) {
contentType = MimeConstants.CT_TEXT_CALENDAR;
} else {
contentType = MimeConstants.CT_TEXT_PLAIN;
}
context.resp.setContentType(contentType);
OperationContext octxt = new OperationContext(context.getAuthAccount(), context.isUsingAdminPrivileges());
FileBufferedWriter fileBufferedWriter = new FileBufferedWriter(context.resp.getWriter(), LC.calendar_ics_export_buffer_size.intValueWithinRange(0, FileBufferedWriter.MAX_BUFFER_SIZE));
try {
if (htmlFormat)
fileBufferedWriter.write("<html><body><pre>");
context.targetMailbox.writeICalendarForCalendarItems(fileBufferedWriter, octxt, calItems, (context.target != null && context.target instanceof Folder) ? (Folder) context.target : null, useOutlookCompatMode, true, needAppleICalHacks, true, htmlFormat, includeInlineAttaches(context));
if (htmlFormat)
fileBufferedWriter.write("</pre></body></html>");
} finally {
fileBufferedWriter.finish();
}
}
Aggregations