use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ItemActionHelper method executeRemote.
private void executeRemote() throws ServiceException, IOException {
Account target = Provisioning.getInstance().get(Key.AccountBy.id, mIidFolder.getAccountId());
AuthToken at = getAuthToken();
String pxyAuthToken = Provisioning.onLocalServer(target) ? null : at.getProxyAuthToken();
ZAuthToken zat = null;
if (pxyAuthToken == null) {
zat = at.toZAuthToken();
zat.resetProxyAuthToken();
} else {
zat = new ZAuthToken(pxyAuthToken);
}
ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(target));
zoptions.setNoSession(true);
zoptions.setTargetAccount(target.getId());
zoptions.setTargetAccountBy(Key.AccountBy.id);
ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
// check for mountpoints before going any further...
ZFolder zfolder = zmbx.getFolderById(mIidFolder.toString(mAuthenticatedAccount));
if (zfolder instanceof ZMountpoint) {
ItemId iidTarget = new ItemId(((ZMountpoint) zfolder).getCanonicalRemoteId(), mAuthenticatedAccount.getId());
if (!mIidFolder.equals(iidTarget)) {
mIidFolder = iidTarget;
if (++mHopCount > com.zimbra.soap.ZimbraSoapContext.MAX_HOP_COUNT)
throw MailServiceException.TOO_MANY_HOPS(mIidRequestedFolder);
schedule();
return;
}
}
boolean deleteOriginal = mOperation != Op.COPY;
String folderStr = mIidFolder.toString();
mCreatedIds = new ArrayList<String>(itemIds.length);
boolean toSpam = mIidFolder.getId() == Mailbox.ID_FOLDER_SPAM;
boolean toMailbox = !toSpam && mIidFolder.getId() != Mailbox.ID_FOLDER_TRASH;
for (MailItem item : mMailbox.getItemById(mOpCtxt, itemIds, type)) {
if (item == null) {
continue;
}
List<Message> msgs = null;
if (item instanceof Conversation) {
msgs = mMailbox.getMessagesByConversation(mOpCtxt, item.getId(), SortBy.DATE_ASC, -1);
}
if (deleteOriginal) {
if (msgs != null) {
// determine which of the conversation's component messages are actually able to be moved
boolean permDenied = false;
for (Iterator<Message> it = msgs.iterator(); it.hasNext(); ) {
Message msg = it.next();
if (!TargetConstraint.checkItem(mTargetConstraint, msg)) {
it.remove();
} else if (!canDelete(msg)) {
it.remove();
permDenied = true;
}
}
// stop here if no messages would be moved...
if (msgs.isEmpty()) {
if (permDenied) {
throw ServiceException.PERM_DENIED("cannot delete any messages in " + item.getType() + " " + item.getId());
}
// all messages were excluded by the TargetConstraint, so there's no failure...
continue;
}
} else {
if (!canDelete(item)) {
throw ServiceException.PERM_DENIED("cannot delete existing copy of " + item.getType() + " " + item.getId());
}
}
}
boolean fromSpam = item.inSpam();
if ((fromSpam && toMailbox) || (!fromSpam && toSpam)) {
try {
Folder dest = mMailbox.getFolderById(mOpCtxt, mIidFolder.getId());
SpamReport report = new SpamReport(toSpam, "remote " + mOperation, dest.getPath());
Folder source = mMailbox.getFolderById(mOpCtxt, item.getFolderId());
report.setSourceFolderPath(source.getPath());
report.setDestAccountName(target.getName());
SpamHandler.getInstance().handle(mOpCtxt, mMailbox, item.getId(), item.getType(), report);
} catch (OutOfMemoryError e) {
Zimbra.halt("out of memory", e);
} catch (Throwable t) {
ZimbraLog.mailop.info("could not train spam filter: " + new ItemId(item).toString(), t);
}
}
// since we can't apply tags to a remote object, hardwiring "tags" to null below...
String flags = (mOperation == Op.UPDATE && mFlags != null ? mFlags : item.getFlagString());
String name = ((mOperation == Op.RENAME || mOperation == Op.UPDATE) && mName != null ? mName : item.getName());
String createdId = null;
InputStream in = null;
switch(item.getType()) {
case CONTACT:
Contact ct = (Contact) item;
Map<String, ZMailbox.ZAttachmentInfo> attachments = new HashMap<String, ZMailbox.ZAttachmentInfo>();
for (Contact.Attachment att : ct.getAttachments()) {
String attachmentId = zmbx.uploadAttachment(att.getFilename(), att.getContent(), att.getContentType(), 0);
ZMailbox.ZAttachmentInfo info = new ZMailbox.ZAttachmentInfo().setAttachmentId(attachmentId);
attachments.put(att.getName(), info);
}
Map<String, String> fields = ct.getFields();
Map<String, String> members = new HashMap<String, String>();
for (String key : fields.keySet()) {
if (ContactConstants.A_groupMember.equals(key)) {
String memberEncoded = fields.get(key);
ContactGroup group = ContactGroup.init(memberEncoded);
for (Member m : group.getMembers()) {
members.put(m.getValue(), m.getType().getSoapEncoded());
}
break;
}
}
fields.remove(ContactConstants.A_groupMember);
ZContact contact = zmbx.createContact(folderStr, null, fields, attachments, members);
createdId = contact.getId();
mCreatedIds.add(createdId);
break;
case MESSAGE:
try {
in = StoreManager.getInstance().getContent(item.getBlob());
createdId = zmbx.addMessage(folderStr, flags, null, item.getDate(), in, item.getSize(), true);
} finally {
ByteUtil.closeStream(in);
}
mCreatedIds.add(createdId);
break;
case VIRTUAL_CONVERSATION:
case CONVERSATION:
for (Message msg : msgs) {
flags = (mOperation == Op.UPDATE && mFlags != null ? mFlags : msg.getFlagString());
try {
in = StoreManager.getInstance().getContent(msg.getBlob());
createdId = zmbx.addMessage(folderStr, flags, null, msg.getDate(), in, msg.getSize(), true);
} finally {
ByteUtil.closeStream(in);
}
mCreatedIds.add(createdId);
}
break;
case DOCUMENT:
Document doc = (Document) item;
SoapHttpTransport transport = new SoapHttpTransport(zoptions.getUri());
try {
in = StoreManager.getInstance().getContent(doc.getBlob());
String uploadId = zmbx.uploadContentAsStream(name, in, doc.getContentType(), doc.getSize(), 4000, true);
// instead of using convenience method from ZMailbox
// we need to hand marshall the request and set the
// response protocol explicitly to what was requested
// from the client.
Element req = new XMLElement(MailConstants.SAVE_DOCUMENT_REQUEST);
Element edoc = req.addUniqueElement(MailConstants.E_DOC);
edoc.addAttribute(MailConstants.A_NAME, name);
edoc.addAttribute(MailConstants.A_FOLDER, folderStr);
edoc.addAttribute(MailConstants.A_FLAGS, flags);
Element upload = edoc.addElement(MailConstants.E_UPLOAD);
upload.addAttribute(MailConstants.A_ID, uploadId);
transport.setResponseProtocol(mResponseProtocol);
transport.setAuthToken(zat);
Element response = transport.invoke(req);
createdId = response.getElement(MailConstants.E_DOC).getAttribute(MailConstants.A_ID);
} finally {
ByteUtil.closeStream(in);
transport.shutdown();
}
mCreatedIds.add(createdId);
break;
case APPOINTMENT:
case TASK:
CalendarItem cal = (CalendarItem) item;
// private calendar item may not be moved by non-owner unless permission was granted
if (!cal.isPublic()) {
boolean asAdmin = mOpCtxt != null ? mOpCtxt.isUsingAdminPrivileges() : false;
if (!cal.allowPrivateAccess(mAuthenticatedAccount, asAdmin))
throw ServiceException.PERM_DENIED("you do not have permission to move/copy a private calendar item from the current folder/mailbox");
}
// Move the item to remote mailbox using SetAppointmentRequest/SetTaskRequest.
QName qname = (item.getType() == MailItem.Type.TASK ? MailConstants.SET_TASK_REQUEST : MailConstants.SET_APPOINTMENT_REQUEST);
Element request = new Element.XMLElement(qname).addAttribute(MailConstants.A_FOLDER, folderStr).addAttribute(MailConstants.A_FLAGS, flags);
ToXML.encodeAlarmTimes(request, cal);
Invite invDefault = cal.getDefaultInviteOrNull();
// Takeover as organizer if we're doing a MOVE and source mailbox is the organizer.
// Don't takeover in a COPY operation.
boolean takeoverAsOrganizer = false;
boolean blockMove = false;
if (Op.MOVE.equals(mOperation)) {
Invite inv = invDefault;
if (inv == null) {
// no default invite; let's use the first invite
Invite[] invs = cal.getInvites();
if (invs != null && invs.length > 0)
inv = invs[0];
}
takeoverAsOrganizer = inv != null && inv.isOrganizer();
blockMove = takeoverAsOrganizer && inv.hasOtherAttendees();
}
if (blockMove) {
throw MailServiceException.INVALID_REQUEST("This operation requires change of organizer and it is not permitted", null);
}
if (invDefault != null) {
addCalendarPart(request.addUniqueElement(MailConstants.A_DEFAULT), cal, invDefault, zmbx, target, takeoverAsOrganizer);
}
for (Invite inv : cal.getInvites()) {
if (inv == null || inv == invDefault)
continue;
String elem = inv.isCancel() ? MailConstants.E_CAL_CANCEL : MailConstants.E_CAL_EXCEPT;
addCalendarPart(request.addElement(elem), cal, inv, zmbx, target, takeoverAsOrganizer);
}
ToXML.encodeCalendarReplies(request, cal);
createdId = zmbx.invoke(request).getAttribute(MailConstants.A_CAL_ID);
mCreatedIds.add(createdId);
break;
default:
throw MailServiceException.CANNOT_COPY(item.getId());
}
try {
if (deleteOriginal && !mIdFormatter.formatItemId(item).equals(createdId)) {
if (msgs == null) {
mMailbox.delete(mOpCtxt, item.getId(), item.getType());
} else {
for (Message msg : msgs) mMailbox.delete(mOpCtxt, msg.getId(), msg.getType());
}
}
} catch (ServiceException e) {
if (e.getCode() != ServiceException.PERM_DENIED)
throw e;
// something funky happened permissions-wise between the getEffectivePermissions check and here...
ZimbraLog.misc.info("could not delete original item " + item.getId() + "; treating operation as a copy instead");
}
}
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ItemAction method forceRemoteSession.
private Account forceRemoteSession(ZimbraSoapContext zsc, Map<String, Object> context, OperationContext octxt, String op, Element action) throws ServiceException {
// only proxying notification from the user's home-server master session
if (!zsc.isNotificationEnabled()) {
return null;
}
Session session = (Session) context.get(SoapEngine.ZIMBRA_SESSION);
if (session instanceof SoapSession.DelegateSession) {
session = ((SoapSession.DelegateSession) session).getParentSession();
}
if (!(session instanceof SoapSession) || session.getMailbox() == null) {
return null;
}
SoapSession ss = (SoapSession) session;
// only have to worry about operations where things can get created in other mailboxes (regular notification works for all other cases)
if (!op.equals(OP_MOVE) && !op.equals(OP_COPY) && !op.equals(OP_SPAM) && !op.equals(OP_RENAME) && !op.equals(OP_UPDATE)) {
return null;
}
String folderStr = action.getAttribute(MailConstants.A_FOLDER, null);
if (folderStr == null) {
return null;
}
// recursively dereference mountpoints to find ultimate target folder
ItemId iidFolder = new ItemId(folderStr, zsc), iidRequested = iidFolder;
Account owner = null;
int hopCount = 0;
ZAuthToken zat = null;
while (hopCount < ZimbraSoapContext.MAX_HOP_COUNT) {
owner = Provisioning.getInstance().getAccountById(iidFolder.getAccountId());
if (Provisioning.onLocalServer(owner)) {
try {
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(owner);
Folder folder = mbox.getFolderById(octxt, iidFolder.getId());
if (!(folder instanceof Mountpoint))
break;
iidFolder = ((Mountpoint) folder).getTarget();
} catch (ServiceException e) {
// could be a PERM_DENIED, could be something else -- this is not the right place to fail, however
break;
}
} else {
if (zat == null) {
AuthToken at = AuthToken.getCsrfUnsecuredAuthToken(zsc.getAuthToken());
String pxyAuthToken = at.getProxyAuthToken();
zat = pxyAuthToken == null ? at.toZAuthToken() : new ZAuthToken(pxyAuthToken);
}
ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(owner));
zoptions.setNoSession(true);
zoptions.setTargetAccount(owner.getId());
zoptions.setTargetAccountBy(Key.AccountBy.id);
ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
ZFolder zfolder = zmbx.getFolderById(iidFolder.toString(zsc.getAuthtokenAccountId()));
if (!(zfolder instanceof ZMountpoint))
break;
iidFolder = new ItemId(((ZMountpoint) zfolder).getCanonicalRemoteId(), zsc.getAuthtokenAccountId());
}
hopCount++;
}
if (hopCount >= ZimbraSoapContext.MAX_HOP_COUNT) {
throw MailServiceException.TOO_MANY_HOPS(iidRequested);
}
// avoid dereferencing the mountpoint again later on
action.addAttribute(MailConstants.A_FOLDER, iidFolder.toString());
// fault in a session to listen in on the target folder's mailbox
if (iidFolder.belongsTo(session.getAuthenticatedAccountId())) {
return null;
} else if (iidFolder.isLocal()) {
ss.getDelegateSession(iidFolder.getAccountId());
return null;
} else {
try {
proxyRequest(zsc.createElement(MailConstants.NO_OP_REQUEST), context, owner.getId());
return owner;
} catch (ServiceException e) {
return null;
}
}
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class DavContext method getInternalDestinationUrl.
private String getInternalDestinationUrl(String destinationUrl) throws ServiceException, DavException {
UrlComponents uc = UrlNamespace.parseUrl(destinationUrl);
Account targetAcct = Provisioning.getInstance().getAccountByName(uc.user);
if (targetAcct == null)
return destinationUrl;
ZMailbox zmbx = getZMailbox(targetAcct);
ItemId targetRoot = new ItemId("", Mailbox.ID_FOLDER_USER_ROOT);
Pair<ZFolder, String> match = zmbx.getFolderByPathLongestMatch(targetRoot.toString(), uc.path);
ZFolder targetFolder = match.getFirst();
if (targetFolder instanceof ZMountpoint) {
ZMountpoint zmp = (ZMountpoint) targetFolder;
ItemId target = new ItemId(zmp.getOwnerId(), Integer.parseInt(zmp.getRemoteId()));
Account acct = Provisioning.getInstance().getAccountById(zmp.getOwnerId());
ZMailbox targetZmbx = getZMailbox(acct);
ZFolder f = targetZmbx.getFolderById(target.toString());
String extraPath = match.getSecond();
destinationUrl = DavServlet.DAV_PATH + "/" + acct.getName() + f.getPath() + ((extraPath != null) ? "/" + extraPath : "");
}
return destinationUrl;
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class ZFolderTest method defaultView.
@Test
public void defaultView() throws Exception {
String xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='appointment'/>";
ZFolder folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.appointment, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='chat'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.chat, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='contact'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.contact, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='conversation'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.conversation, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='document'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.document, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='message'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.message, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='remote'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.remote, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='search'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.search, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='task'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.task, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='voice'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.voice, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='wiki'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.wiki, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.unknown, folder.getDefaultView());
xml = "<folder id='1' rev='1' s='0' i4next='2' i4ms='1' name='X' ms='1' n='0' l='11' view='XXX'/>";
folder = new ZFolder(Element.parseXML(xml), null, null);
Assert.assertEquals(ZFolder.View.unknown, folder.getDefaultView());
}
use of com.zimbra.client.ZFolder in project zm-mailbox by Zimbra.
the class DavServlet method isProxyRequest.
private boolean isProxyRequest(DavContext ctxt, DavMethod m) throws IOException, DavException, ServiceException {
Provisioning prov = Provisioning.getInstance();
ItemId target = null;
String extraPath = null;
String requestPath = ctxt.getPath();
try {
if (ctxt.getUser() == null) {
return false;
}
if (requestPath == null || requestPath.length() < 2) {
return false;
}
Account account = prov.getAccountByName(ctxt.getUser());
if (account == null) {
return false;
}
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(account);
Pair<Folder, String> match = mbox.getFolderByPathLongestMatch(ctxt.getOperationContext(), Mailbox.ID_FOLDER_USER_ROOT, requestPath);
Folder targetFolder = match.getFirst();
if (!(targetFolder instanceof Mountpoint)) {
return false;
}
Mountpoint mp = (Mountpoint) targetFolder;
target = new ItemId(mp.getOwnerId(), mp.getRemoteId());
extraPath = match.getSecond();
} catch (ServiceException e) {
ZimbraLog.dav.debug("can't get path", e);
return false;
}
// we also don't proxy DELETE on a mountpoint.
if (extraPath == null && (m.getName().equals(PropFind.PROPFIND) && ctxt.getDepth() == DavContext.Depth.zero || m.getName().equals(PropPatch.PROPPATCH) || m.getName().equals(Delete.DELETE))) {
return false;
}
String prefix = ctxt.getPath();
if (extraPath != null) {
prefix = prefix.substring(0, prefix.indexOf(extraPath));
}
prefix = HttpUtil.urlEscape(DAV_PATH + "/" + ctxt.getUser() + prefix);
if (!prefix.endsWith("/")) {
prefix += "/";
}
// make sure the target account exists.
Account acct = prov.getAccountById(target.getAccountId());
if (acct == null) {
return false;
}
Server server = prov.getServer(acct);
if (server == null) {
return false;
}
// get the path to the target mail item
AuthToken authToken = AuthProvider.getAuthToken(ctxt.getAuthAccount());
ZMailbox.Options zoptions = new ZMailbox.Options(authToken.toZAuthToken(), AccountUtil.getSoapUri(acct));
zoptions.setNoSession(true);
zoptions.setTargetAccount(target.getAccountId());
zoptions.setTargetAccountBy(Key.AccountBy.id);
ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
ZFolder f = zmbx.getFolderById("" + target.toString());
if (f == null) {
return false;
}
String path = f.getPath();
String newPrefix = HttpUtil.urlEscape(DAV_PATH + "/" + acct.getName() + f.getPath());
if (ctxt.hasRequestMessage()) {
// replace the path in <href> of the request with the path to the target mail item.
Document req = ctxt.getRequestMessage();
for (Object hrefObj : req.getRootElement().elements(DavElements.E_HREF)) {
if (!(hrefObj instanceof Element)) {
continue;
}
Element href = (Element) hrefObj;
String v = href.getText();
// prefix matching is not as straightforward as we have jetty redirect from /dav to /home/dav.
href.setText(newPrefix + "/" + v.substring(v.lastIndexOf('/') + 1));
}
}
// build proxy request
String url = getProxyUrl(ctxt.getRequest(), server, DAV_PATH) + HttpUtil.urlEscape("/" + acct.getName() + path + "/" + (extraPath == null ? "" : extraPath));
HttpState state = new HttpState();
authToken.encode(state, false, server.getAttr(Provisioning.A_zimbraServiceHostname));
HttpClient client = ZimbraHttpConnectionManager.getInternalHttpConnMgr().newHttpClient();
client.setState(state);
HttpMethod method = m.toHttpMethod(ctxt, url);
method.setRequestHeader(new Header(DavProtocol.HEADER_USER_AGENT, "Zimbra-DAV/" + BuildInfo.VERSION));
if (ZimbraLog.dav.isDebugEnabled()) {
Enumeration<String> headers = ctxt.getRequest().getHeaderNames();
while (headers.hasMoreElements()) {
String hdr = headers.nextElement();
if (!PROXY_REQUEST_HEADERS.contains(hdr) && !IGNORABLE_PROXY_REQUEST_HEADERS.contains(hdr)) {
ZimbraLog.dav.debug("Dropping header(s) with name [%s] from proxy request (not in PROXY_REQUEST_HEADERS)", hdr);
}
}
}
for (String h : PROXY_REQUEST_HEADERS) {
String hval = ctxt.getRequest().getHeader(h);
if (hval != null) {
method.addRequestHeader(h, hval);
}
}
int statusCode = HttpClientUtil.executeMethod(client, method);
if (ZimbraLog.dav.isDebugEnabled()) {
for (Header hval : method.getResponseHeaders()) {
String hdrName = hval.getName();
if (!PROXY_RESPONSE_HEADERS.contains(hdrName) && !IGNORABLE_PROXY_RESPONSE_HEADERS.contains(hdrName)) {
ZimbraLog.dav.debug("Dropping header [%s] from proxy response (not in PROXY_RESPONSE_HEADERS)", hval);
}
}
}
for (String h : PROXY_RESPONSE_HEADERS) {
for (Header hval : method.getResponseHeaders(h)) {
String hdrValue = hval.getValue();
if (DavProtocol.HEADER_LOCATION.equals(h)) {
int pfxLastSlashPos = prefix.lastIndexOf('/');
int lastSlashPos = hdrValue.lastIndexOf('/');
if ((lastSlashPos > 0) && (pfxLastSlashPos > 0)) {
hdrValue = prefix.substring(0, pfxLastSlashPos) + hdrValue.substring(lastSlashPos);
ZimbraLog.dav.debug("Original [%s] from proxy response new value '%s'", hval, hdrValue);
}
}
ctxt.getResponse().addHeader(h, hdrValue);
}
}
ctxt.getResponse().setStatus(statusCode);
ctxt.setStatus(statusCode);
try (InputStream in = method.getResponseBodyAsStream()) {
switch(statusCode) {
case DavProtocol.STATUS_MULTI_STATUS:
// rewrite the <href> element in the response to point to local mountpoint.
try {
Document response = W3cDomUtil.parseXMLToDom4jDocUsingSecureProcessing(in);
Element top = response.getRootElement();
for (Object responseObj : top.elements(DavElements.E_RESPONSE)) {
if (!(responseObj instanceof Element)) {
continue;
}
Element href = ((Element) responseObj).element(DavElements.E_HREF);
String v = href.getText();
v = URLDecoder.decode(v);
// Bug:106438, because v contains URL encoded value(%40) for '@' the comparison fails
if (v.startsWith(newPrefix)) {
href.setText(prefix + v.substring(newPrefix.length() + 1));
}
}
if (ZimbraLog.dav.isDebugEnabled()) {
ZimbraLog.dav.debug("PROXY RESPONSE:\n%s", new String(DomUtil.getBytes(response), "UTF-8"));
}
DomUtil.writeDocumentToStream(response, ctxt.getResponse().getOutputStream());
ctxt.responseSent();
} catch (XmlParseException e) {
ZimbraLog.dav.warn("proxy request failed", e);
return false;
}
break;
default:
if (in != null) {
ByteUtil.copy(in, true, ctxt.getResponse().getOutputStream(), false);
}
ctxt.responseSent();
break;
}
return true;
}
}
Aggregations