Search in sources :

Example 1 with SharedInputStream

use of javax.mail.internet.SharedInputStream in project zm-mailbox by Zimbra.

the class ParsedMessage method init.

/**
 * Runs MIME mutators and converters, initializes {@link #mMimeMessage}, {@link #mExpandedMessage},
 * {@link #mFileInputStream} and {@link #mReceivedDate} based on message content.
 */
private void init(Long receivedDate, boolean indexAttachments) throws MessagingException, IOException {
    this.indexAttachments = indexAttachments;
    if (mimeMessage == null) {
        if (sharedStream == null) {
            throw new IOException("Content stream has not been initialized.");
        }
        if (!(sharedStream instanceof SharedInputStream)) {
            InputStream in = sharedStream;
            sharedStream = null;
            byte[] content = ByteUtil.getContent(in, 0);
            sharedStream = new SharedByteArrayInputStream(content);
        }
        mimeMessage = expandedMessage = new Mime.FixedMimeMessage(JMSession.getSession(), sharedStream);
    }
    // Run mutators.
    try {
        runMimeMutators();
    } catch (Exception e) {
        wasMutated = false;
        // Original stream has been read, so get a new one.
        mimeMessage = expandedMessage = new Mime.FixedMimeMessage(JMSession.getSession(), getRawInputStream());
    }
    if (wasMutated()) {
        // Original data is now invalid.
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        mimeMessage.writeTo(buffer);
        byte[] content = buffer.toByteArray();
        ByteUtil.closeStream(sharedStream);
        sharedStream = new SharedByteArrayInputStream(content);
        mimeMessage = expandedMessage = null;
        mimeMessage = expandedMessage = new Mime.FixedMimeMessage(JMSession.getSession(), sharedStream);
    }
    ExpandMimeMessage expand = new ExpandMimeMessage(mimeMessage);
    try {
        expand.expand();
        expandedMessage = expand.getExpanded();
    } catch (Exception e) {
        // roll back if necessary
        expandedMessage = mimeMessage;
        LOG.warn("exception while converting message; message will be analyzed unconverted", e);
    }
    // must set received-date before Lucene document is initialized
    if (receivedDate == null) {
        receivedDate = getZimbraDateHeader(mimeMessage);
    }
    setReceivedDate(receivedDate);
}
Also used : GZIPInputStream(java.util.zip.GZIPInputStream) SharedInputStream(javax.mail.internet.SharedInputStream) SharedByteArrayInputStream(javax.mail.util.SharedByteArrayInputStream) BlobInputStream(com.zimbra.cs.store.BlobInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) SharedInputStream(javax.mail.internet.SharedInputStream) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MessagingException(javax.mail.MessagingException) ParseException(java.text.ParseException) AddressException(javax.mail.internet.AddressException) ServiceException(com.zimbra.common.service.ServiceException) IOException(java.io.IOException) ConversionException(com.zimbra.cs.convert.ConversionException) ObjectHandlerException(com.zimbra.cs.object.ObjectHandlerException) SharedByteArrayInputStream(javax.mail.util.SharedByteArrayInputStream)

Example 2 with SharedInputStream

use of javax.mail.internet.SharedInputStream in project zm-mailbox by Zimbra.

the class ParsedContact method init.

