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