Add support for storing raw header fields

This commit is contained in:
cketti 2014-11-13 22:40:58 +01:00
parent 8630bb0ad4
commit bcb6c75c2e
6 changed files with 109 additions and 25 deletions

View File

@ -135,6 +135,9 @@ public abstract class Message implements Part, CompositeBody {
@Override
public abstract void addHeader(String name, String value) throws MessagingException;
@Override
public abstract void addRawHeader(String name, String raw) throws MessagingException;
@Override
public abstract void setHeader(String name, String value) throws MessagingException;

View File

@ -7,6 +7,8 @@ import java.io.OutputStream;
public interface Part {
public void addHeader(String name, String value) throws MessagingException;
public void addRawHeader(String name, String raw) throws MessagingException;
public void removeHeader(String name) throws MessagingException;
public void setHeader(String name, String value) throws MessagingException;

View File

@ -47,6 +47,11 @@ public class MimeBodyPart extends BodyPart {
mHeader.addHeader(name, value);
}
@Override
public void addRawHeader(String name, String raw) {
mHeader.addRawHeader(name, raw);
}
@Override
public void setHeader(String name, String value) {
mHeader.setHeader(name, value);

View File

@ -52,7 +52,13 @@ public class MimeHeader {
}
public void addHeader(String name, String value) {
mFields.add(new Field(name, MimeUtility.foldAndEncode(value)));
Field field = Field.newNameValueField(name, MimeUtility.foldAndEncode(value));
mFields.add(field);
}
void addRawHeader(String name, String raw) {
Field field = Field.newRawField(name, raw);
mFields.add(field);
}
public void setHeader(String name, String value) {
@ -66,7 +72,7 @@ public class MimeHeader {
public Set<String> getHeaderNames() {
Set<String> names = new LinkedHashSet<String>();
for (Field field : mFields) {
names.add(field.name);
names.add(field.getName());
}
return names;
}
@ -74,8 +80,8 @@ public class MimeHeader {
public String[] getHeader(String name) {
List<String> values = new ArrayList<String>();
for (Field field : mFields) {
if (field.name.equalsIgnoreCase(name)) {
values.add(field.value);
if (field.getName().equalsIgnoreCase(name)) {
values.add(field.getValue());
}
}
if (values.isEmpty()) {
@ -87,7 +93,7 @@ public class MimeHeader {
public void removeHeader(String name) {
List<Field> removeFields = new ArrayList<Field>();
for (Field field : mFields) {
if (field.name.equalsIgnoreCase(name)) {
if (field.getName().equalsIgnoreCase(name)) {
removeFields.add(field);
}
}
@ -97,27 +103,35 @@ public class MimeHeader {
public void writeTo(OutputStream out) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
for (Field field : mFields) {
if (!Utility.arrayContains(writeOmitFields, field.name)) {
String v = field.value;
if (hasToBeEncoded(v)) {
Charset charset = null;
if (mCharset != null) {
charset = Charset.forName(mCharset);
}
v = EncoderUtil.encodeEncodedWord(field.value, charset);
if (!Utility.arrayContains(writeOmitFields, field.getName())) {
if (field.hasRawData()) {
writer.write(field.getRaw());
} else {
writeNameValueField(writer, field);
}
writer.write(field.name);
writer.write(": ");
writer.write(v);
writer.write("\r\n");
}
}
writer.flush();
}
private void writeNameValueField(BufferedWriter writer, Field field) throws IOException {
String value = field.getValue();
if (hasToBeEncoded(value)) {
Charset charset = null;
if (mCharset != null) {
charset = Charset.forName(mCharset);
}
value = EncoderUtil.encodeEncodedWord(field.getValue(), charset);
}
writer.write(field.getName());
writer.write(": ");
writer.write(value);
}
// encode non printable characters except LF/CR/TAB codes.
private boolean hasToBeEncoded(String text) {
for (int i = 0; i < text.length(); i++) {
@ -133,19 +147,67 @@ public class MimeHeader {
private static class Field {
private final String name;
private final String value;
private final String raw;
public static Field newNameValueField(String name, String value) {
if (value == null) {
throw new NullPointerException("Argument 'value' cannot be null");
}
return new Field(name, value, null);
}
public static Field newRawField(String name, String raw) {
if (raw == null) {
throw new NullPointerException("Argument 'raw' cannot be null");
}
if (name != null && !raw.startsWith(name + ":")) {
throw new IllegalArgumentException("The value of 'raw' needs to start with the supplied field name " +
"followed by a colon");
}
return new Field(name, null, raw);
}
private Field(String name, String value, String raw) {
if (name == null) {
throw new NullPointerException("Argument 'name' cannot be null");
}
public Field(String name, String value) {
this.name = name;
this.value = value;
this.raw = raw;
}
public String getName() {
return name;
}
public String getValue() {
if (value != null) {
return value;
}
int delimiterIndex = raw.indexOf(':');
if (delimiterIndex == raw.length() - 1) {
return "";
}
return raw.substring(delimiterIndex + 1).trim();
}
public String getRaw() {
return raw;
}
public boolean hasRawData() {
return raw != null;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("(");
sb.append(name).append('=').append(value).append(')');
return sb.toString();
return (hasRawData()) ? getRaw() : getName() + ": " + getValue();
}
}

View File

@ -423,6 +423,11 @@ public class MimeMessage extends Message {
mHeader.addHeader(name, value);
}
@Override
public void addRawHeader(String name, String raw) {
mHeader.addRawHeader(name, raw);
}
@Override
public void setHeader(String name, String value) throws UnavailableStorageException {
mHeader.setHeader(name, value);
@ -598,7 +603,9 @@ public class MimeMessage extends Message {
public void field(Field parsedField) throws MimeException {
expect(Part.class);
try {
((Part)stack.peek()).addHeader(parsedField.getName(), parsedField.getBody().trim());
String name = parsedField.getName();
String raw = parsedField.getRaw().toString();
((Part) stack.peek()).addRawHeader(name, raw);
} catch (MessagingException me) {
throw new Error(me);
}

View File

@ -507,6 +507,11 @@ public class LocalMessage extends MimeMessage {
super.addHeader(name, value);
}
@Override
public void addRawHeader(String name, String raw) {
throw new RuntimeException("Not supported");
}
@Override
public void setHeader(String name, String value) throws UnavailableStorageException {
if (!mHeadersLoaded)