1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.mime4j.descriptor;
21
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.james.mime4j.parser.Field;
28 import org.apache.james.mime4j.util.MimeUtil;
29
30
31
32
33
34 public class DefaultBodyDescriptor implements MutableBodyDescriptor {
35 private static final String US_ASCII = "us-ascii";
36
37 private static final String SUB_TYPE_EMAIL = "rfc822";
38
39 private static final String MEDIA_TYPE_TEXT = "text";
40
41 private static final String MEDIA_TYPE_MESSAGE = "message";
42
43 private static final String EMAIL_MESSAGE_MIME_TYPE = MEDIA_TYPE_MESSAGE + "/" + SUB_TYPE_EMAIL;
44
45 private static final String DEFAULT_SUB_TYPE = "plain";
46
47 private static final String DEFAULT_MEDIA_TYPE = MEDIA_TYPE_TEXT;
48
49 private static final String DEFAULT_MIME_TYPE = DEFAULT_MEDIA_TYPE + "/" + DEFAULT_SUB_TYPE;
50
51 private static Log log = LogFactory.getLog(DefaultBodyDescriptor.class);
52
53 private String mediaType = DEFAULT_MEDIA_TYPE;
54 private String subType = DEFAULT_SUB_TYPE;
55 private String mimeType = DEFAULT_MIME_TYPE;
56 private String boundary = null;
57 private String charset = US_ASCII;
58 private String transferEncoding = "7bit";
59 private Map<String, String> parameters = new HashMap<String, String>();
60 private boolean contentTypeSet;
61 private boolean contentTransferEncSet;
62 private long contentLength = -1;
63
64
65
66
67 public DefaultBodyDescriptor() {
68 this(null);
69 }
70
71
72
73
74
75
76
77 public DefaultBodyDescriptor(BodyDescriptor parent) {
78 if (parent != null && MimeUtil.isSameMimeType("multipart/digest", parent.getMimeType())) {
79 mimeType = EMAIL_MESSAGE_MIME_TYPE;
80 subType = SUB_TYPE_EMAIL;
81 mediaType = MEDIA_TYPE_MESSAGE;
82 } else {
83 mimeType = DEFAULT_MIME_TYPE;
84 subType = DEFAULT_SUB_TYPE;
85 mediaType = DEFAULT_MEDIA_TYPE;
86 }
87 }
88
89
90
91
92
93
94
95 public void addField(Field field) {
96 String name = field.getName();
97 String value = field.getBody();
98
99 name = name.trim().toLowerCase();
100
101 if (name.equals("content-transfer-encoding") && !contentTransferEncSet) {
102 contentTransferEncSet = true;
103
104 value = value.trim().toLowerCase();
105 if (value.length() > 0) {
106 transferEncoding = value;
107 }
108
109 } else if (name.equals("content-length") && contentLength == -1) {
110 try {
111 contentLength = Long.parseLong(value.trim());
112 } catch (NumberFormatException e) {
113 log.error("Invalid content-length: " + value);
114 }
115 } else if (name.equals("content-type") && !contentTypeSet) {
116 parseContentType(value);
117 }
118 }
119
120 private void parseContentType(String value) {
121 contentTypeSet = true;
122
123 Map<String, String> params = MimeUtil.getHeaderParams(value);
124
125 String main = params.get("");
126 String type = null;
127 String subtype = null;
128 if (main != null) {
129 main = main.toLowerCase().trim();
130 int index = main.indexOf('/');
131 boolean valid = false;
132 if (index != -1) {
133 type = main.substring(0, index).trim();
134 subtype = main.substring(index + 1).trim();
135 if (type.length() > 0 && subtype.length() > 0) {
136 main = type + "/" + subtype;
137 valid = true;
138 }
139 }
140
141 if (!valid) {
142 main = null;
143 type = null;
144 subtype = null;
145 }
146 }
147 String b = params.get("boundary");
148
149 if (main != null
150 && ((main.startsWith("multipart/") && b != null)
151 || !main.startsWith("multipart/"))) {
152
153 mimeType = main;
154 this.subType = subtype;
155 this.mediaType = type;
156 }
157
158 if (MimeUtil.isMultipart(mimeType)) {
159 boundary = b;
160 }
161
162 String c = params.get("charset");
163 charset = null;
164 if (c != null) {
165 c = c.trim();
166 if (c.length() > 0) {
167 charset = c.toLowerCase();
168 }
169 }
170 if (charset == null && MEDIA_TYPE_TEXT.equals(mediaType)) {
171 charset = US_ASCII;
172 }
173
174
175
176
177 parameters.putAll(params);
178 parameters.remove("");
179 parameters.remove("boundary");
180 parameters.remove("charset");
181 }
182
183
184
185
186
187
188 public String getMimeType() {
189 return mimeType;
190 }
191
192
193
194
195
196
197 public String getBoundary() {
198 return boundary;
199 }
200
201
202
203
204
205
206 public String getCharset() {
207 return charset;
208 }
209
210
211
212
213
214
215 public Map<String, String> getContentTypeParameters() {
216 return parameters;
217 }
218
219
220
221
222
223
224 public String getTransferEncoding() {
225 return transferEncoding;
226 }
227
228 @Override
229 public String toString() {
230 return mimeType;
231 }
232
233 public long getContentLength() {
234 return contentLength;
235 }
236
237 public String getMediaType() {
238 return mediaType;
239 }
240
241 public String getSubType() {
242 return subType;
243 }
244 }