use of com.zimbra.common.mime.ContentType in project zm-mailbox by Zimbra.
the class ProxyServlet method doProxy.
private void doProxy(HttpServletRequest req, HttpServletResponse resp) throws IOException {
ZimbraLog.clearContext();
boolean isAdmin = isAdminRequest(req);
AuthToken authToken = isAdmin ? getAdminAuthTokenFromCookie(req, resp, true) : getAuthTokenFromCookie(req, resp, true);
if (authToken == null) {
String zAuthToken = req.getParameter(QP_ZAUTHTOKEN);
if (zAuthToken != null) {
try {
authToken = AuthProvider.getAuthToken(zAuthToken);
if (authToken.isExpired()) {
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "authtoken expired");
return;
}
} catch (AuthTokenException e) {
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "unable to parse authtoken");
return;
}
}
}
if (authToken == null) {
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "no authtoken cookie");
return;
}
if (!authToken.isRegistered()) {
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "authtoken is invalid");
return;
}
if (isAdmin && !authToken.isAdmin()) {
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "permission denied");
return;
}
// get the posted body before the server read and parse them.
byte[] body = copyPostedData(req);
// sanity check
String target = req.getParameter(TARGET_PARAM);
if (target == null) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
// check for permission
URL url = new URL(target);
if (!isAdmin && !checkPermissionOnTarget(url, authToken)) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
// determine whether to return the target inline or store it as an upload
String uploadParam = req.getParameter(UPLOAD_PARAM);
boolean asUpload = uploadParam != null && (uploadParam.equals("1") || uploadParam.equalsIgnoreCase("true"));
HttpRequestBase method = null;
try {
HttpClientBuilder clientBuilder = ZimbraHttpConnectionManager.getExternalHttpConnMgr().newHttpClient();
HttpProxyUtil.configureProxy(clientBuilder);
String reqMethod = req.getMethod();
if (reqMethod.equalsIgnoreCase("GET")) {
method = new HttpGet(target);
} else if (reqMethod.equalsIgnoreCase("POST")) {
HttpPost post = new HttpPost(target);
if (body != null)
post.setEntity(new ByteArrayEntity(body, org.apache.http.entity.ContentType.create(req.getContentType())));
method = post;
} else if (reqMethod.equalsIgnoreCase("PUT")) {
HttpPut put = new HttpPut(target);
if (body != null)
put.setEntity(new ByteArrayEntity(body, org.apache.http.entity.ContentType.create(req.getContentType())));
method = put;
} else if (reqMethod.equalsIgnoreCase("DELETE")) {
method = new HttpDelete(target);
} else {
ZimbraLog.zimlet.info("unsupported request method: " + reqMethod);
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
// handle basic auth
String auth, user, pass;
auth = req.getParameter(AUTH_PARAM);
user = req.getParameter(USER_PARAM);
pass = req.getParameter(PASS_PARAM);
if (auth != null && user != null && pass != null) {
if (!auth.equals(AUTH_BASIC)) {
ZimbraLog.zimlet.info("unsupported auth type: " + auth);
resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
CredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, pass));
clientBuilder.setDefaultCredentialsProvider(provider);
}
Enumeration headers = req.getHeaderNames();
while (headers.hasMoreElements()) {
String hdr = (String) headers.nextElement();
ZimbraLog.zimlet.debug("incoming: " + hdr + ": " + req.getHeader(hdr));
if (canProxyHeader(hdr)) {
ZimbraLog.zimlet.debug("outgoing: " + hdr + ": " + req.getHeader(hdr));
if (hdr.equalsIgnoreCase("x-host"))
method.setHeader("Host", req.getHeader(hdr));
else
method.addHeader(hdr, req.getHeader(hdr));
}
}
HttpResponse httpResp = null;
try {
if (!(reqMethod.equalsIgnoreCase("POST") || reqMethod.equalsIgnoreCase("PUT"))) {
clientBuilder.setRedirectStrategy(new DefaultRedirectStrategy());
}
HttpClient client = clientBuilder.build();
httpResp = HttpClientUtil.executeMethod(client, method);
} catch (HttpException ex) {
ZimbraLog.zimlet.info("exception while proxying " + target, ex);
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
int status = httpResp.getStatusLine() == null ? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : httpResp.getStatusLine().getStatusCode();
// workaround for Alexa Thumbnails paid web service, which doesn't bother to return a content-type line
Header ctHeader = httpResp.getFirstHeader("Content-Type");
String contentType = ctHeader == null || ctHeader.getValue() == null ? DEFAULT_CTYPE : ctHeader.getValue();
// getEntity may return null if no response body (e.g. HTTP 204)
InputStream targetResponseBody = null;
HttpEntity targetResponseEntity = httpResp.getEntity();
if (targetResponseEntity != null) {
targetResponseBody = targetResponseEntity.getContent();
}
if (asUpload) {
String filename = req.getParameter(FILENAME_PARAM);
if (filename == null || filename.equals(""))
filename = new ContentType(contentType).getParameter("name");
if ((filename == null || filename.equals("")) && httpResp.getFirstHeader("Content-Disposition") != null)
filename = new ContentDisposition(httpResp.getFirstHeader("Content-Disposition").getValue()).getParameter("filename");
if (filename == null || filename.equals(""))
filename = "unknown";
List<Upload> uploads = null;
if (targetResponseBody != null) {
try {
Upload up = FileUploadServlet.saveUpload(targetResponseBody, filename, contentType, authToken.getAccountId());
uploads = Arrays.asList(up);
} catch (ServiceException e) {
if (e.getCode().equals(MailServiceException.UPLOAD_REJECTED))
status = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE;
else
status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
}
resp.setStatus(status);
FileUploadServlet.sendResponse(resp, status, req.getParameter(FORMAT_PARAM), null, uploads, null);
} else {
resp.setStatus(status);
resp.setContentType(contentType);
for (Header h : httpResp.getAllHeaders()) if (canProxyHeader(h.getName()))
resp.addHeader(h.getName(), h.getValue());
if (targetResponseBody != null)
ByteUtil.copy(targetResponseBody, true, resp.getOutputStream(), true);
}
} finally {
if (method != null)
method.releaseConnection();
}
}
use of com.zimbra.common.mime.ContentType in project zm-mailbox by Zimbra.
the class ParseMimeMessage method attachUpload.
private static void attachUpload(MimeMultipart mmp, Upload up, String contentID, ParseMessageContext ctxt, ContentType ctypeOverride, String contentDescription, String contentDisposition) throws ServiceException, MessagingException {
// make sure we haven't exceeded the max size
ctxt.incrementSize("upload " + up.getName(), (long) (up.getSize() * 1.33));
// scan upload for viruses
StringBuffer info = new StringBuffer();
UploadScanner.Result result = UploadScanner.accept(up, info);
if (result == UploadScanner.REJECT) {
throw MailServiceException.UPLOAD_REJECTED(up.getName(), info.toString());
} else if (result == UploadScanner.ERROR) {
throw MailServiceException.SCAN_ERROR(up.getName());
}
String filename = up.getName();
// create the part and override the DataSource's default ctype, if required
MimeBodyPart mbp = new ForceBase64MimeBodyPart();
UploadDataSource uds = new UploadDataSource(up);
if (ctypeOverride != null && !ctypeOverride.equals("")) {
uds.setContentType(ctypeOverride);
}
mbp.setDataHandler(new DataHandler(uds));
// set headers -- ctypeOverride non-null has magical properties that I'm going to regret tomorrow
ContentType ctype = ctypeOverride;
ContentDisposition cdisp;
if (Part.INLINE.equalsIgnoreCase(contentDisposition)) {
cdisp = new ContentDisposition(Part.INLINE, ctxt.use2231);
} else {
cdisp = new ContentDisposition(Part.ATTACHMENT, ctxt.use2231);
}
if (ctype == null) {
ctype = new ContentType(up.getContentType() == null ? MimeConstants.CT_APPLICATION_OCTET_STREAM : up.getContentType());
ctype.cleanup().setParameter("name", filename);
cdisp.setParameter("filename", filename);
}
mbp.setHeader("Content-Type", ctype.setCharset(ctxt.defaultCharset).toString());
mbp.setHeader("Content-Disposition", cdisp.setCharset(ctxt.defaultCharset).toString());
if (contentDescription != null) {
mbp.setHeader("Content-Description", contentDescription);
}
if (ctype.getContentType().equals(MimeConstants.CT_APPLICATION_PDF)) {
mbp.setHeader("Content-Transfer-Encoding", "base64");
}
mbp.setContentID(contentID);
// add to the parent part
mmp.addBodyPart(mbp);
}
use of com.zimbra.common.mime.ContentType in project zm-mailbox by Zimbra.
the class ParseMimeMessage method attachMessage.
@SuppressWarnings("unchecked")
private static void attachMessage(MimeMultipart mmp, ItemId iid, String contentID, ParseMessageContext ctxt, boolean attachMessageFromCache) throws MessagingException, ServiceException {
if (!iid.isLocal()) {
attachRemoteItem(mmp, iid, contentID, ctxt, Collections.EMPTY_MAP, new ContentType(MimeConstants.CT_MESSAGE_RFC822));
return;
}
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(iid.getAccountId());
Message msg = mbox.getMessageById(ctxt.octxt, iid.getId());
ctxt.incrementSize("attached message", msg.getSize());
MimeBodyPart mbp = new ZMimeBodyPart();
if (attachMessageFromCache && mbox.getAccount().isFeatureSMIMEEnabled() && (Mime.isEncrypted(msg.getMimeMessage(false).getContentType()) || Mime.isPKCS7Signed(msg.getMimeMessage(false).getContentType()))) {
MimeMessage cachedMimeMessage = msg.getMimeMessage(true);
mbp.setContent(cachedMimeMessage, MimeConstants.CT_MESSAGE_RFC822);
} else {
mbp.setDataHandler(new DataHandler(new MailboxBlobDataSource(msg.getBlob())));
mbp.setHeader("Content-Type", MimeConstants.CT_MESSAGE_RFC822);
mbp.setHeader("Content-Disposition", Part.ATTACHMENT);
}
mbp.setContentID(contentID);
mmp.addBodyPart(mbp);
}
use of com.zimbra.common.mime.ContentType in project zm-mailbox by Zimbra.
the class TnefConverter method expandTNEF.
/**
* Performs the TNEF->MIME conversion on any TNEF body parts that
* make up the given message.
* @throws ServiceException
*/
private MimeMultipart expandTNEF(MimeBodyPart bp) throws MessagingException, IOException {
if (!TNEFUtils.isTNEFMimeType(bp.getContentType()))
return null;
MimeMessage converted = null;
// convert TNEF to a MimeMessage and remove it from the parent
InputStream is = null;
try {
TNEFInputStream tnefis = new TNEFInputStream(is = bp.getInputStream());
converted = TNEFMime.convert(JMSession.getSession(), tnefis);
// XXX bburtin: nasty hack. Don't handle OOME since JTNEF can allocate a huge byte
// array when the TNEF file is malformed. See bug 42649.
// } catch (OutOfMemoryError e) {
// Zimbra.halt("Ran out of memory while expanding TNEF attachment", e);
} catch (Throwable t) {
ZimbraLog.extensions.warn("Conversion failed. TNEF attachment will not be expanded.", t);
return null;
} finally {
ByteUtil.closeStream(is);
}
Object convertedContent = converted.getContent();
if (!(convertedContent instanceof MimeMultipart)) {
ZimbraLog.extensions.debug("TNEF attachment doesn't contain valid MimeMultiPart");
return null;
}
MimeMultipart convertedMulti = (MimeMultipart) convertedContent;
// make sure that all the attachments are marked as attachments
for (int i = 0; i < convertedMulti.getCount(); i++) {
BodyPart subpart = convertedMulti.getBodyPart(i);
if (subpart.getHeader("Content-Disposition") == null)
subpart.setHeader("Content-Disposition", Part.ATTACHMENT);
}
// Create a MimeBodyPart for the converted data. Currently we're throwing
// away the top-level message because its content shows up as blank after
// the conversion.
MimeBodyPart convertedPart = new ZMimeBodyPart();
convertedPart.setContent(convertedMulti);
// If the TNEF object contains calendar data, create an iCalendar version.
MimeBodyPart icalPart = null;
if (DebugConfig.enableTnefToICalendarConversion) {
try {
TnefToICalendar calConverter = new DefaultTnefToICalendar();
ZCalendar.DefaultContentHandler icalHandler = new ZCalendar.DefaultContentHandler();
if (calConverter.convert(mMimeMessage, bp.getInputStream(), icalHandler)) {
if (icalHandler.getNumCals() > 0) {
List<ZVCalendar> cals = icalHandler.getCals();
Writer writer = new StringWriter(1024);
ICalTok method = null;
for (ZVCalendar cal : cals) {
cal.toICalendar(writer);
if (method == null)
method = cal.getMethod();
}
writer.close();
icalPart = new ZMimeBodyPart();
icalPart.setText(writer.toString());
ContentType ct = new ContentType(MimeConstants.CT_TEXT_CALENDAR);
ct.setCharset(MimeConstants.P_CHARSET_UTF8);
if (method != null)
ct.setParameter("method", method.toString());
icalPart.setHeader("Content-Type", ct.toString());
}
}
} catch (ServiceException e) {
throw new MessagingException("TNEF to iCalendar conversion failure: " + e.getMessage(), e);
} catch (Throwable t) {
// don't allow TNEF errors to crash server
ZimbraLog.extensions.warn("Failed to convert TNEF to iCal", t);
throw new MessagingException("TNEF to iCalendar conversion failure");
}
}
// create a multipart/alternative for the TNEF and its MIME version
MimeMultipart altMulti = new ZMimeMultipart("alternative");
// altMulti.addBodyPart(bp);
altMulti.addBodyPart(convertedPart);
if (icalPart != null)
altMulti.addBodyPart(icalPart);
return altMulti;
}
use of com.zimbra.common.mime.ContentType in project zm-mailbox by Zimbra.
the class Mime method main.
public static void main(String[] args) throws MessagingException, IOException {
String s = URLDecoder.decode("Zimbra%20日本語化の考慮点.txt", "utf-8");
System.out.println(s);
System.out.println(expandNumericCharacterReferences("Zimbra%20日本語化の考慮点.txt@&;&#;&#x;&#༤7"));
MimeMessage mm = new FixedMimeMessage(JMSession.getSession(), new SharedFileInputStream("C:\\Temp\\mail\\24245"));
InputStream is = new RawContentMultipartDataSource(mm, new ContentType(mm.getContentType())).getInputStream();
int num;
byte[] buf = new byte[1024];
while ((num = is.read(buf)) != -1) {
System.out.write(buf, 0, num);
}
}
Aggregations