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