private void init(Map<String, ? extends Object> fields, InputStream in) throws ServiceException {
    if (fields == null) {
        throw ServiceException.INVALID_REQUEST("contact must have fields", null);
    }
    // Initialized shared stream.
    try {
        if (in instanceof SharedInputStream) {
            sharedStream = in;
        } else if (in != null) {
            byte[] content = ByteUtil.getContent(in, 1024);
            sharedStream = new SharedByteArrayInputStream(content);
        }
    } catch (IOException e) {
        throw MailServiceException.MESSAGE_PARSE_ERROR(e);
    }
    // Initialize fields.
    Map<String, String> map = new HashMap<String, String>();
    for (Map.Entry<String, ? extends Object> entry : fields.entrySet()) {
        String key = StringUtil.stripControlCharacters(entry.getKey());
        String value = null;
        if (entry.getValue() instanceof String[]) {
            // encode multi value attributes as JSONObject
            try {
                value = Contact.encodeMultiValueAttr((String[]) entry.getValue());
            } catch (JSONException e) {
                ZimbraLog.index.warn("Error encoding multi valued attribute " + key, e);
            }
        } else if (entry.getValue() instanceof String) {
            value = StringUtil.stripControlCharacters((String) entry.getValue());
        } else if (entry.getValue() instanceof ContactGroup) {
            value = ((ContactGroup) entry.getValue()).encode();
        }
        if (key != null && !key.trim().isEmpty() && !Strings.isNullOrEmpty(value)) {
            if (key.length() > ContactConstants.MAX_FIELD_NAME_LENGTH) {
                throw ServiceException.INVALID_REQUEST("too big filed name", null);
            } else if (value.length() > ContactConstants.MAX_FIELD_VALUE_LENGTH) {
                throw MailServiceException.CONTACT_TOO_BIG(ContactConstants.MAX_FIELD_VALUE_LENGTH, value.length());
            }
            map.put(key, value);
        }
    }
    if (map.isEmpty()) {
        throw ServiceException.INVALID_REQUEST("contact must have fields", null);
    } else if (map.size() > ContactConstants.MAX_FIELD_COUNT) {
        throw ServiceException.INVALID_REQUEST("too many fields", null);
    }
    contactFields = map;
    // Initialize attachments.
    if (sharedStream != null) {
        InputStream contentStream = null;
        try {
            // Parse attachments.
            contentStream = getContentStream();
            contactAttachments = parseBlob(contentStream);
            for (Attachment attach : contactAttachments) {
                contactFields.remove(attach.getName());
            }
            initializeSizeAndDigest();
        } catch (MessagingException me) {
            throw MailServiceException.MESSAGE_PARSE_ERROR(me);
        } catch (IOException ioe) {
            throw MailServiceException.MESSAGE_PARSE_ERROR(ioe);
        } finally {
            ByteUtil.closeStream(contentStream);
        }
    }
}
Also used : HashMap(java.util.HashMap) MessagingException(javax.mail.MessagingException) SharedInputStream(javax.mail.internet.SharedInputStream) SharedByteArrayInputStream(javax.mail.util.SharedByteArrayInputStream) InputStream(java.io.InputStream) JSONException(org.json.JSONException) Attachment(com.zimbra.cs.mailbox.Contact.Attachment) IOException(java.io.IOException) SharedByteArrayInputStream(javax.mail.util.SharedByteArrayInputStream) SharedInputStream(javax.mail.internet.SharedInputStream) ContactGroup(com.zimbra.cs.mailbox.ContactGroup) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with SharedInputStream

use of javax.mail.internet.SharedInputStream in project zm-mailbox by Zimbra.

the class TestBlobInputStream method runBlobInputStreamTest.

