use of com.zimbra.common.util.ByteUtil.PositionInputStream in project zm-mailbox by Zimbra.
the class UUEncodeConverter method visitMessage.
@Override
protected boolean visitMessage(MimeMessage mm, VisitPhase visitKind) throws MessagingException {
// do the decode in the exit phase
if (visitKind != VisitPhase.VISIT_END)
return false;
MimeMultipart mmp = null;
try {
// only check "text/plain" parts for uudecodeable attachments
if (!mm.isMimeType(MimeConstants.CT_TEXT_PLAIN))
return false;
// don't check transfer-encoded parts for uudecodeable attachments
String cte = mm.getHeader("Content-Transfer-Encoding", null);
if (cte != null) {
cte = cte.trim().toLowerCase();
if (!cte.equals(MimeConstants.ET_7BIT) && !cte.equals(MimeConstants.ET_8BIT) && !cte.equals(MimeConstants.ET_BINARY))
return false;
}
List<UUDecodedFile> uufiles = null;
// go through top-level text/plain part and extract uuencoded files
PositionInputStream is = null;
long size;
try {
is = new PositionInputStream(new BufferedInputStream(mm.getInputStream()));
for (int c = is.read(); c != -1; ) {
long start = is.getPosition() - 1;
// check for uuencode header: "begin NNN filename"
if (c == 'b' && (c = is.read()) == 'e' && (c = is.read()) == 'g' && (c = is.read()) == 'i' && (c = is.read()) == 'n' && ((c = is.read()) == ' ' || c == '\t') && Character.isDigit((c = is.read())) && Character.isDigit(c = is.read()) && Character.isDigit(c = is.read()) && ((c = is.read()) == ' ' || c == '\t')) {
StringBuilder sb = new StringBuilder();
while ((c = is.read()) != '\r' && c != '\n' && c != -1) sb.append((char) c);
String filename = FileUtil.trimFilename(sb.toString().trim());
if (c != -1 && filename.length() > 0) {
if (uufiles == null)
uufiles = new ArrayList<UUDecodedFile>(3);
try {
uufiles.add(new UUDecodedFile(is, filename, start));
// check to make sure that the caller's OK with altering the message
if (uufiles.size() == 1 && mCallback != null && !mCallback.onModification())
return false;
} catch (IOException ioe) {
}
}
}
// skip to the beginning of the next line
while (c != '\r' && c != '\n' && c != -1) c = is.read();
while (c == '\r' || c == '\n') c = is.read();
}
size = is.getPosition();
} finally {
ByteUtil.closeStream(is);
}
if (uufiles == null || uufiles.isEmpty())
return false;
// create MimeParts for the extracted files
mmp = new ZMimeMultipart("mixed");
for (UUDecodedFile uu : uufiles) {
MimeBodyPart mbp = new ZMimeBodyPart();
mbp.setHeader("Content-Type", uu.getContentType());
mbp.setHeader("Content-Disposition", new ContentDisposition(Part.ATTACHMENT).setParameter("filename", uu.getFilename()).toString());
mbp.setDataHandler(new DataHandler(uu.getDataSource()));
mmp.addBodyPart(mbp);
size -= uu.getEndOffset() - uu.getStartOffset();
}
// take the remaining text and put it in as the first "related" part
InputStream isOrig = null;
try {
isOrig = mm.getInputStream();
long offset = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream((int) size);
byte[] buffer = new byte[8192];
for (UUDecodedFile uu : uufiles) {
long count = uu.getStartOffset() - offset, numRead;
while (count > 0 && (numRead = isOrig.read(buffer, 0, (int) Math.min(count, 8192))) >= 0) {
baos.write(buffer, 0, (int) numRead);
count -= numRead;
}
isOrig.skip(uu.getEndOffset() - uu.getStartOffset());
offset = uu.getEndOffset();
}
ByteUtil.copy(isOrig, true, baos, true);
MimeBodyPart mbp = new ZMimeBodyPart();
mbp.setDataHandler(new DataHandler(new ByteArrayDataSource(baos.toByteArray(), MimeConstants.CT_TEXT_PLAIN)));
mmp.addBodyPart(mbp, 0);
} finally {
ByteUtil.closeStream(isOrig);
}
} catch (MessagingException e) {
ZimbraLog.extensions.warn("exception while uudecoding message part; skipping part", e);
return false;
} catch (IOException e) {
ZimbraLog.extensions.warn("exception while uudecoding message part; skipping part", e);
return false;
}
// replace the top-level part with a new multipart/related
mm.setContent(mmp);
mm.setHeader("Content-Type", mmp.getContentType() + "; generated=true");
return true;
}
Aggregations