gecko-dev/grendel/storage/BerkeleyMessage.java

232 lines
8.1 KiB
Java

/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Grendel mail/news client.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1997
* Netscape Communications Corporation. All Rights Reserved.
*
* Created: Terry Weissman <terry@netscape.com>, 28 Aug 1997.
*
* Contributors: Will Scullin <scullin@meer.net>
*/
package grendel.storage;
import calypso.util.Assert;
import calypso.util.ByteBuf;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.InternetHeaders;
class BerkeleyMessage extends MessageBase {
int fIndex;
int fLength;
/* Note: these flag values are compatible with the X-Mozilla-Status
headers generated by Netscape Mail 2.0 through 4.0. Don't change
them.
Note also: Mozilla 2.0 and 3.0 can't read X-Mozilla-Status headers
that contain other than exactly 4 hex digits (16 bits.) If we
ever need to save more than 16 flags to the file, we will probably
have to do so incompatibly...
Think twice before adding a new flag here! Do you really need to
write it to X-Mozilla-Status? Is parsing it from another header
good enough? These flags are scarce, and once added, they can't
ever be removed without breaking old files.
*/
protected static final int X_MOZILLA_FLAG_READ = 0x0001;
protected static final int X_MOZILLA_FLAG_REPLIED = 0x0002; // since 4.0
protected static final int X_MOZILLA_FLAG_MARKED = 0x0004;
protected static final int X_MOZILLA_FLAG_DELETED = 0x0008;
protected static final int X_MOZILLA_FLAG_HAS_RE = 0x0010;
/* 0x0020, 0x0040, 0x0080, and 0x0100 are unused. */
protected static final int X_MOZILLA_FLAG_SMTP_AUTH = 0x0200; // since 4.0
protected static final int X_MOZILLA_FLAG_PARTIAL = 0x0400;
protected static final int X_MOZILLA_FLAG_QUEUED = 0x0800; // since 3.0?
protected static final int X_MOZILLA_FLAG_FORWARDED = 0x1000; // since 4.0
/* Note: this one is 3 bits. */
protected static final int X_MOZILLA_FLAG_PRIORITY = 0xE000; // since 4.0
BerkeleyMessage(BerkeleyFolder f, InternetHeaders h) {
super(f, h);
parseMozillaStatus(h);
}
BerkeleyMessage(BerkeleyFolder f,
long date,
long flags,
ByteBuf author,
ByteBuf recipient,
ByteBuf subj,
ByteBuf id,
ByteBuf refs[]) {
super(f, date, flags, author, recipient, subj, id, refs);
}
BerkeleyMessage(BerkeleyFolder f,
long date,
long flags,
ByteBuf author,
ByteBuf recipient,
ByteBuf subj,
MessageID id,
MessageID refs[]) {
super(f, date, flags, author, recipient, subj, id, refs);
}
protected void parseMozillaStatus(InternetHeaders h) {
int xms = 0;
String hh[] = h.getHeader("X-Mozilla-Status");
if (hh != null && hh.length != 0) {
byte value[] = hh[0].trim().getBytes();
/* sucks that we can't use Short.parseShort(buf, 16). */
for (int i = 0; i < value.length; i++) {
byte b = value[i];
if (b >= '0' && b <= '9') xms = (xms << 4) | (b - '0');
else if (b >= 'A' && b <= 'F') xms = (xms << 4) | (b - 'A' + 10);
else if (b >= 'a' && b <= 'f') xms = (xms << 4) | (b - 'a' + 10);
else { xms = 0; break; }
}
flags = mozillaFlagsToInternalFlags(xms);
}
}
/** Given a value read from an X-Mozilla-Status header, returns a
value suitable for storing in MessageBase.flags.
(The two types of flags don't use the same space or range.)
*/
static long mozillaFlagsToInternalFlags(long x_mozilla_status) {
long xms = x_mozilla_status;
long flags = 0;
if ((xms & X_MOZILLA_FLAG_READ) != 0) flags |= FLAG_READ;
if ((xms & X_MOZILLA_FLAG_REPLIED) != 0) flags |= FLAG_REPLIED;
if ((xms & X_MOZILLA_FLAG_MARKED) != 0) flags |= FLAG_MARKED;
if ((xms & X_MOZILLA_FLAG_DELETED) != 0) flags |= FLAG_DELETED;
if ((xms & X_MOZILLA_FLAG_HAS_RE) != 0) flags |= FLAG_HAS_RE;
if ((xms & X_MOZILLA_FLAG_SMTP_AUTH) != 0) flags |= FLAG_SMTP_AUTH;
if ((xms & X_MOZILLA_FLAG_PARTIAL) != 0) flags |= FLAG_PARTIAL;
if ((xms & X_MOZILLA_FLAG_QUEUED) != 0) flags |= FLAG_QUEUED;
if ((xms & X_MOZILLA_FLAG_FORWARDED) != 0) flags |= FLAG_FORWARDED;
/* if ((xms & X_MOZILLA_FLAG_PRIORITY) != 0) ... #### */
return flags;
}
/** Given a value of the form found in MessageBase.flags, returns a
value that may be written to an X-Mozilla-Flags header.
(The two types of flags don't use the same space or range.)
*/
static long internalFlagsToMozillaFlags(long internal_flags) {
long f = internal_flags;
long xms = 0;
if ((f & FLAG_READ) != 0) xms |= X_MOZILLA_FLAG_READ;
if ((f & FLAG_REPLIED) != 0) xms |= X_MOZILLA_FLAG_REPLIED;
if ((f & FLAG_MARKED) != 0) xms |= X_MOZILLA_FLAG_MARKED;
if ((f & FLAG_DELETED) != 0) xms |= X_MOZILLA_FLAG_DELETED;
if ((f & FLAG_HAS_RE) != 0) xms |= X_MOZILLA_FLAG_HAS_RE;
if ((f & FLAG_SMTP_AUTH) != 0) xms |= X_MOZILLA_FLAG_SMTP_AUTH;
if ((f & FLAG_PARTIAL) != 0) xms |= X_MOZILLA_FLAG_PARTIAL;
if ((f & FLAG_QUEUED) != 0) xms |= X_MOZILLA_FLAG_QUEUED;
if ((f & FLAG_FORWARDED) != 0) xms |= X_MOZILLA_FLAG_FORWARDED;
/* #### X_MOZILLA_FLAG_PRIORITY */
return xms;
}
/** Returns a reasonable value for the X-Mozilla-Status header of the
given Message. If the Message is a subclass of MessageBase, this
value will be based on MessageBase.flags; otherwise, we will go through
the painful string-based javamail API. (The Message may also be null.)
*/
static long makeMozillaFlags(Message m) {
long xms = 0;
if (m instanceof MessageBase) {
xms = internalFlagsToMozillaFlags(((MessageBase)m).flags);
} else if (m == null) {
xms = X_MOZILLA_FLAG_READ;
} else {
for (int i=0 ; i<FLAGDEFS.length ; i++) {
try {
Flags f = m.getFlags();
if (FLAGDEFS[i].builtin != null
? f.contains(FLAGDEFS[i].builtin)
: f.contains(FLAGDEFS[i].non_builtin)) {
xms |= FLAGDEFS[i].flag;
}
} catch (MessagingException e) { }
}
xms = internalFlagsToMozillaFlags(xms);
}
return xms;
}
void setSize(int l) {
fLength = l;
}
public int getSize() {
return fLength;
}
void setStorageFolderIndex(int p) {
fIndex = p;
}
int getStorageFolderIndex() {
return fIndex;
}
public InputStream getInputStreamWithHeaders()
throws MessagingException
{
BerkeleyFolder f = (BerkeleyFolder) getFolder();
try {
return new PartialFileInputStream(f.getFile(), getStorageFolderIndex(),
fLength);
} catch (IOException e) {
throw new MessagingException(e.toString());
}
}
protected void setFlagBit(long flag, boolean value) {
long oflags = flags;
super.setFlagBit(flag, value);
if (oflags != flags) {
setFlagsDirty(true);
((BerkeleyFolder) folder).setFlagsDirty(true, this, oflags);
}
}
public void writeTo(OutputStream aStream) {
Assert.NotYetImplemented("BerkeleyFolder.writeTo(IOStream)");
}
public int getLineCount() {
Assert.NotYetImplemented("BerkeleyFolder.getLineCount()");
return 0;
}
}