diff options
Diffstat (limited to 'java/com/google/gerrit/mail/EmailHeader.java')
-rw-r--r-- | java/com/google/gerrit/mail/EmailHeader.java | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/java/com/google/gerrit/mail/EmailHeader.java b/java/com/google/gerrit/mail/EmailHeader.java new file mode 100644 index 0000000000..69d5fcdaab --- /dev/null +++ b/java/com/google/gerrit/mail/EmailHeader.java @@ -0,0 +1,233 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.mail; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.base.MoreObjects; +import java.io.IOException; +import java.io.Writer; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +public abstract class EmailHeader { + public abstract boolean isEmpty(); + + public abstract void write(Writer w) throws IOException; + + public static class String extends EmailHeader { + private final java.lang.String value; + + public String(java.lang.String v) { + value = v; + } + + public java.lang.String getString() { + return value; + } + + @Override + public boolean isEmpty() { + return value == null || value.length() == 0; + } + + @Override + public void write(Writer w) throws IOException { + if (needsQuotedPrintable(value)) { + w.write(quotedPrintable(value)); + } else { + w.write(value); + } + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } + + @Override + public boolean equals(Object o) { + return (o instanceof String) && Objects.equals(value, ((String) o).value); + } + + @Override + public java.lang.String toString() { + return MoreObjects.toStringHelper(this).addValue(value).toString(); + } + } + + public static boolean needsQuotedPrintable(java.lang.String value) { + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) < ' ' || '~' < value.charAt(i)) { + return true; + } + } + return false; + } + + static boolean needsQuotedPrintableWithinPhrase(int cp) { + switch (cp) { + case '!': + case '*': + case '+': + case '-': + case '/': + case '=': + case '_': + return false; + default: + if (('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z') || ('0' <= cp && cp <= '9')) { + return false; + } + return true; + } + } + + public static java.lang.String quotedPrintable(java.lang.String value) { + final StringBuilder r = new StringBuilder(); + + r.append("=?UTF-8?Q?"); + for (int i = 0; i < value.length(); i++) { + final int cp = value.codePointAt(i); + if (cp == ' ') { + r.append('_'); + + } else if (needsQuotedPrintableWithinPhrase(cp)) { + byte[] buf = new java.lang.String(Character.toChars(cp)).getBytes(UTF_8); + for (byte b : buf) { + r.append('='); + r.append(Integer.toHexString((b >>> 4) & 0x0f).toUpperCase()); + r.append(Integer.toHexString(b & 0x0f).toUpperCase()); + } + + } else { + r.append(Character.toChars(cp)); + } + } + r.append("?="); + + return r.toString(); + } + + public static class Date extends EmailHeader { + private final java.util.Date value; + + public Date(java.util.Date v) { + value = v; + } + + public java.util.Date getDate() { + return value; + } + + @Override + public boolean isEmpty() { + return value == null; + } + + @Override + public void write(Writer w) throws IOException { + final SimpleDateFormat fmt; + // Mon, 1 Jun 2009 10:49:44 -0700 + fmt = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); + w.write(fmt.format(value)); + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } + + @Override + public boolean equals(Object o) { + return (o instanceof Date) && Objects.equals(value, ((Date) o).value); + } + + @Override + public java.lang.String toString() { + return MoreObjects.toStringHelper(this).addValue(value).toString(); + } + } + + public static class AddressList extends EmailHeader { + private final List<Address> list = new ArrayList<>(); + + public AddressList() {} + + public AddressList(Address addr) { + add(addr); + } + + public List<Address> getAddressList() { + return Collections.unmodifiableList(list); + } + + public void add(Address addr) { + list.add(addr); + } + + public void remove(java.lang.String email) { + list.removeIf(address -> address.getEmail().equals(email)); + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public void write(Writer w) throws IOException { + int len = 8; + boolean firstAddress = true; + boolean needComma = false; + for (Address addr : list) { + java.lang.String s = addr.toHeaderString(); + if (firstAddress) { + firstAddress = false; + } else if (72 < len + s.length()) { + w.write(",\r\n\t"); + len = 8; + needComma = false; + } + + if (needComma) { + w.write(", "); + } + w.write(s); + len += s.length(); + needComma = true; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(list); + } + + @Override + public boolean equals(Object o) { + return (o instanceof AddressList) && Objects.equals(list, ((AddressList) o).list); + } + + @Override + public java.lang.String toString() { + return MoreObjects.toStringHelper(this).addValue(list).toString(); + } + } +} |