1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package javax.mail.internet;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.Enumeration;
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.LinkedHashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35
36 import javax.mail.Address;
37 import javax.mail.Header;
38 import javax.mail.MessagingException;
39
40
41
42
43
44
45 public class InternetHeaders {
46
47 protected List headers = new ArrayList();
48
49 private transient String lastHeaderName;
50
51
52
53
54 public InternetHeaders() {
55
56 addHeader("Return-path", null);
57 addHeader("Received", null);
58 addHeader("Message-ID", null);
59 addHeader("Resent-Date", null);
60 addHeader("Date", null);
61 addHeader("Resent-From", null);
62 addHeader("From", null);
63 addHeader("Reply-To", null);
64 addHeader("Sender", null);
65 addHeader("To", null);
66 addHeader("Subject", null);
67 addHeader("Cc", null);
68 addHeader("In-Reply-To", null);
69 addHeader("Resent-Message-Id", null);
70 addHeader("Errors-To", null);
71 addHeader("MIME-Version", null);
72 addHeader("Content-Type", null);
73 addHeader("Content-Transfer-Encoding", null);
74 addHeader("Content-MD5", null);
75
76 addHeader(":", null);
77 addHeader("Content-Length", null);
78 addHeader("Status", null);
79 }
80
81
82
83
84
85
86
87
88
89
90 public InternetHeaders(InputStream in) throws MessagingException {
91 load(in);
92 }
93
94
95
96
97
98
99
100
101
102
103 public void load(InputStream in) throws MessagingException {
104 try {
105 StringBuffer name = new StringBuffer(32);
106 StringBuffer value = new StringBuffer(128);
107 done: while (true) {
108 int c = in.read();
109 char ch = (char) c;
110 if (c == -1) {
111 break;
112 } else if (c == 13) {
113
114 in.read();
115 break;
116 } else if ( c == 10) {
117
118 break;
119 } else if (Character.isWhitespace(ch)) {
120
121 do {
122 c = in.read();
123 if (c == -1) {
124 break done;
125 }
126 ch = (char) c;
127 } while (Character.isWhitespace(ch));
128 } else {
129
130 if (name.length() > 0) {
131 addHeader(name.toString().trim(), value.toString().trim());
132 }
133 name.setLength(0);
134 value.setLength(0);
135 while (true) {
136 name.append((char) c);
137 c = in.read();
138 if (c == -1) {
139 break done;
140 } else if (c == ':') {
141 break;
142 }
143 }
144 c = in.read();
145 if (c == -1) {
146 break done;
147 }
148 }
149
150 while (c != 13 && c != 10) {
151 ch = (char) c;
152 value.append(ch);
153 c = in.read();
154 if (c == -1) {
155 break done;
156 }
157 }
158
159 if (c == 13) {
160 c = in.read();
161 }
162
163 if (c == -1) {
164 break;
165 }
166 }
167 if (name.length() > 0) {
168 addHeader(name.toString().trim(), value.toString().trim());
169 }
170 } catch (IOException e) {
171 throw new MessagingException("Error loading headers", e);
172 }
173 }
174
175
176
177
178
179
180
181
182
183 public String[] getHeader(String name) {
184 List accumulator = new ArrayList();
185
186 for (int i = 0; i < headers.size(); i++) {
187 InternetHeader header = (InternetHeader)headers.get(i);
188 if (header.getName().equalsIgnoreCase(name) && header.getValue() != null) {
189 accumulator.add(header.getValue());
190 }
191 }
192
193
194 if (accumulator.isEmpty()) {
195 return null;
196 }
197
198
199 return (String[])accumulator.toArray(new String[accumulator.size()]);
200 }
201
202
203
204
205
206
207
208
209
210
211
212
213 public String getHeader(String name, String delimiter) {
214
215 String[] matches = getHeader(name);
216
217
218 if (matches == null) {
219 return null;
220 }
221
222
223 if (matches.length == 1 || delimiter == null) {
224 return matches[0];
225 }
226
227
228 StringBuffer result = new StringBuffer(matches[0]);
229
230 for (int i = 1; i < matches.length; i++) {
231 result.append(delimiter);
232 result.append(matches[i]);
233 }
234
235 return result.toString();
236 }
237
238
239
240
241
242
243
244
245
246
247
248 public void setHeader(String name, String value) {
249
250 for (int i = 0; i < headers.size(); i++) {
251 InternetHeader header = (InternetHeader)headers.get(i);
252
253 if (name.equalsIgnoreCase(header.getName())) {
254
255 header.setValue(value);
256
257 removeHeaders(name, i + 1);
258 return;
259 }
260 }
261
262
263 addHeader(name, value);
264 }
265
266
267
268
269
270
271
272
273
274 private void removeHeaders(String name, int pos) {
275
276 for (int i = pos; i < headers.size(); i++) {
277 InternetHeader header = (InternetHeader)headers.get(i);
278
279 if (name.equalsIgnoreCase(header.getName())) {
280
281 headers.remove(i);
282 i--;
283 }
284 }
285 }
286
287
288
289
290
291
292
293
294
295
296 private int findHeader(String name) {
297 return findHeader(name, 0);
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311 private int findHeader(String name, int start) {
312 for (int i = start; i < headers.size(); i++) {
313 InternetHeader header = (InternetHeader)headers.get(i);
314
315 if (name.equalsIgnoreCase(header.getName())) {
316 return i;
317 }
318 }
319 return -1;
320 }
321
322
323
324
325
326
327
328
329
330 public void addHeader(String name, String value) {
331 InternetHeader newHeader = new InternetHeader(name, value);
332
333
334
335 if (name.equalsIgnoreCase("Received") || name.equalsIgnoreCase("Return-Path")) {
336
337 int pos = findHeader(name);
338
339
340 if (pos != -1) {
341
342
343 InternetHeader oldHeader = (InternetHeader)headers.get(pos);
344 if (oldHeader.getValue() == null) {
345 oldHeader.setValue(value);
346 }
347 else {
348 headers.add(pos, newHeader);
349 }
350 }
351 else {
352
353 headers.add(0, newHeader);
354 }
355 }
356
357 else {
358
359 int pos = findHeader(name);
360
361
362 if (pos != -1) {
363 InternetHeader oldHeader = (InternetHeader)headers.get(pos);
364
365 if (oldHeader.getValue() == null) {
366 oldHeader.setValue(value);
367 }
368 else {
369
370
371
372 int lastPos = findHeader(name, pos + 1);
373
374 while (lastPos != -1) {
375 pos = lastPos;
376 lastPos = findHeader(name, pos + 1);
377 }
378
379
380 headers.add(pos + 1, newHeader);
381 }
382 }
383 else {
384
385 pos = findHeader(":");
386 if (pos == -1) {
387 pos = headers.size();
388 }
389 headers.add(pos, newHeader);
390 }
391 }
392 }
393
394
395
396
397
398
399
400
401 public void removeHeader(String name) {
402
403 int pos = findHeader(name);
404
405 if (pos != -1) {
406 InternetHeader oldHeader = (InternetHeader)headers.get(pos);
407
408 oldHeader.setValue(null);
409
410 removeHeaders(name, pos + 1);
411 }
412 }
413
414
415
416
417
418
419
420 public Enumeration getAllHeaders() {
421 List result = new ArrayList();
422
423 for (int i = 0; i < headers.size(); i++) {
424 InternetHeader header = (InternetHeader)headers.get(i);
425
426 if (header.getValue() != null) {
427 result.add(header);
428 }
429 }
430
431 return Collections.enumeration(result);
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445 private boolean matchHeader(String name, String[] names) {
446 for (int i = 0; i < names.length; i++) {
447 if (name.equalsIgnoreCase(names[i])) {
448 return true;
449 }
450 }
451 return false;
452 }
453
454
455
456
457
458 public Enumeration getMatchingHeaders(String[] names) {
459 List result = new ArrayList();
460
461 for (int i = 0; i < headers.size(); i++) {
462 InternetHeader header = (InternetHeader)headers.get(i);
463
464 if (header.getValue() != null) {
465
466 if (matchHeader(header.getName(), names)) {
467 result.add(header);
468 }
469 }
470 }
471 return Collections.enumeration(result);
472 }
473
474
475
476
477
478 public Enumeration getNonMatchingHeaders(String[] names) {
479 List result = new ArrayList();
480
481 for (int i = 0; i < headers.size(); i++) {
482 InternetHeader header = (InternetHeader)headers.get(i);
483
484 if (header.getValue() != null) {
485
486 if (!matchHeader(header.getName(), names)) {
487 result.add(header);
488 }
489 }
490 }
491 return Collections.enumeration(result);
492 }
493
494
495
496
497
498
499
500
501
502
503
504
505 public void addHeaderLine(String line) {
506
507 if (line.length() == 0) {
508 return;
509 }
510
511
512 char ch = line.charAt(0);
513
514
515 if (ch == ' ' || ch == '\t') {
516 InternetHeader header = (InternetHeader)headers.get(headers.size() - 1);
517 header.appendValue(line);
518 }
519 else {
520
521 headers.add(new InternetHeader(line));
522 }
523 }
524
525
526
527
528
529 public Enumeration getAllHeaderLines() {
530 return new HeaderLineEnumeration(getAllHeaders());
531 }
532
533
534
535
536 public Enumeration getMatchingHeaderLines(String[] names) {
537 return new HeaderLineEnumeration(getMatchingHeaders(names));
538 }
539
540
541
542
543 public Enumeration getNonMatchingHeaderLines(String[] names) {
544 return new HeaderLineEnumeration(getNonMatchingHeaders(names));
545 }
546
547
548
549
550
551
552
553
554
555 void setHeader(String name, Address[] addresses) {
556
557 if (addresses.length == 0) {
558 removeHeader(name);
559 }
560
561
562 setHeader(name, addresses[0].toString());
563
564
565 for (int i = 1; i < addresses.length; i++) {
566 Address address = addresses[i];
567 addHeader(name, address.toString());
568 }
569 }
570
571
572 void writeTo(OutputStream out, String[] ignore) throws IOException {
573 if (ignore == null) {
574
575 for (int i = 0; i < headers.size(); i++) {
576 InternetHeader header = (InternetHeader)headers.get(i);
577
578 if (header.getValue() != null) {
579 header.writeTo(out);
580 }
581 }
582 }
583 else {
584
585 for (int i = 0; i < headers.size(); i++) {
586 InternetHeader header = (InternetHeader)headers.get(i);
587
588 if (header.getValue() != null) {
589 if (matchHeader(header.getName(), ignore)) {
590 header.writeTo(out);
591 }
592 }
593 }
594 }
595 }
596
597 protected static final class InternetHeader extends Header {
598
599 public InternetHeader(String h) {
600
601 super("", "");
602 int separator = h.indexOf(':');
603
604 if (separator == -1) {
605 name = h.trim();
606 }
607 else {
608 name = h.substring(0, separator);
609
610 separator++;
611
612 while (separator < h.length()) {
613 char ch = h.charAt(separator);
614 if (ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n') {
615 break;
616 }
617 separator++;
618 }
619
620 value = h.substring(separator);
621 }
622 }
623
624 public InternetHeader(String name, String value) {
625 super(name, value);
626 }
627
628
629
630
631
632
633
634 void setValue(String value) {
635 this.value = value;
636 }
637
638
639
640
641
642
643 void appendValue(String value) {
644 if (this.value == null) {
645 this.value = value;
646 }
647 else {
648 this.value = this.value + "\r\n" + value;
649 }
650 }
651
652 void writeTo(OutputStream out) throws IOException {
653 out.write(name.getBytes());
654 out.write(':');
655 out.write(' ');
656 out.write(value.getBytes());
657 out.write('\r');
658 out.write('\n');
659 }
660 }
661
662 private static class HeaderLineEnumeration implements Enumeration {
663 private Enumeration headers;
664
665 public HeaderLineEnumeration(Enumeration headers) {
666 this.headers = headers;
667 }
668
669 public boolean hasMoreElements() {
670 return headers.hasMoreElements();
671 }
672
673 public Object nextElement() {
674 Header h = (Header) headers.nextElement();
675 return h.getName() + ": " + h.getValue();
676 }
677 }
678 }