MimePart.java :  » IDE » J » org » armedbear » j » mail » Java Open Source

Java Open Source » IDE » J 
J » org » armedbear » j » mail » MimePart.java
/*
 * MimePart.java
 *
 * Copyright (C) 2000-2003 Peter Graves
 * $Id: MimePart.java,v 1.2 2003/06/29 00:19:34 piso Exp $
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package org.armedbear.j.mail;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.armedbear.j.Directories;
import org.armedbear.j.Editor;
import org.armedbear.j.File;
import org.armedbear.j.FastStringBuffer;
import org.armedbear.j.Headers;
import org.armedbear.j.Log;
import org.armedbear.j.StringPair;
import org.armedbear.j.Utilities;

public class MimePart
{
    protected String raw;
    protected Headers headers;

    private Vector parts;

    public MimePart(String raw)
    {
        this.raw = raw;
    }

    public MimePart(String raw, Headers headers)
    {
        this.raw = raw;
        this.headers = headers;
    }

    public final String getRawText()
    {
        return raw;
    }

    public String getAllHeaders()
    {
        if (raw.startsWith("\r\n"))
            return "\r\n";
        if (raw.startsWith("\n"))
            return "\n";
        int index = raw.indexOf("\r\n\r\n");
        if (index >= 0)
            return RFC2047.decode(raw.substring(0, index + 2));
        index = raw.indexOf("\n\n");
        if (index >= 0)
            return RFC2047.decode(raw.substring(0, index + 1));
        return raw;
    }

    public String getRawHeaders()
    {
        if (raw.startsWith("\r\n"))
            return "\r\n";
        if (raw.startsWith("\n"))
            return "\n";
        int index = raw.indexOf("\r\n\r\n");
        if (index >= 0)
            return raw.substring(0, index + 2);
        index = raw.indexOf("\n\n");
        if (index >= 0)
            return raw.substring(0, index + 1);
        return raw;
    }

    public String getRawBody()
    {
        if (raw.startsWith("\r\n"))
            return raw.substring(2);
        else if (raw.startsWith("\n"))
            return raw.substring(1);
        else {
            int index = raw.indexOf("\r\n\r\n");
            if (index >= 0)
                return raw.substring(index + 4);
            else {
                index = raw.indexOf("\n\n");
                if (index >= 0)
                    return raw.substring(index + 2);
                else
                    return raw;
            }
        }
    }

    public String getDecodedBody()
    {
        final String rawBody = getRawBody();
        final String contentType = getContentType();
        final String transferEncoding = getTransferEncoding();
        final String charset =
            Utilities.getCharsetFromContentType(getHeaderValue(Headers.CONTENT_TYPE));
        final String characterEncoding = Utilities.getEncodingFromCharset(charset);
        if (contentType == null || contentType.toLowerCase().startsWith("text/")) {
            if (transferEncoding == null ||
                transferEncoding.equals("7bit") ||
                transferEncoding.equals("8bit") ||
                transferEncoding.equals("binary"))
                return rawBody;
            else if (transferEncoding.equals("quoted-printable")) {
                byte[] bytes = QuotedPrintableDecoder.decode(rawBody);
                try {
                    return new String(bytes, characterEncoding);
                }
                catch (UnsupportedEncodingException e) {
                    Log.error(e);
                    return new String(bytes);
                }
            } else if (transferEncoding.equals("base64")) {
                try {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    Base64Decoder.decode(rawBody, out); // Ignore errors.
                    byte[] bytes = out.toByteArray();
                    if (bytes != null) {
                        try {
                            return new String(bytes, 0, bytes.length,
                                characterEncoding);
                        }
                        catch (UnsupportedEncodingException e) {
                            Log.error(e);
                            return new String(bytes, 0, bytes.length);
                        }
                    }
                }
                catch (IOException e) {
                    Log.error(e);
                }
                return null;
            } else
                return null;
        } else if (contentType.startsWith("multipart/"))
            return rawBody;
        else if (transferEncoding == null)
            return rawBody;
        else
            return null;
    }

    private byte[] getDecodedBodyAsByteArray()
    {
        final String rawBody = getRawBody();
        final String encoding = getTransferEncoding();
        if (encoding == null || encoding.equals("7bit") ||
            encoding.equals("8bit") || encoding.equals("binary")) {
            byte[] bytes = null;
            try {
                 bytes = rawBody.getBytes("ISO8859_1");
            }
            catch (UnsupportedEncodingException e) {
                Log.error(e);
            }
            return bytes;
        }
        if (encoding.equals("quoted-printable"))
            return QuotedPrintableDecoder.decode(rawBody);
        if (encoding.equals("base64")) {
            try {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                if (Base64Decoder.decode(rawBody, out))
                    return out.toByteArray();
            }
            catch (IOException e) {
                Log.error(e);
            }
            // Fall through, return null...
        }
        return null;
    }

    public Vector getParts()
    {
        return parts;
    }

    public MimePart getPart(int i)
    {
        if (parts == null)
            return null;
        if (i < 0)
            return null;
        if (i >= parts.size())
            return null;
        return (MimePart) parts.get(i);
    }

    protected void addParts(Vector v)
    {
        v.add(this);
        // Recurse.
        if (parts != null) {
            for (int i = 0; i < parts.size(); i++) {
                MimePart part = (MimePart) parts.get(i);
                String contentType = part.getContentType();
                if (contentType != null && contentType.startsWith("multipart/"))
                    part.addParts(v);
                else
                    v.add(part);
            }
        }
    }

    public final Headers getHeaders()
    {
        if (headers == null)
            headers = Headers.parse(raw);
        return headers;
    }

    public final String getHeaderValue(int index)
    {
        if (headers == null)
            headers = Headers.parse(raw);
        return headers.getValue(index);
    }

    public final String getContentType()
    {
        String s = getHeaderValue(Headers.CONTENT_TYPE);
        if (s == null )
            return null;
        s = s.trim();
        if (s.length() == 0)
            return null;
        int index = s.indexOf(';');
        if (index >= 0)
            s = s.substring(0, index);
        return s.toLowerCase();
    }

    public final String getTransferEncoding()
    {
        String s = getHeaderValue(Headers.CONTENT_TRANSFER_ENCODING);
        if (s == null )
            return null;
        return s.toLowerCase();
    }

    public final String getDisposition()
    {
        String s = getHeaderValue(Headers.CONTENT_DISPOSITION);
        if (s == null)
            return null;
        s = s.trim();
        int index = s.indexOf(';');
        if (index >= 0 )
            s = s.substring(0, index);
        return s;
    }

    public final int getSize()
    {
        String s = getRawBody();
        return s == null ? 0 : s.length();
    }

    public final boolean isAttachment()
    {
        String s = getHeaderValue(Headers.CONTENT_DISPOSITION);
        if (s != null && s.trim().startsWith("attachment"))
            return true;
        else
            return false;
    }

    public final boolean isInline()
    {
        String s = getHeaderValue(Headers.CONTENT_DISPOSITION);
        if (s != null && s.trim().startsWith("inline"))
            return true;
        return false;
    }

    public String getAttachmentFileName()
    {
        String filename =
            getHeaderParameter(Headers.CONTENT_DISPOSITION, "filename");
        if (filename == null)
            filename = getHeaderParameter(Headers.CONTENT_TYPE, "name");
        if (filename != null) {
            filename = filename.trim();
            int length = filename.length();
            // Strip quotes.
            if (length >= 2 && filename.charAt(0) == '"' &&
                filename.charAt(length-1) == '"')
                filename = filename.substring(1, length-1);
            // Filename might be RFC2047-encoded.
            filename = RFC2047.decode(filename);
            // Remove path prefix, if any.
            int index = filename.lastIndexOf('/');
            if (index < 0)
                index = filename.lastIndexOf('\\');
            if (index >= 0)
                filename = filename.substring(index+1);
        }
        return filename;
    }

    private String getHeaderParameter(int header, String parameterName)
    {
        String s = getHeaderValue(header);
        if (s != null) {
            s = s.trim();
            String lower = s.toLowerCase();
            int index = lower.indexOf(parameterName.concat("="));
            if (index >= 0) {
                int begin = index + parameterName.length() + 1;
                int end = s.indexOf(';', begin);
                if (end >= 0)
                    return s.substring(begin, end);
                else
                    return s.substring(begin);
            }
        }
        return null;
    }

    public File cacheDecoded()
    {
        String filename = getAttachmentFileName();
        String extension = null;
        if (filename != null && filename.length() > 0) {
            extension = Utilities.getExtension(filename);
        } else {
            // No filename specified.
            String contentType = getContentType();
            if (contentType != null) {
                if (contentType.equals("image/jpeg"))
                    extension = ".jpg";
                else if (contentType.equals("image/gif"))
                    extension = ".gif";
                else if (contentType.equals("text/html"))
                    extension = ".html";
            }
        }
        File cache =
            Utilities.getTempFile(Directories.getTempDirectory(), extension);
        if (cache != null && saveDecoded(cache))
            return cache;
        else
            return null;
    }

    public boolean saveDecoded(File file)
    {
        String encoding = getTransferEncoding();
        if (encoding == null || encoding.equals("7bit") ||
            encoding.equals("8bit") || encoding.equals("binary") ||
            encoding.equals("quoted-printable")) {
            try {
                byte[] bytes = getDecodedBodyAsByteArray();
                if (bytes == null)
                    return false;
                FileOutputStream out = file.getOutputStream();
                out.write(bytes);
                out.flush();
                out.close();
                return true;
            }
            catch (IOException e) {
                Log.error(e);
                return false;
            }
        } else if (encoding.equals("base64")) {
            return saveDecodedBase64(file);
        } else if (encoding.equals("x-uuencode")) {
            Log.error("saveDecoded x-uuencode not supported");
            return false;
        } else {
            Log.error("saveDecoded unrecognized encoding " + encoding);
            return false;
        }
    }

    private boolean saveDecodedBase64(File file)
    {
        boolean success = false;
        try {
            BufferedOutputStream out =
                new BufferedOutputStream(file.getOutputStream());
            String rawBody = getRawBody();
            success = Base64Decoder.decode(rawBody, out);
            out.flush();
            out.close();
        }
        catch (IOException e) {
            Log.error(e);
            success = false;
        }
        if (!success)
            file.delete();
        return success;
    }

    private static final String BOUNDARY_START = "boundary=";

    public void parse()
    {
        final String contentType = getHeaderValue(Headers.CONTENT_TYPE);
        if (contentType == null)
            return;
        if (contentType.toLowerCase().startsWith("multipart/")) {
            int index = contentType.toLowerCase().indexOf(BOUNDARY_START);
            if (index < 0) {
                Log.error("can't find boundary parameter");
                return;
            }
            String boundary =
                contentType.substring(index + BOUNDARY_START.length()).trim();
            if (boundary.length() >= 2 && boundary.charAt(0) == '"') {
                int end = boundary.indexOf('"', 1);
                if (end >= 0)
                    boundary = boundary.substring(1, end);
            }
            parts = parseParts(boundary);
            if (parts != null) {
                for (int i = 0; i < parts.size(); i++) {
                    MimePart part = (MimePart) parts.get(i);
                    part.parse();
                }
            }
            return;
        }
        final String disposition = getDisposition();
        if (disposition != null && disposition.equalsIgnoreCase("attachment")) {
            parts = new Vector();
            MimePart part = new MimePart(raw);
            parts.add(part);
        }
    }

    private Vector parseParts(String boundary)
    {
        final String marker = "--" + boundary;
        final String endMarker = marker + "--";
        final int veryEnd = raw.indexOf(endMarker);
        int start = raw.indexOf(marker);
        if (start < 0)
            return null;
        Vector v = new Vector();
        while (true) {
            start += marker.length();
            if (raw.charAt(start) == '\r')
                ++start;
            if (raw.charAt(start) == '\n')
                ++start;
            int end = raw.indexOf(marker, start);
            if (end < 0)
                end = raw.length();
            MimePart part = new MimePart(raw.substring(start, end));
            v.add(part);
            if (end == veryEnd || end == raw.length())
                break;
            start = end;
        }
        return v;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.