Search in sources :

Example 1 with PositionInputStream

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;
}
Also used : ZMimeBodyPart(com.zimbra.common.zmime.ZMimeBodyPart) MessagingException(javax.mail.MessagingException) BufferedInputStream(java.io.BufferedInputStream) PositionInputStream(com.zimbra.common.util.ByteUtil.PositionInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) IOException(java.io.IOException) DataHandler(javax.activation.DataHandler) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ContentDisposition(com.zimbra.common.mime.ContentDisposition) MimeMultipart(javax.mail.internet.MimeMultipart) ZMimeMultipart(com.zimbra.common.zmime.ZMimeMultipart) BufferedInputStream(java.io.BufferedInputStream) PositionInputStream(com.zimbra.common.util.ByteUtil.PositionInputStream) ZMimeMultipart(com.zimbra.common.zmime.ZMimeMultipart) ZMimeBodyPart(com.zimbra.common.zmime.ZMimeBodyPart) MimeBodyPart(javax.mail.internet.MimeBodyPart) ByteArrayDataSource(javax.mail.util.ByteArrayDataSource)

Aggregations

ContentDisposition (com.zimbra.common.mime.ContentDisposition)1 PositionInputStream (com.zimbra.common.util.ByteUtil.PositionInputStream)1 ZMimeBodyPart (com.zimbra.common.zmime.ZMimeBodyPart)1 ZMimeMultipart (com.zimbra.common.zmime.ZMimeMultipart)1 BufferedInputStream (java.io.BufferedInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 ArrayList (java.util.ArrayList)1 DataHandler (javax.activation.DataHandler)1 MessagingException (javax.mail.MessagingException)1 MimeBodyPart (javax.mail.internet.MimeBodyPart)1 MimeMultipart (javax.mail.internet.MimeMultipart)1 ByteArrayDataSource (javax.mail.util.ByteArrayDataSource)1