minor reformatting
[org.ibex.mail.git] / src / org / ibex / mail / MIME.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.mail;
6 import static org.ibex.mail.MailException.*;
7 import org.ibex.crypto.*;
8 import org.ibex.util.*;
9 import org.ibex.mail.protocol.*;
10 import org.ibex.js.*;
11 import org.ibex.io.*;
12 import org.ibex.io.Fountain;
13 import java.util.*;
14 import java.net.*;
15 import java.io.*;
16
17 // FEATURE: MIME RFC2045, 2046, 2049
18
19 /** This class contains logic for encoding and decoding MIME multipart messages */
20 public class MIME {
21
22     public static class Part extends JSReflection implements Fountain {
23         public  final Headers      headers;
24         public  final ContentType  contentType;
25         private final String       encoding;
26
27         private final Fountain     all;
28         private final Fountain     body;
29
30         public Stream getStream()   { return all.getStream(); }
31         public int getNumLines()    { return all.getNumLines(); }
32         public long getLength()     { return all.getLength(); }
33         public Fountain getBody()   { return body; }
34
35         private class BodyFountain implements Fountain {
36             public int getNumLines()  { return Stream.countLines(getStream()); }
37             public long getLength()   { return Part.this.getLength() - headers.getLength() - 2 /*FIXME: correct?*/; }
38             public Stream getStream() {
39                 return /*
40                          "quoted-printable".equals(encoding) ? Encode.QuotedPrintable.decode(body.toString(),false) :
41                          "base64".equals(encoding)           ? Encode.fromBase64(body.toString()) :
42                        */
43                     Headers.Original.skip(all.getStream());
44             }
45         }
46
47         public Part(Fountain all) {
48             this.headers     = new Headers.Original(all.getStream());
49             String ctype     = headers.get("content-type");
50             this.encoding    = headers.get("content-transfer-encoding");
51             if (!(encoding == null || encoding.equals("7bit") || encoding.equals("8bit") || encoding.equals("binary") ||
52                   encoding.equals("quoted-printable") || encoding.equals("base64"))) {
53                 // FIXME: "7BIT" is popular
54                 Log.warn(MIME.class, "unknown TransferEncoding \"" + encoding + "\"");
55                 ctype = "application/octet-stream";
56             }
57             this.contentType = new ContentType(ctype, headers.get("content-description"), headers.get("content-id"), encoding);
58             this.all = all;
59             this.body = new BodyFountain();
60         }
61
62         /*
63         public Part getPart(int i) {
64             Stream stream = body.getStream();
65             Vec v = new Vec();
66             // first part begins with a boundary delimiter
67             for(String s = stream.readln(); s != null; s = stream.readln())
68                 if (s.equals("--" + contentType.parameters.get("boundary"))) break;
69             while(true) {
70                 Stream substream = new BoundaryStream(stream, (String)contentType.parameters.get("boundary"));
71                 Part p = new Part(substream, true, null); // FIXME split off headers
72                 v.addElement(p);
73                 if (substream.isLast()) break;
74             }
75             return parts = (Part[])v.copyInto(new Part[v.size()]);
76         }
77         */
78     }
79     /*
80     public static class Boundary implements Stream.Transformer {
81         private final String boundary;
82         private boolean done = false;
83         private boolean last = false;
84         public Boundary(String bounardy) { this.boundary = boundary; }
85         public boolean isLast() { while(!done) readln(); return last; }
86         public Stream transform(Stream stream) {
87             for(String s = stream.readln(); s != null; s = stream.readln()) {
88                 if (boundary != null && (s.equals(boundary) || s.equals(boundary + "--"))) {
89                     body.setLength(body.length() - 2);  // preceeding CRLF is part of delimiter
90                     last = s.equals(boundary + "--");
91                     done = true;
92                     break;
93                 }
94                 body.append(s);
95                 body.append("\r\n");
96                 //lines++;
97             }
98         }
99     }
100     */
101 }