mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-07 20:17:37 +00:00
269 lines
9.9 KiB
Java
269 lines
9.9 KiB
Java
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License
|
|
* Version 1.0 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS"
|
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
|
* the License for the specific language governing rights and limitations
|
|
* under the License.
|
|
*
|
|
* The Original Code is the Grendel mail/news client.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are Copyright (C) 1997
|
|
* Netscape Communications Corporation. All Rights Reserved.
|
|
*
|
|
* Created: Jamie Zawinski <jwz@netscape.com>, 21 Aug 1997.
|
|
*/
|
|
|
|
package grendel.mime.parser;
|
|
|
|
import grendel.mime.IMimeOperator;
|
|
import calypso.util.ByteBuf;
|
|
import javax.mail.internet.InternetHeaders;
|
|
import java.util.StringTokenizer;
|
|
|
|
|
|
/** This class represents the X-Sun-Attachment type, which is the Content-Type
|
|
assigned by that pile of garbage called MailTool. This is not a MIME type
|
|
per se, but it's very similar to multipart/mixed, so it's easy to parse.
|
|
Lots of people use MailTool, so we're stuck with having to parse this
|
|
idiotic, obsolete format.
|
|
@see MimeMultipart
|
|
@see MimeUntypedText
|
|
*/
|
|
|
|
/* The format is this:
|
|
|
|
= Content-Type is X-Sun-Attachment
|
|
= parts are separated by lines of exactly ten dashes
|
|
= just after the dashes comes a block of headers, including:
|
|
|
|
X-Sun-Data-Type: (manditory)
|
|
Values are Text, Postscript, Scribe, SGML, TeX, Troff, DVI,
|
|
and Message.
|
|
|
|
X-Sun-Encoding-Info: (optional)
|
|
Ordered, comma-separated values, including Compress and Uuencode.
|
|
|
|
X-Sun-Data-Name: (optional)
|
|
File name, maybe.
|
|
|
|
X-Sun-Data-Description: (optional)
|
|
Longer text.
|
|
|
|
X-Sun-Content-Lines: (manditory, unless Length is present)
|
|
Number of lines in the body, not counting headers and the blank
|
|
line that follows them.
|
|
|
|
X-Sun-Content-Length: (manditory, unless Lines is present)
|
|
Bytes, presumably using Unix line terminators.
|
|
*/
|
|
|
|
class MimeXSunAttachment extends MimeMultipart {
|
|
|
|
public MimeXSunAttachment(String content_type, InternetHeaders headers) {
|
|
super(content_type, headers);
|
|
}
|
|
|
|
protected void computeBoundary() {
|
|
// handled in checkBoundary();
|
|
}
|
|
|
|
protected int checkBoundary(ByteBuf line_buf) {
|
|
if (line_buf.length() <= 10)
|
|
return BOUNDARY_NONE;
|
|
else {
|
|
byte line[] = line_buf.toBytes();
|
|
if (line[0] == '-' && line[1] == '-' && line[2] == '-' &&
|
|
line[3] == '-' && line[4] == '-' && line[5] == '-' &&
|
|
line[6] == '-' && line[7] == '-' && line[8] == '-' &&
|
|
line[9] == '-' &&
|
|
(line[10] == '\r' || line[10] == '\n'))
|
|
return BOUNDARY_SEPARATOR;
|
|
else
|
|
return BOUNDARY_NONE;
|
|
}
|
|
}
|
|
|
|
protected void createMultipartChild() {
|
|
child_headers = translateSunHeaders(child_headers);
|
|
super.createMultipartChild();
|
|
}
|
|
|
|
private String getHeader(InternetHeaders ih, String name) {
|
|
String h[] = ih.getHeader(name);
|
|
if (h == null || h.length == 0)
|
|
return null;
|
|
else
|
|
return h[0];
|
|
}
|
|
|
|
/** Translates x-sun-attachment sub-headers to legal MIME headers. */
|
|
InternetHeaders translateSunHeaders(InternetHeaders in) {
|
|
InternetHeaders out = new InternetHeaders();
|
|
String dt = getHeader(in, "X-Sun-Data-Type");
|
|
String cs = getHeader(in, "X-Sun-Charset");
|
|
String ei = getHeader(in, "X-Sun-Encoding-Info");
|
|
String dn = getHeader(in, "X-Sun-Data-Name");
|
|
String dd = getHeader(in, "X-Sun-Data-Description");
|
|
|
|
if (dn != null && dd != null && dn.equalsIgnoreCase(dd))
|
|
dd = null; // you losers.
|
|
|
|
if (dt != null && dd != null && dt.equalsIgnoreCase(dd))
|
|
dd = null; // you complete losers.
|
|
|
|
if (dt != null && dn != null && dt.equalsIgnoreCase(dn))
|
|
dn = null; // you complete and utter losers.
|
|
|
|
String mime_type = null;
|
|
String mime_enc = null;
|
|
|
|
|
|
/* These are the magic types used by MailTool that I can determine.
|
|
The only actual written spec I've found only listed the first few.
|
|
The rest were found by inspection (both of real-world messages,
|
|
and by running `strings' on the MailTool binary, and on the file
|
|
/usr/openwin/lib/cetables/cetables (the "Class Engine", Sun's
|
|
equivalent to .mailcap and mime.types.)
|
|
*/
|
|
String sun_type_table[][] = {
|
|
{ "default", "text/plain" },
|
|
{ "default-doc", "text/plain" },
|
|
{ "text", "text/plain" },
|
|
{ "scribe", "text/plain" },
|
|
{ "sgml", "text/plain" },
|
|
{ "tex", "text/plain" },
|
|
{ "troff", "text/plain" },
|
|
{ "c-file", "text/plain" },
|
|
{ "h-file", "text/plain" },
|
|
{ "readme-file", "text/plain" },
|
|
{ "shell-script", "text/plain" },
|
|
{ "cshell-script", "text/plain" },
|
|
{ "makefile", "text/plain" },
|
|
{ "hidden-docs", "text/plain" },
|
|
{ "message", "message/rfc822" },
|
|
{ "mail-message", "message/rfc822" },
|
|
{ "mail-file", "text/plain" },
|
|
{ "gif-file", "image/gif" },
|
|
{ "jpeg-file", "image/jpg" },
|
|
{ "ppm-file", "image/ppm" },
|
|
{ "pgm-file", "image/x-portable-graymap" },
|
|
{ "pbm-file", "image/x-portable-bitmap" },
|
|
{ "xpm-file", "image/x-xpixmap" },
|
|
{ "ilbm-file", "image/ilbm" },
|
|
{ "tiff-file", "image/tiff" },
|
|
{ "photocd-file", "image/x-photo-cd" },
|
|
{ "sun-raster", "image/x-sun-raster" },
|
|
{ "audio-file", "audio/basic" },
|
|
{ "postscript", "application/postscript" },
|
|
{ "postscript-file", "application/postscript" },
|
|
{ "framemaker-document", "application/x-framemaker" },
|
|
{ "sundraw-document", "application/x-sun-draw" },
|
|
{ "sunpaint-document", "application/x-sun-paint" },
|
|
{ "sunwrite-document", "application/x-sun-write" },
|
|
{ "islanddraw-document", "application/x-island-draw" },
|
|
{ "islandpaint-document", "application/x-island-paint" },
|
|
{ "islandwrite-document", "application/x-island-write" },
|
|
{ "sun-executable", "application/octet-stream" },
|
|
{ "default-app", "application/octet-stream" },
|
|
{ "compress", "application/x-compress" },
|
|
{ "default-compress", "application/x-compress" },
|
|
{ "gzip", "application/x-gzip" },
|
|
{ "uuencode", "application/x-uuencode" },
|
|
};
|
|
for (int i = 0; i < sun_type_table.length; i++) {
|
|
if (dt.equalsIgnoreCase(sun_type_table[i][0])) {
|
|
mime_type = sun_type_table[i][1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Translate x-sun-attachment sub-part encodings to legal MIME encodings.
|
|
However, if the X-Sun-Encoding-Info field contains more than one
|
|
encoding (that is, contains a comma) then assign it the encoding of
|
|
the *rightmost* element in the list; and change its Content-Type to
|
|
application/octet-stream. Examples:
|
|
|
|
Sun Type: Translates To:
|
|
================== ====================
|
|
type: TEXT type: text/plain
|
|
encoding: COMPRESS encoding: x-compress
|
|
|
|
type: POSTSCRIPT type: application/x-compress
|
|
encoding: COMPRESS,UUENCODE encoding: x-uuencode
|
|
|
|
type: TEXT type: application/octet-stream
|
|
encoding: UNKNOWN,UUENCODE encoding: x-uuencode
|
|
</PRE>
|
|
*/
|
|
if (ei != null) {
|
|
StringTokenizer st = new StringTokenizer(ei, " ,", false);
|
|
String last_enc = null;
|
|
String butlast_enc = null;
|
|
|
|
while (st.hasMoreTokens()) {
|
|
String t = st.nextToken();
|
|
if (t.equalsIgnoreCase("adpcm-compress")) {
|
|
// this "adpcm-compress" pseudo-encoding is some random junk that
|
|
// MailTool adds to the encoding description of .AU files: we can
|
|
// ignore it if it is the leftmost element of the encoding field.
|
|
// (It looks like it's created via `audioconvert -f g721'. Why?
|
|
// Who knows.) Ignore it.
|
|
} else {
|
|
butlast_enc = last_enc;
|
|
last_enc = t;
|
|
}
|
|
}
|
|
|
|
if (butlast_enc != null) {
|
|
if (butlast_enc.equalsIgnoreCase("uuencode"))
|
|
mime_type = "application/x-uuencode";
|
|
else if (butlast_enc.equalsIgnoreCase("gzip"))
|
|
mime_type = "application/x-gzip";
|
|
else if (butlast_enc.equalsIgnoreCase("compress") ||
|
|
butlast_enc.equalsIgnoreCase("default-compress"))
|
|
mime_type = "application/x-compress";
|
|
else
|
|
mime_type = "application/octet-stream";
|
|
}
|
|
|
|
if (last_enc != null) {
|
|
if (last_enc.equalsIgnoreCase("uuencode")) {
|
|
mime_enc = "x-uuencode";
|
|
} else {
|
|
mime_type = "application/octet-stream";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mime_type == null) {
|
|
mime_type = "application/octet-stream";
|
|
if (mime_enc == null && dt != null && dt.equalsIgnoreCase("uuencode"))
|
|
mime_enc = "x-uuencode";
|
|
}
|
|
|
|
if (cs != null && mime_type.startsWith("text/"))
|
|
mime_type += "; charset=\"" + cs + "\"";
|
|
|
|
out.addHeaderLine("Content-Type: " + mime_type + "\r\n");
|
|
|
|
if (mime_enc != null)
|
|
out.addHeaderLine("Content-Transfer-Encoding: " + mime_enc + "\r\n");
|
|
|
|
if (dn != null)
|
|
out.addHeaderLine("Content-Disposition: inline; filename=\"" + dn +
|
|
"\"\r\n");
|
|
|
|
if (dd != null)
|
|
out.addHeaderLine("Content-Description: " + dd + "\r\n");
|
|
|
|
return out;
|
|
}
|
|
}
|