+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
+
+package org.ibex.mail;
+import static org.ibex.mail.MailException.*;
+import org.ibex.crypto.*;
+import org.ibex.util.*;
+import org.ibex.mail.protocol.*;
+import org.ibex.js.*;
+import org.ibex.io.*;
+import org.ibex.io.Fountain;
+import java.util.*;
+import java.net.*;
+import java.io.*;
+
+public class Headers extends JS.Immutable implements Fountain {
+ private final Hash head = new Hash();
+ private final Hash headModified = new Hash();
+ public int lines;
+ public final boolean mime;
+
+ private String raw;
+ private StringFountain fountain;
+
+ public String get(String s) {
+ String ret = (String)headModified.get(s.toLowerCase());
+ if (ret==null) ret = (String)head.get(s.toLowerCase());
+ return ret;
+ }
+ public void put(String k, String v) {
+ Stream stream = getStream();
+ StringBuffer all = new StringBuffer();
+ int lines = 0;
+ boolean good = false;
+ String key = null;
+ for(String s = stream.readln(); s != null && !s.equals(""); s = stream.readln()) {
+ if (Character.isSpace(s.charAt(0))) { all.append(s); all.append("\r\n"); lines++; continue; }
+ if (s.indexOf(':') == -1) throw new Malformed("Header line does not contain colon: " + s);
+ key = s.substring(0, s.indexOf(':')).toLowerCase();
+ lines++;
+ if (key.toLowerCase().equals(k.toLowerCase())) {
+ good = true;
+ all.append(k + ": " + v + "\r\n");
+ continue;
+ }
+ all.append(s);
+ all.append("\r\n");
+ }
+ if (!good) {
+ lines++;
+ all.append(k + ": " + v + "\r\n");
+ }
+ this.raw = all.toString();
+ this.lines = lines;
+ this.fountain = new Fountain.StringFountain(this.raw);
+ }
+ public JS get(JS s) throws JSExn { return JSU.S(get(JSU.toString(s).toLowerCase())); }
+
+ public Stream getStream() { return fountain.getStream(); }
+ public int getLength() { return fountain.getLength(); }
+ public int getNumLines() { return fountain.getNumLines(); }
+ public Stream getStreamWithCRLF() { return new Stream(raw+"\r\n"); }
+
+ // FIXME
+ public String getString() { return raw; }
+
+ public Headers(Stream stream) throws Malformed { this(stream, false); }
+ public Headers(Stream stream, boolean assumeMime) throws Malformed {
+ StringBuffer all = new StringBuffer();
+ String key = null;
+ int lines = 0;
+ for(String s = stream.readln(); s != null && !s.equals(""); s = stream.readln()) {
+ all.append(s);
+ all.append("\r\n");
+ lines++;
+ if (Character.isSpace(s.charAt(0))) {
+ if (key == null) throw new Malformed("Message began with a blank line; no headers");
+ head.put(key, head.get(key) + " " + s.trim());
+ continue;
+ }
+ if (s.indexOf(':') == -1) throw new Malformed("Header line does not contain colon: " + s);
+ key = s.substring(0, s.indexOf(':')).toLowerCase();
+ for(int i=0; i<key.length(); i++)
+ if (key.charAt(i) < 33 || key.charAt(i) > 126)
+ throw new Malformed("Header key \""+key+"\" contains invalid character \"" + key.charAt(i) + "\"");
+ String val = s.substring(s.indexOf(':') + 1).trim();
+ if (get(key) != null) val = get(key) + " " + val; // just append it to the previous one;
+ head.put(key, val);
+ }
+ this.raw = all.toString();
+ this.fountain = new Fountain.StringFountain(this.raw);
+ this.lines = lines;
+ this.mime = assumeMime | (get("mime-version") != null && get("mime-version").trim().equals("1.0"));
+ /*
+ java.util.Enumeration e = head.keys();
+ while(e.hasNext()) {
+ String k = (String)e.next();
+ String v = (String)head.get(k);
+ if (mime) k = Encode.RFC2047.decode(k);
+ v = uncomment(v);
+ if (mime) v = Encode.RFC2047.decode(v);
+ head.put(k, v);
+ }
+ */
+ }
+
+ // Helpers //////////////////////////////////////////////////////////////////////////////
+
+ public static Stream skip(Stream stream) {
+ for(String s = stream.readln(); s!=null && s.length() > 0;) s = stream.readln();
+ return stream;
+ }
+
+ public static String uncomment(String val) {
+ boolean inquotes = false;
+ for(int i=0; i<val.length(); i++) {
+ if (val.charAt(i) == '\"') inquotes = !inquotes;
+ if (val.charAt(i) == '(' && !inquotes)
+ val = val.substring(0, i) + val.substring(val.indexOf(i--, ')') + 1);
+ }
+ return val;
+ }
+}