1 package org.bouncycastle.mime;
2 
3 import java.io.IOException;
4 import java.io.InputStream;
5 
6 import org.bouncycastle.mime.encoding.Base64InputStream;
7 import org.bouncycastle.mime.encoding.QuotedPrintableInputStream;
8 
9 public class BasicMimeParser
10     implements MimeParser
11 {
12     private final InputStream src;
13     private final MimeParserContext parserContext;
14     private final String defaultContentTransferEncoding;
15     private Headers headers;
16 
17     private boolean isMultipart = false;
18     private final String boundary;
19 
BasicMimeParser( InputStream src)20     public BasicMimeParser(
21         InputStream src)
22         throws IOException
23     {
24         this(null, new Headers(src, "7bit"), src);
25     }
26 
BasicMimeParser( MimeParserContext parserContext, InputStream src)27     public BasicMimeParser(
28         MimeParserContext parserContext, InputStream src)
29         throws IOException
30     {
31         this(parserContext, new Headers(src, parserContext.getDefaultContentTransferEncoding()), src);
32     }
33 
BasicMimeParser( Headers headers, InputStream content)34     public BasicMimeParser(
35         Headers headers, InputStream content)
36     {
37         this(null, headers, content);
38     }
39 
BasicMimeParser( MimeParserContext parserContext, Headers headers, InputStream src)40     public BasicMimeParser(
41         MimeParserContext parserContext, Headers headers, InputStream src)
42     {
43         if (headers.isMultipart())
44         {
45             isMultipart = true;
46             boundary = headers.getBoundary();
47         }
48         else
49         {
50             boundary = null;
51         }
52 
53         this.headers = headers;
54         this.parserContext = parserContext;
55         this.src = src;
56         this.defaultContentTransferEncoding = (parserContext != null) ? parserContext.getDefaultContentTransferEncoding() : "7bit";
57     }
58 
59 
60 
parse(MimeParserListener listener)61     public void parse(MimeParserListener listener)
62         throws IOException
63     {
64         MimeContext context = listener.createContext(parserContext, headers);
65 
66         String s;
67         if (isMultipart)    // Signed
68         {
69             MimeMultipartContext mContext = (MimeMultipartContext)context;
70             String startBoundary = "--" + boundary;
71             boolean startFound = false;
72             int partNo = 0;
73             LineReader rd = new LineReader(src);
74             while ((s = rd.readLine()) != null && !"--".equals(s))
75             {
76                 if (startFound)
77                 {
78                     InputStream inputStream = new BoundaryLimitedInputStream(src, boundary);
79                     Headers headers = new Headers(inputStream, defaultContentTransferEncoding);
80 
81                     MimeContext partContext = mContext.createContext(partNo++);
82                     inputStream = partContext.applyContext(headers, inputStream);
83 
84                     listener.object(parserContext, headers, processStream(headers, inputStream));
85 
86                     if (inputStream.read() >= 0)
87                     {
88                         throw new IOException("MIME object not fully processed");
89                     }
90                 }
91                 else if (startBoundary.equals(s))
92                 {
93                     startFound = true;
94                     InputStream inputStream = new BoundaryLimitedInputStream(src, boundary);
95                     Headers headers = new Headers(inputStream, defaultContentTransferEncoding);
96 
97                     MimeContext partContext = mContext.createContext(partNo++);
98                     inputStream = partContext.applyContext(headers, inputStream);
99 
100                     listener.object(parserContext, headers, processStream(headers, inputStream));
101 
102                     if (inputStream.read() >= 0)
103                     {
104                         throw new IOException("MIME object not fully processed");
105                     }
106                 }
107             }
108         }
109         else
110         {
111             InputStream inputStream = context.applyContext(headers, src);
112 
113             listener.object(parserContext, headers, processStream(headers, inputStream));
114         }
115     }
116 
isMultipart()117     public boolean isMultipart()
118     {
119         return isMultipart;
120     }
121 
processStream(Headers headers, InputStream inputStream)122     private InputStream processStream(Headers headers, InputStream inputStream)
123     {
124         if (headers.getContentTransferEncoding().equals("base64"))
125         {
126             return new Base64InputStream(inputStream);
127         }
128         else if (headers.getContentTransferEncoding().equals("quoted-printable"))
129         {
130             return new QuotedPrintableInputStream(inputStream);
131         }
132         else
133         {
134             return inputStream;
135         }
136     }
137 }
138