public void runBlobInputStreamTest() throws Exception {
    String CONTENT = "0123456789";
    createFile(CONTENT);
    BlobInputStream in = new BlobInputStream(mFile, mFile.length());
    // Test reading all content
    String read = getContent(in, 100);
    assertEquals(CONTENT, read);
    checkEof(in);
    in.close();
    // Test reading beginning and end
    in = new BlobInputStream(mFile, mFile.length());
    assertEquals("01234", getContent(in, 5));
    assertEquals("56789", getContent(in, 100));
    checkEof(in);
    in.close();
    // Test invalid start/end
    try {
        in = new BlobInputStream(mFile, mFile.length(), 6L, 5L);
        fail("Test with start=6 and end=5 should not have succeeded.");
    } catch (IOException e) {
    }
    // Test skip
    in = new BlobInputStream(mFile, mFile.length());
    assertEquals(2, in.skip(2));
    assertEquals("23", getContent(in, 2));
    assertEquals(3, in.skip(3));
    assertEquals("7", getContent(in, 1));
    assertEquals(2, in.skip(1000));
    checkEof(in);
    in.close();
    // Test mark
    in = new BlobInputStream(mFile, mFile.length());
    assertTrue(in.markSupported());
    boolean success = true;
    try {
        in.reset();
    } catch (IOException e) {
        success = false;
    }
    assertFalse("reset() should not have succeeded", success);
    assertEquals("012", getContent(in, 3));
    in.mark(3);
    assertEquals("34", getContent(in, 2));
    in.reset();
    assertEquals("34", getContent(in, 2));
    assertEquals("56", getContent(in, 2));
    success = true;
    try {
        in.reset();
    } catch (IOException e) {
        success = false;
    }
    assertFalse("reset() should not have succeeded", success);
    in.close();
    // Test reading a byte array with an offset.
    in = new BlobInputStream(mFile, mFile.length());
    byte[] buf = new byte[5];
    for (int i = 0; i < 5; i++) {
        buf[i] = 57;
    }
    int numRead = in.read(buf, 3, 2);
    assertTrue("Unexpected number of bytes read: " + numRead, numRead == 1 || numRead == 2);
    int[] untouchedIndexes = null;
    if (numRead == 1) {
        assertEquals((byte) '0', buf[3]);
        untouchedIndexes = new int[] { 0, 1, 2, 4 };
    }
    if (numRead == 2) {
        assertEquals((byte) '0', buf[3]);
        assertEquals((byte) '1', buf[4]);
        untouchedIndexes = new int[] { 0, 1, 2 };
    }
    for (int i : untouchedIndexes) {
        assertEquals("Unexpected value at index " + i, 57, buf[i]);
    }
    in.close();
    // Test reading into a byte array.
    in = new BlobInputStream(mFile, mFile.length());
    in.read();
    in.read();
    numRead = in.read(buf);
    assertTrue(numRead > 0);
    assertTrue(numRead <= 5);
    byte[] test = new byte[numRead];
    System.arraycopy(buf, 0, test, 0, numRead);
    assertTrue("23456".startsWith(new String(test)));
    in.close();
    // Test substream - all content
    InputStream sub = in.newStream(0, CONTENT.length());
    assertEquals(CONTENT, getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream beginning
    sub = in.newStream(0, 5);
    assertEquals("01234", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream end
    sub = in.newStream(5, 10);
    assertEquals("56789", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    sub = in.newStream(5, -1);
    assertEquals("56789", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream past EOF
    assertEquals(null, in.newStream(5, 11));
    // Test substream middle
    sub = in.newStream(3, 6);
    assertEquals("345", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream position
    sub = in.newStream(3, 6);
    assertEquals(0, ((SharedInputStream) sub).getPosition());
    sub.read(new byte[2]);
    assertEquals(2, ((SharedInputStream) sub).getPosition());
    sub.close();
    // Test sub-substream
    InputStream subsub = ((BlobInputStream) sub).newStream(1, 3);
    assertEquals("45", getContent(subsub, 100));
    // Test position after reading 1 character
    in.close();
    in = new BlobInputStream(mFile, mFile.length());
    assertEquals(0, in.getPosition());
    in.read();
    assertEquals(1, in.getPosition());
    in.close();
    // Test reading byte arrays until the end of the file
    in = new BlobInputStream(mFile, mFile.length());
    buf = new byte[4];
    while ((numRead = in.read(buf)) >= 0) {
    }
    in.close();
    mFile.delete();
}
Also used : BlobInputStream(com.zimbra.cs.store.BlobInputStream) SharedInputStream(javax.mail.internet.SharedInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) BlobInputStream(com.zimbra.cs.store.BlobInputStream)

Example 4 with SharedInputStream

use of javax.mail.internet.SharedInputStream in project zm-mailbox by Zimbra.

the class ZSharedFileInputStreamTest method bis.

@Test
public void bis() throws Exception {
    final String CONTENT = "0123456789";
    File file = createFile(CONTENT);
    ZSharedFileInputStream in = new ZSharedFileInputStream(file);
    // Test reading all content
    String read = getContent(in, 100);
    Assert.assertEquals(CONTENT, read);
    checkEof(in);
    in.close();
    // Test reading beginning and end
    in = new ZSharedFileInputStream(file);
    Assert.assertEquals("01234", getContent(in, 5));
    Assert.assertEquals("56789", getContent(in, 100));
    checkEof(in);
    in.close();
    // Test invalid start/end
    try {
        in = new ZSharedFileInputStream(file, 6L, 5L);
        Assert.fail("Test with start=6 and end=5 should not have succeeded.");
    } catch (AssertionError e) {
    }
    // Test skip
    in = new ZSharedFileInputStream(file);
    Assert.assertEquals(2, in.skip(2));
    Assert.assertEquals("23", getContent(in, 2));
    Assert.assertEquals(3, in.skip(3));
    Assert.assertEquals("7", getContent(in, 1));
    Assert.assertEquals(2, in.skip(1000));
    checkEof(in);
    in.close();
    // Test mark
    in = new ZSharedFileInputStream(file);
    Assert.assertTrue(in.markSupported());
    try {
        in.reset();
        Assert.fail("reset() should not have succeeded");
    } catch (IOException e) {
    }
    Assert.assertEquals("012", getContent(in, 3));
    in.mark(3);
    Assert.assertEquals("34", getContent(in, 2));
    in.reset();
    Assert.assertEquals("34", getContent(in, 2));
    Assert.assertEquals("56", getContent(in, 2));
    try {
        in.reset();
    } catch (IOException e) {
        Assert.fail("reset() should not have succeeded");
    }
    in.close();
    // Test reading a byte array with an offset.
    in = new ZSharedFileInputStream(file);
    byte[] buf = new byte[5];
    for (int i = 0; i < 5; i++) {
        buf[i] = 57;
    }
    int numRead = in.read(buf, 3, 2);
    Assert.assertTrue("Unexpected number of bytes read: " + numRead, numRead == 1 || numRead == 2);
    int[] untouchedIndexes = null;
    if (numRead == 1) {
        Assert.assertEquals((byte) '0', buf[3]);
        untouchedIndexes = new int[] { 0, 1, 2, 4 };
    } else if (numRead == 2) {
        Assert.assertEquals((byte) '0', buf[3]);
        Assert.assertEquals((byte) '1', buf[4]);
        untouchedIndexes = new int[] { 0, 1, 2 };
    }
    for (int i : untouchedIndexes) {
        Assert.assertEquals("Unexpected value at index " + i, 57, buf[i]);
    }
    in.close();
    // Test reading into a byte array.
    in = new ZSharedFileInputStream(file);
    in.read();
    in.read();
    numRead = in.read(buf);
    Assert.assertTrue(numRead > 0);
    Assert.assertTrue(numRead <= 5);
    byte[] test = new byte[numRead];
    System.arraycopy(buf, 0, test, 0, numRead);
    Assert.assertTrue("23456".startsWith(new String(test)));
    in.close();
    // Test substream - all content
    InputStream sub = in.newStream(0, CONTENT.length());
    Assert.assertEquals(CONTENT, getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream beginning
    sub = in.newStream(0, 5);
    Assert.assertEquals("01234", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream end
    sub = in.newStream(5, 10);
    Assert.assertEquals("56789", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    sub = in.newStream(5, -1);
    Assert.assertEquals("56789", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream past EOF
    sub = in.newStream(5, 11);
    Assert.assertEquals("56789", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream middle
    sub = in.newStream(3, 6);
    Assert.assertEquals("345", getContent(sub, 100));
    checkEof(sub);
    sub.close();
    // Test substream position
    sub = in.newStream(3, 6);
    Assert.assertEquals(0, ((SharedInputStream) sub).getPosition());
    sub.read(new byte[2]);
    Assert.assertEquals(2, ((SharedInputStream) sub).getPosition());
    sub.close();
    // Test sub-substream
    InputStream subsub = ((ZSharedFileInputStream) sub).newStream(1, 3);
    Assert.assertEquals("45", getContent(subsub, 100));
    // Test position after reading 1 character
    in.close();
    in = new ZSharedFileInputStream(file);
    Assert.assertEquals(0, in.getPosition());
    in.read();
    Assert.assertEquals(1, in.getPosition());
    in.close();
    // Test reading byte arrays until the end of the file
    in = new ZSharedFileInputStream(file);
    buf = new byte[4];
    while ((numRead = in.read(buf)) >= 0) {
    }
    in.close();
    file.delete();
}
Also used : SharedInputStream(javax.mail.internet.SharedInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) File(java.io.File) Test(org.junit.Test)

Example 5 with SharedInputStream

use of javax.mail.internet.SharedInputStream in project zm-mailbox by Zimbra.

the class ZMimeParser method endPart.

/**
 * Records the endpoint of a MIME part.  Stores both the byte offset of
 *  the end of the part as well as the line count of the part body.  If
 *  the part being ended was a multipart preamble and was of nonzero
 *  length, associates the part with its parent appropriately.
 */
private PartInfo endPart(long end, boolean clean, long lineStart) {
    PartInfo pinfo = parts.remove(parts.size() - 1);
    ZMimePart mp = pinfo.part;
    if (pinfo.location == PartLocation.PREAMBLE) {
        long bodyEnd = Math.max(pinfo.bodyStart, lineStart), length = lineStart - pinfo.bodyStart;
        SharedInputStream bodyStream = (SharedInputStream) sis.newStream(pinfo.bodyStart, bodyEnd);
        if (!clean && !parts.isEmpty()) {
            PartInfo pcurrent = currentPart();
            String enc = pcurrent.part.getEncoding();
            if (enc != null && !ZMimeBodyPart.RAW_ENCODINGS.contains(enc)) {
                // supposedly-encoded multipart and no boundary hit -- defer decoding and parsing
                pcurrent.multi.setDataSource(new MimePartDataSource(pcurrent.part));
                // don't save this as a preamble!
                length = 0;
            }
        }
        if (length > 0) {
            try {
                if (length > MAXIMUM_HEADER_LENGTH) {
                    // constrain preamble length to some reasonable value (64K)
                    bodyStream = (SharedInputStream) bodyStream.newStream(0, length = MAXIMUM_HEADER_LENGTH);
                }
                // save preamble to *parent* multipart
                String preamble = new String(ByteUtil.readInput((InputStream) bodyStream, (int) length, (int) length), charset);
                currentPart().multi.setPreamble(preamble);
            } catch (IOException ioe) {
            }
        }
    } else {
        long bodyEnd = Math.max(pinfo.bodyStart, end), length = end - pinfo.bodyStart;
        SharedInputStream bodyStream = (SharedInputStream) sis.newStream(pinfo.bodyStart, bodyEnd);
        mp.endPart(bodyStream, length, lineNumber - pinfo.firstLine);
    }
    return currentPart();
}
Also used : BufferedInputStream(java.io.BufferedInputStream) SharedInputStream(javax.mail.internet.SharedInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) SharedByteArrayInputStream(javax.mail.util.SharedByteArrayInputStream) InputStream(java.io.InputStream) MimePartDataSource(javax.mail.internet.MimePartDataSource) SharedInputStream(javax.mail.internet.SharedInputStream) IOException(java.io.IOException)

Aggregations

IOException (java.io.IOException)5 InputStream (java.io.InputStream)5 SharedInputStream (javax.mail.internet.SharedInputStream)5 SharedByteArrayInputStream (javax.mail.util.SharedByteArrayInputStream)3 BlobInputStream (com.zimbra.cs.store.BlobInputStream)2 MessagingException (javax.mail.MessagingException)2 ServiceException (com.zimbra.common.service.ServiceException)1 ConversionException (com.zimbra.cs.convert.ConversionException)1 Attachment (com.zimbra.cs.mailbox.Contact.Attachment)1 ContactGroup (com.zimbra.cs.mailbox.ContactGroup)1 ObjectHandlerException (com.zimbra.cs.object.ObjectHandlerException)1 BufferedInputStream (java.io.BufferedInputStream)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 ParseException (java.text.ParseException)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 GZIPInputStream (java.util.zip.GZIPInputStream)1