From 9fff57fa3180adfba8b2ab5ffa5edc6affbcd7d2 Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 15 Apr 2021 17:24:47 +0200 Subject: [PATCH] Revert "Added mbox" This reverts commit a0a7f6010b3248f15b407e1a6252a6fc82d1ee50. --- .../sun/mail/mbox/ContentLengthCounter.java | 75 -- .../sun/mail/mbox/ContentLengthUpdater.java | 116 -- .../com/sun/mail/mbox/DefaultMailbox.java | 106 -- .../java/com/sun/mail/mbox/FileInterface.java | 143 -- .../java/com/sun/mail/mbox/InboxFile.java | 22 - .../java/com/sun/mail/mbox/LineCounter.java | 64 - .../main/java/com/sun/mail/mbox/MailFile.java | 26 - .../main/java/com/sun/mail/mbox/Mailbox.java | 29 - .../java/com/sun/mail/mbox/MboxFolder.java | 1164 ----------------- .../java/com/sun/mail/mbox/MboxMessage.java | 532 -------- .../java/com/sun/mail/mbox/MboxProvider.java | 29 - .../java/com/sun/mail/mbox/MboxStore.java | 113 -- .../java/com/sun/mail/mbox/MessageLoader.java | 285 ---- .../sun/mail/mbox/NewlineOutputStream.java | 94 -- .../com/sun/mail/mbox/SolarisMailbox.java | 81 -- .../java/com/sun/mail/mbox/SunOSMailbox.java | 20 - .../java/com/sun/mail/mbox/SunV3BodyPart.java | 314 ----- .../com/sun/mail/mbox/SunV3Multipart.java | 201 --- .../main/java/com/sun/mail/mbox/TempFile.java | 183 --- .../main/java/com/sun/mail/mbox/UNIXFile.java | 132 -- .../java/com/sun/mail/mbox/UNIXFolder.java | 74 -- .../java/com/sun/mail/mbox/UNIXInbox.java | 123 -- 22 files changed, 3926 deletions(-) delete mode 100644 app/src/main/java/com/sun/mail/mbox/ContentLengthCounter.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/ContentLengthUpdater.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/DefaultMailbox.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/FileInterface.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/InboxFile.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/LineCounter.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/MailFile.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/Mailbox.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/MboxFolder.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/MboxMessage.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/MboxProvider.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/MboxStore.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/MessageLoader.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/NewlineOutputStream.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/SolarisMailbox.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/SunOSMailbox.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/SunV3BodyPart.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/SunV3Multipart.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/TempFile.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/UNIXFile.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/UNIXFolder.java delete mode 100644 app/src/main/java/com/sun/mail/mbox/UNIXInbox.java diff --git a/app/src/main/java/com/sun/mail/mbox/ContentLengthCounter.java b/app/src/main/java/com/sun/mail/mbox/ContentLengthCounter.java deleted file mode 100644 index f01aa592d8..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/ContentLengthCounter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; - -/** - * Count the number of bytes in the body of the message written to the stream. - */ -class ContentLengthCounter extends OutputStream { - private long size = 0; - private boolean inHeader = true; - private int lastb1 = -1, lastb2 = -1; - - public void write(int b) throws IOException { - if (inHeader) { - // if line terminator is CR - if (b == '\r' && lastb1 == '\r') - inHeader = false; - else if (b == '\n') { - // if line terminator is \n - if (lastb1 == '\n') - inHeader = false; - // if line terminator is CRLF - else if (lastb1 == '\r' && lastb2 == '\n') - inHeader = false; - } - lastb2 = lastb1; - lastb1 = b; - } else - size++; - } - - public void write(byte[] b) throws IOException { - if (inHeader) - super.write(b); - else - size += b.length; - } - - public void write(byte[] b, int off, int len) throws IOException { - if (inHeader) - super.write(b, off, len); - else - size += len; - } - - public long getSize() { - return size; - } - - /* - public static void main(String argv[]) throws Exception { - int b; - ContentLengthCounter os = new ContentLengthCounter(); - while ((b = System.in.read()) >= 0) - os.write(b); - System.out.println("size " + os.getSize()); - } - */ -} diff --git a/app/src/main/java/com/sun/mail/mbox/ContentLengthUpdater.java b/app/src/main/java/com/sun/mail/mbox/ContentLengthUpdater.java deleted file mode 100644 index b6d4408f21..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/ContentLengthUpdater.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; - -/** - * Update the Content-Length header in the message written to the stream. - */ -class ContentLengthUpdater extends FilterOutputStream { - private String contentLength; - private boolean inHeader = true; - private boolean sawContentLength = false; - private int lastb1 = -1, lastb2 = -1; - private StringBuilder line = new StringBuilder(); - - public ContentLengthUpdater(OutputStream os, long contentLength) { - super(os); - this.contentLength = "Content-Length: " + contentLength; - } - - public void write(int b) throws IOException { - if (inHeader) { - String eol = "\n"; - // First, determine if we're still in the header. - if (b == '\r') { - // if line terminator is CR - if (lastb1 == '\r') { - inHeader = false; - eol = "\r"; - // else, if line terminator is CRLF - } else if (lastb1 == '\n' && lastb2 == '\r') { - inHeader = false; - eol = "\r\n"; - } - // else, if line terminator is \n - } else if (b == '\n') { - if (lastb1 == '\n') { - inHeader = false; - eol = "\n"; - } - } - - // If we're no longer in the header, and we haven't seen - // a Content-Length header yet, it's time to put one out. - if (!inHeader && !sawContentLength) { - out.write(contentLength.getBytes("iso-8859-1")); - out.write(eol.getBytes("iso-8859-1")); - } - - // If we have a full line, see if it's a Content-Length header. - if (b == '\r' || (b == '\n' && lastb1 != '\r')) { - if (line.toString().regionMatches(true, 0, - "content-length:", 0, 15)) { - // yup, got it - sawContentLength = true; - // put out the new version - out.write(contentLength.getBytes("iso-8859-1")); - } else { - // not a Content-Length header, just write it out - out.write(line.toString().getBytes("iso-8859-1")); - } - line.setLength(0); // clear buffer for next line - } - if (b == '\r' || b == '\n') - out.write(b); // write out line terminator immediately - else - line.append((char)b); // accumulate characters of the line - - // rotate saved characters for next time through loop - lastb2 = lastb1; - lastb1 = b; - } else - out.write(b); // not in the header, just write it out - } - - public void write(byte[] b) throws IOException { - if (inHeader) - write(b, 0, b.length); - else - out.write(b); - } - - public void write(byte[] b, int off, int len) throws IOException { - if (inHeader) { - for (int i = 0 ; i < len ; i++) { - write(b[off + i]); - } - } else - out.write(b, off, len); - } - - // for testing - public static void main(String argv[]) throws Exception { - int b; - ContentLengthUpdater os = - new ContentLengthUpdater(System.out, Long.parseLong(argv[0])); - while ((b = System.in.read()) >= 0) - os.write(b); - os.flush(); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/DefaultMailbox.java b/app/src/main/java/com/sun/mail/mbox/DefaultMailbox.java deleted file mode 100644 index bac0b05765..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/DefaultMailbox.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; - -public class DefaultMailbox extends Mailbox { - private final String home; - - private static final boolean homeRelative = - Boolean.getBoolean("mail.mbox.homerelative"); - - public DefaultMailbox() { - home = System.getProperty("user.home"); - } - - public MailFile getMailFile(String user, String folder) { - return new DefaultMailFile(filename(user, folder)); - } - - public String filename(String user, String folder) { - try { - char c = folder.charAt(0); - if (c == File.separatorChar) { - return folder; - } else if (c == '~') { - int i = folder.indexOf(File.separatorChar); - String tail = ""; - if (i > 0) { - tail = folder.substring(i); - folder = folder.substring(0, i); - } - return home + tail; - } else { - if (folder.equalsIgnoreCase("INBOX")) - folder = "INBOX"; - if (homeRelative) - return home + File.separator + folder; - else - return folder; - } - } catch (StringIndexOutOfBoundsException e) { - return folder; - } - } -} - -class DefaultMailFile extends File implements MailFile { - protected transient RandomAccessFile file; - - private static final long serialVersionUID = 3713116697523761684L; - - DefaultMailFile(String name) { - super(name); - } - - public boolean lock(String mode) { - try { - file = new RandomAccessFile(this, mode); - return true; - } catch (FileNotFoundException fe) { - return false; - } catch (IOException ie) { - file = null; - return false; - } - } - - public void unlock() { - if (file != null) { - try { - file.close(); - } catch (IOException e) { - // ignore it - } - file = null; - } - } - - public void touchlock() { - } - - public FileDescriptor getFD() { - if (file == null) - return null; - try { - return file.getFD(); - } catch (IOException e) { - return null; - } - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/FileInterface.java b/app/src/main/java/com/sun/mail/mbox/FileInterface.java deleted file mode 100644 index 891f0d5514..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/FileInterface.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.File; -import java.io.FilenameFilter; - -public interface FileInterface { - /** - * Gets the name of the file. This method does not include the - * directory. - * @return the file name. - */ - public String getName(); - - /** - * Gets the path of the file. - * @return the file path. - */ - public String getPath(); - - /** - * Gets the absolute path of the file. - * @return the absolute file path. - */ - public String getAbsolutePath(); - - /** - * Gets the official, canonical path of the File. - * @return canonical path - */ - // XXX - JDK1.1 - // public String getCanonicalPath(); - - /** - * Gets the name of the parent directory. - * @return the parent directory, or null if one is not found. - */ - public String getParent(); - - /** - * Returns a boolean indicating whether or not a file exists. - */ - public boolean exists(); - - /** - * Returns a boolean indicating whether or not a writable file - * exists. - */ - public boolean canWrite(); - - /** - * Returns a boolean indicating whether or not a readable file - * exists. - */ - public boolean canRead(); - - /** - * Returns a boolean indicating whether or not a normal file - * exists. - */ - public boolean isFile(); - - /** - * Returns a boolean indicating whether or not a directory file - * exists. - */ - public boolean isDirectory(); - - /** - * Returns a boolean indicating whether the file name is absolute. - */ - public boolean isAbsolute(); - - /** - * Returns the last modification time. The return value should - * only be used to compare modification dates. It is meaningless - * as an absolute time. - */ - public long lastModified(); - - /** - * Returns the length of the file. - */ - public long length(); - - /** - * Creates a directory and returns a boolean indicating the - * success of the creation. Will return false if the directory already - * exists. - */ - public boolean mkdir(); - - /** - * Renames a file and returns a boolean indicating whether - * or not this method was successful. - * @param dest the new file name - */ - public boolean renameTo(File dest); - - /** - * Creates all directories in this path. This method - * returns true if the target (deepest) directory was created, - * false if the target directory was not created (e.g., if it - * existed previously). - */ - public boolean mkdirs(); - - /** - * Lists the files in a directory. Works only on directories. - * @return an array of file names. This list will include all - * files in the directory except the equivalent of "." and ".." . - */ - public String[] list(); - - /** - * Uses the specified filter to list files in a directory. - * @param filter the filter used to select file names - * @return the filter selected files in this directory. - * @see FilenameFilter - */ - public String[] list(FilenameFilter filter); - - /** - * Deletes the specified file. Returns true - * if the file could be deleted. - */ - public boolean delete(); -} diff --git a/app/src/main/java/com/sun/mail/mbox/InboxFile.java b/app/src/main/java/com/sun/mail/mbox/InboxFile.java deleted file mode 100644 index e4fffd5f60..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/InboxFile.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -public interface InboxFile extends MailFile { - public boolean openLock(String mode); - public void closeLock(); -} diff --git a/app/src/main/java/com/sun/mail/mbox/LineCounter.java b/app/src/main/java/com/sun/mail/mbox/LineCounter.java deleted file mode 100644 index 1ae4084f90..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/LineCounter.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; - -/** - * Count number of lines output. - */ -class LineCounter extends FilterOutputStream { - private int lastb = -1; - protected int lineCount; - - public LineCounter(OutputStream os) { - super(os); - } - - public void write(int b) throws IOException { - // If we have a full line, count it. - if (b == '\r' || (b == '\n' && lastb != '\r')) - lineCount++; - out.write(b); - lastb = b; - } - - public void write(byte[] b) throws IOException { - write(b, 0, b.length); - } - - public void write(byte[] b, int off, int len) throws IOException { - for (int i = 0 ; i < len ; i++) { - write(b[off + i]); - } - } - - public int getLineCount() { - return lineCount; - } - - // for testing - public static void main(String argv[]) throws Exception { - int b; - LineCounter os = - new LineCounter(System.out); - while ((b = System.in.read()) >= 0) - os.write(b); - os.flush(); - System.out.println(os.getLineCount()); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/MailFile.java b/app/src/main/java/com/sun/mail/mbox/MailFile.java deleted file mode 100644 index f790fced83..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/MailFile.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.FileDescriptor; - -public interface MailFile extends FileInterface { - public boolean lock(String mode); - public void unlock(); - public void touchlock(); - public FileDescriptor getFD(); -} diff --git a/app/src/main/java/com/sun/mail/mbox/Mailbox.java b/app/src/main/java/com/sun/mail/mbox/Mailbox.java deleted file mode 100644 index b902121c92..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/Mailbox.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -public abstract class Mailbox { - /** - * Return a MailFile object for the specified user's folder. - */ - public abstract MailFile getMailFile(String user, String folder); - - /** - * Return the file name corresponding to a folder with the given name. - */ - public abstract String filename(String user, String folder); -} diff --git a/app/src/main/java/com/sun/mail/mbox/MboxFolder.java b/app/src/main/java/com/sun/mail/mbox/MboxFolder.java deleted file mode 100644 index 340b84ff02..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/MboxFolder.java +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import javax.mail.*; -import javax.mail.event.*; -import javax.mail.internet.*; -import javax.mail.util.*; -import java.io.*; -import java.util.*; -import com.sun.mail.util.LineInputStream; - -/** - * This class represents a mailbox file containing RFC822 style email messages. - * - * @author John Mani - * @author Bill Shannon - */ - -public class MboxFolder extends Folder { - - private String name; // null => the default folder - private boolean is_inbox = false; - private int total; // total number of messages in mailbox - private volatile boolean opened = false; - private List messages; - private TempFile temp; - private MboxStore mstore; - private MailFile folder; - private long file_size; // the size the last time we read or wrote it - private long saved_file_size; // size at the last open, close, or expunge - private boolean special_imap_message; - - private static final boolean homeRelative = - Boolean.getBoolean("mail.mbox.homerelative"); - - /** - * Metadata for each message, to avoid instantiating MboxMessage - * objects for messages we're not going to look at.

- * - * MboxFolder keeps an array of these objects corresponding to - * each message in the folder. Access to the array elements is - * synchronized, but access to contents of this object is not. - * The metadata stored here is only accessed if the message field - * is null; otherwise the MboxMessage object contains the metadata. - */ - static final class MessageMetadata { - public long start; // offset in temp file of start of this message - // public long end; // offset in temp file of end of this message - public long dataend; // offset of end of message data, <= "end" - public MboxMessage message; // the message itself - public boolean recent; // message is recent? - public boolean deleted; // message is marked deleted? - public boolean imap; // special imap message? - } - - public MboxFolder(MboxStore store, String name) { - super(store); - this.mstore = store; - this.name = name; - - if (name != null && name.equalsIgnoreCase("INBOX")) - is_inbox = true; - - folder = mstore.getMailFile(name == null ? "~" : name); - if (folder.exists()) - saved_file_size = folder.length(); - else - saved_file_size = -1; - } - - public char getSeparator() { - return File.separatorChar; - } - - public Folder[] list(String pattern) throws MessagingException { - if (!folder.isDirectory()) - throw new MessagingException("not a directory"); - - if (name == null) - return list(null, pattern, true); - else - return list(name + File.separator, pattern, false); - } - - /* - * Version of list shared by MboxStore and MboxFolder. - */ - protected Folder[] list(String ref, String pattern, boolean fromStore) - throws MessagingException { - if (ref != null && ref.length() == 0) - ref = null; - int i; - String refdir = null; - String realdir = null; - - pattern = canonicalize(ref, pattern); - if ((i = indexOfAny(pattern, "%*")) >= 0) { - refdir = pattern.substring(0, i); - } else { - refdir = pattern; - } - if ((i = refdir.lastIndexOf(File.separatorChar)) >= 0) { - // get rid of anything after directory name - refdir = refdir.substring(0, i + 1); - realdir = mstore.mb.filename(mstore.user, refdir); - } else if (refdir.length() == 0 || refdir.charAt(0) != '~') { - // no separator and doesn't start with "~" => home or cwd - refdir = null; - if (homeRelative) - realdir = mstore.home; - else - realdir = "."; - } else { - realdir = mstore.mb.filename(mstore.user, refdir); - } - List flist = new ArrayList(); - listWork(realdir, refdir, pattern, fromStore ? 0 : 1, flist); - if (Match.path("INBOX", pattern, '\0')) - flist.add("INBOX"); - - Folder fl[] = new Folder[flist.size()]; - for (i = 0; i < fl.length; i++) { - fl[i] = createFolder(mstore, flist.get(i)); - } - return fl; - } - - public String getName() { - if (name == null) - return ""; - else if (is_inbox) - return "INBOX"; - else - return folder.getName(); - } - - public String getFullName() { - if (name == null) - return ""; - else - return name; - } - - public Folder getParent() { - if (name == null) - return null; - else if (is_inbox) - return createFolder(mstore, null); - else - // XXX - have to recognize other folders under default folder - return createFolder(mstore, folder.getParent()); - } - - public boolean exists() { - return folder.exists(); - } - - public int getType() { - if (folder.isDirectory()) - return HOLDS_FOLDERS; - else - return HOLDS_MESSAGES; - } - - public Flags getPermanentFlags() { - return MboxStore.permFlags; - } - - public synchronized boolean hasNewMessages() { - if (folder instanceof UNIXFile) { - UNIXFile f = (UNIXFile)folder; - if (f.length() > 0) { - long atime = f.lastAccessed(); - long mtime = f.lastModified(); -//System.out.println(name + " atime " + atime + " mtime " + mtime); - return atime < mtime; - } - return false; - } - long current_size; - if (folder.exists()) - current_size = folder.length(); - else - current_size = -1; - // if we've never opened the folder, remember the size now - // (will cause us to return false the first time) - if (saved_file_size < 0) - saved_file_size = current_size; - return current_size > saved_file_size; - } - - public synchronized Folder getFolder(String name) - throws MessagingException { - if (folder.exists() && !folder.isDirectory()) - throw new MessagingException("not a directory"); - return createFolder(mstore, - (this.name == null ? "~" : this.name) + File.separator + name); - } - - public synchronized boolean create(int type) throws MessagingException { - switch (type) { - case HOLDS_FOLDERS: - if (!folder.mkdirs()) { - return false; - } - break; - - case HOLDS_MESSAGES: - if (folder.exists()) { - return false; - } - try { - (new FileOutputStream((File)folder)).close(); - } catch (FileNotFoundException fe) { - File parent = new File(folder.getParent()); - if (!parent.mkdirs()) - throw new - MessagingException("can't create folder: " + name); - try { - (new FileOutputStream((File)folder)).close(); - } catch (IOException ex3) { - throw new - MessagingException("can't create folder: " + name, ex3); - } - } catch (IOException e) { - throw new - MessagingException("can't create folder: " + name, e); - } - break; - - default: - throw new MessagingException("type not supported"); - } - notifyFolderListeners(FolderEvent.CREATED); - return true; - } - - public synchronized boolean delete(boolean recurse) - throws MessagingException { - checkClosed(); - if (name == null) - throw new MessagingException("can't delete default folder"); - boolean ret = true; - if (recurse && folder.isDirectory()) - ret = delete(new File(folder.getPath())); - if (ret && folder.delete()) { - notifyFolderListeners(FolderEvent.DELETED); - return true; - } - return false; - } - - /** - * Recursively delete the specified file/directory. - */ - private boolean delete(File f) { - File[] files = f.listFiles(); - boolean ret = true; - for (int i = 0; ret && i < files.length; i++) { - if (files[i].isDirectory()) - ret = delete(files[i]); - else - ret = files[i].delete(); - } - return ret; - } - - public synchronized boolean renameTo(Folder f) - throws MessagingException { - checkClosed(); - if (name == null) - throw new MessagingException("can't rename default folder"); - if (!(f instanceof MboxFolder)) - throw new MessagingException("can't rename to: " + f.getName()); - String newname = ((MboxFolder)f).folder.getPath(); - if (folder.renameTo(new File(newname))) { - notifyFolderRenamedListeners(f); - return true; - } - return false; - } - - /* Ensure the folder is open */ - void checkOpen() throws IllegalStateException { - if (!opened) - throw new IllegalStateException("Folder is not Open"); - } - - /* Ensure the folder is not open */ - private void checkClosed() throws IllegalStateException { - if (opened) - throw new IllegalStateException("Folder is Open"); - } - - /* - * Check that the given message number is within the range - * of messages present in this folder. If the message - * number is out of range, we check to see if new messages - * have arrived. - */ - private void checkRange(int msgno) throws MessagingException { - if (msgno < 1) // message-numbers start at 1 - throw new IndexOutOfBoundsException("message number < 1"); - - if (msgno <= total) - return; - - // Out of range, let's check if there are any new messages. - getMessageCount(); - - if (msgno > total) // Still out of range ? Throw up ... - throw new IndexOutOfBoundsException(msgno + " > " + total); - } - - /* Ensure the folder is open & readable */ - private void checkReadable() throws IllegalStateException { - if (!opened || (mode != READ_ONLY && mode != READ_WRITE)) - throw new IllegalStateException("Folder is not Readable"); - } - - /* Ensure the folder is open & writable */ - private void checkWritable() throws IllegalStateException { - if (!opened || mode != READ_WRITE) - throw new IllegalStateException("Folder is not Writable"); - } - - public boolean isOpen() { - return opened; - } - - /* - * Open the folder in the specified mode. - */ - public synchronized void open(int mode) throws MessagingException { - if (opened) - throw new IllegalStateException("Folder is already Open"); - - if (!folder.exists()) - throw new FolderNotFoundException(this, "Folder doesn't exist: " + - folder.getPath()); - this.mode = mode; - switch (mode) { - case READ_WRITE: - default: - if (!folder.canWrite()) - throw new MessagingException("Open Failure, can't write: " + - folder.getPath()); - // fall through... - - case READ_ONLY: - if (!folder.canRead()) - throw new MessagingException("Open Failure, can't read: " + - folder.getPath()); - break; - } - - if (is_inbox && folder instanceof InboxFile) { - InboxFile inf = (InboxFile)folder; - if (!inf.openLock(mode == READ_WRITE ? "rw" : "r")) - throw new MessagingException("Failed to lock INBOX"); - } - if (!folder.lock("r")) - throw new MessagingException("Failed to lock folder: " + name); - messages = new ArrayList(); - total = 0; - Message[] msglist = null; - try { - temp = new TempFile(null); - saved_file_size = folder.length(); - msglist = load(0L, false); - } catch (IOException e) { - throw new MessagingException("IOException", e); - } finally { - folder.unlock(); - } - notifyConnectionListeners(ConnectionEvent.OPENED); - if (msglist != null) - notifyMessageAddedListeners(msglist); - opened = true; // now really opened - } - - public synchronized void close(boolean expunge) throws MessagingException { - checkOpen(); - - try { - if (mode == READ_WRITE) { - try { - writeFolder(true, expunge); - } catch (IOException e) { - throw new MessagingException("I/O Exception", e); - } - } - messages = null; - } finally { - opened = false; - if (is_inbox && folder instanceof InboxFile) { - InboxFile inf = (InboxFile)folder; - inf.closeLock(); - } - temp.close(); - temp = null; - notifyConnectionListeners(ConnectionEvent.CLOSED); - } - } - - /** - * Re-write the folder with the current contents of the messages. - * If closing is true, turn off the RECENT flag. If expunge is - * true, don't write out deleted messages (only used from close() - * when the message cache won't be accessed again). - * - * Return the number of messages written. - */ - protected int writeFolder(boolean closing, boolean expunge) - throws IOException, MessagingException { - - /* - * First, see if there have been any changes. - */ - int modified = 0, deleted = 0, recent = 0; - for (int msgno = 1; msgno <= total; msgno++) { - MessageMetadata md = messages.get(messageIndexOf(msgno)); - MboxMessage msg = md.message; - if (msg != null) { - Flags flags = msg.getFlags(); - if (msg.isModified() || !msg.origFlags.equals(flags)) - modified++; - if (flags.contains(Flags.Flag.DELETED)) - deleted++; - if (flags.contains(Flags.Flag.RECENT)) - recent++; - } else { - if (md.deleted) - deleted++; - if (md.recent) - recent++; - } - } - if ((!closing || recent == 0) && (!expunge || deleted == 0) && - modified == 0) - return 0; - - /* - * Have to save any new mail that's been appended to the - * folder since we last loaded it. - */ - if (!folder.lock("rw")) - throw new MessagingException("Failed to lock folder: " + name); - int oldtotal = total; // XXX - Message[] msglist = null; - if (folder.length() != file_size) - msglist = load(file_size, !closing); - // don't use the folder's FD, need to re-open in order to trunc the file - OutputStream os = - new BufferedOutputStream(new FileOutputStream((File)folder)); - int wr = 0; - boolean keep = true; - try { - if (special_imap_message) - appendStream(getMessageStream(0), os); - for (int msgno = 1; msgno <= total; msgno++) { - MessageMetadata md = messages.get(messageIndexOf(msgno)); - MboxMessage msg = md.message; - if (msg != null) { - if (expunge && msg.isSet(Flags.Flag.DELETED)) - continue; // skip it; - if (closing && msgno <= oldtotal && - msg.isSet(Flags.Flag.RECENT)) - msg.setFlag(Flags.Flag.RECENT, false); - writeMboxMessage(msg, os); - } else { - if (expunge && md.deleted) - continue; // skip it; - if (closing && msgno <= oldtotal && md.recent) { - // have to instantiate message so that we can - // clear the recent flag - msg = (MboxMessage)getMessage(msgno); - msg.setFlag(Flags.Flag.RECENT, false); - writeMboxMessage(msg, os); - } else { - appendStream(getMessageStream(msgno), os); - } - } - folder.touchlock(); - wr++; - } - // If no messages in the mailbox, and we're closing, - // maybe we should remove the mailbox. - if (wr == 0 && closing) { - String skeep = ((MboxStore)store).getSession(). - getProperty("mail.mbox.deleteEmpty"); - if (skeep != null && skeep.equalsIgnoreCase("true")) - keep = false; - } - } catch (IOException e) { - throw e; - } catch (MessagingException e) { - throw e; - } catch (Exception e) { -e.printStackTrace(); - throw new MessagingException("unexpected exception " + e); - } finally { - // close the folder, flushing out the data - try { - os.close(); - file_size = saved_file_size = folder.length(); - if (!keep) { - folder.delete(); - file_size = 0; - } - } catch (IOException ex) {} - - if (keep) { - // make sure the access time is greater than the mod time - // XXX - would be nice to have utime() - try { - Thread.sleep(1000); // sleep for a second - } catch (InterruptedException ex) {} - InputStream is = null; - try { - is = new FileInputStream((File)folder); - is.read(); // read a byte - } catch (IOException ex) {} // ignore errors - try { - if (is != null) - is.close(); - is = null; - } catch (IOException ex) {} // ignore errors - } - - folder.unlock(); - if (msglist != null) - notifyMessageAddedListeners(msglist); - } - return wr; - } - - /** - * Append the input stream to the output stream, closing the - * input stream when done. - */ - private static final void appendStream(InputStream is, OutputStream os) - throws IOException { - try { - byte[] buf = new byte[64 * 1024]; - int len; - while ((len = is.read(buf)) > 0) - os.write(buf, 0, len); - } finally { - is.close(); - } - } - - /** - * Write a MimeMessage to the specified OutputStream in a - * format suitable for a UNIX mailbox, i.e., including a correct - * Content-Length header and with the local platform's line - * terminating convention.

- * - * If the message is really a MboxMessage, use its writeToFile - * method, which has access to the UNIX From line. Otherwise, do - * all the work here, creating an appropriate UNIX From line. - */ - public static void writeMboxMessage(MimeMessage msg, OutputStream os) - throws IOException, MessagingException { - try { - if (msg instanceof MboxMessage) { - ((MboxMessage)msg).writeToFile(os); - } else { - // XXX - modify the message to preserve the flags in headers - MboxMessage.setHeadersFromFlags(msg); - ContentLengthCounter cos = new ContentLengthCounter(); - NewlineOutputStream nos = new NewlineOutputStream(cos); - msg.writeTo(nos); - nos.flush(); - os = new NewlineOutputStream(os, true); - os = new ContentLengthUpdater(os, cos.getSize()); - PrintStream pos = new PrintStream(os, false, "iso-8859-1"); - pos.println(getUnixFrom(msg)); - msg.writeTo(pos); - pos.flush(); - } - } catch (MessagingException me) { - throw me; - } catch (IOException ioe) { - throw ioe; - } - } - - /** - * Construct an appropriately formatted UNIX From line using - * the sender address and the date in the message. - */ - protected static String getUnixFrom(MimeMessage msg) { - Address[] afrom; - String from; - Date ddate; - String date; - try { - if ((afrom = msg.getFrom()) == null || - !(afrom[0] instanceof InternetAddress) || - (from = ((InternetAddress)afrom[0]).getAddress()) == null) - from = "UNKNOWN"; - if ((ddate = msg.getReceivedDate()) == null || - (ddate = msg.getSentDate()) == null) - ddate = new Date(); - } catch (MessagingException e) { - from = "UNKNOWN"; - ddate = new Date(); - } - date = ddate.toString(); - // date is of the form "Sat Aug 12 02:30:00 PDT 1995" - // need to strip out the timezone - return "From " + from + " " + - date.substring(0, 20) + date.substring(24); - } - - public synchronized int getMessageCount() throws MessagingException { - if (!opened) - return -1; - - boolean locked = false; - Message[] msglist = null; - try { - if (folder.length() != file_size) { - if (!folder.lock("r")) - throw new MessagingException("Failed to lock folder: " + - name); - locked = true; - msglist = load(file_size, true); - } - } catch (IOException e) { - throw new MessagingException("I/O Exception", e); - } finally { - if (locked) { - folder.unlock(); - if (msglist != null) - notifyMessageAddedListeners(msglist); - } - } - return total; - } - - /** - * Get the specified message. Note that messages are numbered - * from 1. - */ - public synchronized Message getMessage(int msgno) - throws MessagingException { - checkReadable(); - checkRange(msgno); - - MessageMetadata md = messages.get(messageIndexOf(msgno)); - MboxMessage m = md.message; - if (m == null) { - InputStream is = getMessageStream(msgno); - try { - m = loadMessage(is, msgno, mode == READ_WRITE); - } catch (IOException ex) { - MessagingException mex = - new MessageRemovedException("mbox message gone", ex); - throw mex; - } - md.message = m; - } - return m; - } - - private final int messageIndexOf(int msgno) { - return special_imap_message ? msgno : msgno - 1; - } - - private InputStream getMessageStream(int msgno) { - int index = messageIndexOf(msgno); - MessageMetadata md = messages.get(index); - return temp.newStream(md.start, md.dataend); - } - - public synchronized void appendMessages(Message[] msgs) - throws MessagingException { - if (!folder.lock("rw")) - throw new MessagingException("Failed to lock folder: " + name); - - OutputStream os = null; - boolean err = false; - try { - os = new BufferedOutputStream( - new FileOutputStream(((File)folder).getPath(), true)); - // XXX - should use getAbsolutePath()? - for (int i = 0; i < msgs.length; i++) { - if (msgs[i] instanceof MimeMessage) { - writeMboxMessage((MimeMessage)msgs[i], os); - } else { - err = true; - continue; - } - folder.touchlock(); - } - } catch (IOException e) { - throw new MessagingException("I/O Exception", e); - } catch (MessagingException e) { - throw e; - } catch (Exception e) { -e.printStackTrace(); - throw new MessagingException("unexpected exception " + e); - } finally { - if (os != null) - try { - os.close(); - } catch (IOException e) { - // ignored - } - folder.unlock(); - } - if (opened) - getMessageCount(); // loads new messages as a side effect - if (err) - throw new MessagingException("Can't append non-Mime message"); - } - - public synchronized Message[] expunge() throws MessagingException { - checkWritable(); - - /* - * First, write out the folder to make sure we have permission, - * disk space, etc. - */ - int wr = total; // number of messages written out - try { - wr = writeFolder(false, true); - } catch (IOException e) { - throw new MessagingException("expunge failed", e); - } - if (wr == total) // wrote them all => nothing expunged - return new Message[0]; - - /* - * Now, actually get rid of the expunged messages. - */ - int del = 0; - Message[] msglist = new Message[total - wr]; - int msgno = 1; - while (msgno <= total) { - MessageMetadata md = messages.get(messageIndexOf(msgno)); - MboxMessage msg = md.message; - if (msg != null) { - if (msg.isSet(Flags.Flag.DELETED)) { - msg.setExpunged(true); - msglist[del] = msg; - del++; - messages.remove(messageIndexOf(msgno)); - total--; - } else { - msg.setMessageNumber(msgno); // update message number - msgno++; - } - } else { - if (md.deleted) { - // have to instantiate it for the notification - msg = (MboxMessage)getMessage(msgno); - msg.setExpunged(true); - msglist[del] = msg; - del++; - messages.remove(messageIndexOf(msgno)); - total--; - } else { - msgno++; - } - } - } - if (del != msglist.length) // this is really an assert - throw new MessagingException("expunge delete count wrong"); - notifyMessageRemovedListeners(true, msglist); - return msglist; - } - - /* - * Load more messages from the folder starting at the specified offset. - */ - private Message[] load(long offset, boolean notify) - throws MessagingException, IOException { - int oldtotal = total; - MessageLoader loader = new MessageLoader(temp); - int loaded = loader.load(folder.getFD(), offset, messages); - total += loaded; - file_size = folder.length(); - - if (offset == 0 && loaded > 0) { - /* - * If the first message is the special message that the - * IMAP server adds to the mailbox, remember that we've - * seen it so it won't be shown to the user. - */ - MessageMetadata md = messages.get(0); - if (md.imap) { - special_imap_message = true; - total--; - } - } - if (notify) { - Message[] msglist = new Message[total - oldtotal]; - for (int i = oldtotal, j = 0; i < total; i++, j++) - msglist[j] = getMessage(i + 1); - return msglist; - } else - return null; - } - - /** - * Parse the input stream and return an appropriate message object. - * The InputStream must be a SharedInputStream. - */ - private MboxMessage loadMessage(InputStream is, int msgno, - boolean writable) throws MessagingException, IOException { - LineInputStream in = new LineInputStream(is); - - /* - * Read lines until a UNIX From line, - * skipping blank lines. - */ - String line; - String unix_from = null; - while ((line = in.readLine()) != null) { - if (line.trim().length() == 0) - continue; - if (line.startsWith("From ")) { - /* - * A UNIX From line looks like: - * From address Day Mon DD HH:MM:SS YYYY - */ - unix_from = line; - int i; - // find the space after the address, before the date - i = unix_from.indexOf(' ', 5); - if (i < 0) - continue; // not a valid UNIX From line - break; - } - throw new MessagingException("Garbage in mailbox: " + line); - } - - if (unix_from == null) - throw new EOFException("end of mailbox"); - - /* - * Now load the RFC822 headers into an InternetHeaders object. - */ - InternetHeaders hdrs = new InternetHeaders(is); - - // the rest is the message content - SharedInputStream sis = (SharedInputStream)is; - InputStream stream = sis.newStream(sis.getPosition(), -1); - return new MboxMessage(this, hdrs, stream, msgno, unix_from, writable); - } - - /* - * Only here to make accessible to MboxMessage. - */ - protected void notifyMessageChangedListeners(int type, Message m) { - super.notifyMessageChangedListeners(type, m); - } - - - /** - * this is an exact duplicate of the Folder.getURL except it doesn't - * add a beginning '/' to the URLName. - */ - public URLName getURLName() { - // XXX - note: this should not be done this way with the - // new javax.mail apis. - - URLName storeURL = getStore().getURLName(); - if (name == null) - return storeURL; - - char separator = getSeparator(); - String fullname = getFullName(); - StringBuilder encodedName = new StringBuilder(); - - // We need to encode each of the folder's names, and replace - // the store's separator char with the URL char '/'. - StringTokenizer tok = new StringTokenizer( - fullname, Character.toString(separator), true); - - while (tok.hasMoreTokens()) { - String s = tok.nextToken(); - if (s.charAt(0) == separator) - encodedName.append("/"); - else - // XXX - should encode, but since there's no decoder... - //encodedName.append(java.net.URLEncoder.encode(s)); - encodedName.append(s); - } - - return new URLName(storeURL.getProtocol(), storeURL.getHost(), - storeURL.getPort(), encodedName.toString(), - storeURL.getUsername(), - null /* no password */); - } - - /** - * Create an MboxFolder object, or a subclass thereof. - * Can be overridden by subclasses of MboxFolder so that - * the appropriate subclass is created by the list method. - */ - protected Folder createFolder(MboxStore store, String name) { - return new MboxFolder(store, name); - } - - /* - * Support routines for list(). - */ - - /** - * Return a canonicalized pattern given a reference name and a pattern. - */ - private static String canonicalize(String ref, String pat) { - if (ref == null) - return pat; - try { - if (pat.length() == 0) { - return ref; - } else if (pat.charAt(0) == File.separatorChar) { - return ref.substring(0, ref.indexOf(File.separatorChar)) + pat; - } else { - return ref + pat; - } - } catch (StringIndexOutOfBoundsException e) { - return pat; - } - } - - /** - * Return the first index of any of the characters in "any" in "s", - * or -1 if none are found. - * - * This should be a method on String. - */ - private static int indexOfAny(String s, String any) { - try { - int len = s.length(); - for (int i = 0; i < len; i++) { - if (any.indexOf(s.charAt(i)) >= 0) - return i; - } - return -1; - } catch (StringIndexOutOfBoundsException e) { - return -1; - } - } - - /** - * The recursive part of generating the list of mailboxes. - * realdir is the full pathname to the directory to search. - * dir is the name the user uses, often a relative name that's - * relative to the user's home directory. dir (if not null) always - * has a trailing file separator character. - * - * @param realdir real pathname of directory to start looking in - * @param dir user's name for realdir - * @param pat pattern to match against - * @param level level of the directory hierarchy we're in - * @param flist list to which to add folder names that match - */ - // Derived from the c-client listWork() function. - private void listWork(String realdir, String dir, String pat, - int level, List flist) { - String sl[]; - File fdir = new File(realdir); - try { - sl = fdir.list(); - } catch (SecurityException e) { - return; // can't read it, ignore it - } - - if (level == 0 && dir != null && - Match.path(dir, pat, File.separatorChar)) - flist.add(dir); - - if (sl == null) - return; // nothing return, we're done - - if (realdir.charAt(realdir.length() - 1) != File.separatorChar) - realdir += File.separator; - - for (int i = 0; i < sl.length; i++) { - if (sl[i].charAt(0) == '.') - continue; // ignore all "dot" files for now - String md = realdir + sl[i]; - File mf = new File(md); - if (!mf.exists()) - continue; - String name; - if (dir != null) - name = dir + sl[i]; - else - name = sl[i]; - if (mf.isDirectory()) { - if (Match.path(name, pat, File.separatorChar)) { - flist.add(name); - name += File.separator; - } else { - name += File.separator; - if (Match.path(name, pat, File.separatorChar)) - flist.add(name); - } - if (Match.dir(name, pat, File.separatorChar)) - listWork(md, name, pat, level + 1, flist); - } else { - if (Match.path(name, pat, File.separatorChar)) - flist.add(name); - } - } - } -} - -/** - * Pattern matching support class for list(). - * Should probably be more public. - */ -// Translated from the c-client functions pmatch_full() and dmatch(). -class Match { - /** - * Pathname pattern match - * - * @param s base string - * @param pat pattern string - * @param delim delimiter character - * @return true if base matches pattern - */ - static public boolean path(String s, String pat, char delim) { - try { - return path(s, 0, s.length(), pat, 0, pat.length(), delim); - } catch (StringIndexOutOfBoundsException e) { - return false; - } - } - - static private boolean path(String s, int s_index, int s_len, - String pat, int p_index, int p_len, char delim) - throws StringIndexOutOfBoundsException { - - while (p_index < p_len) { - char c = pat.charAt(p_index); - switch (c) { - case '%': - if (++p_index >= p_len) // % at end of pattern - // ok if no delimiters - return delim == 0 || s.indexOf(delim, s_index) < 0; - // scan remainder until delimiter - do { - if (path(s, s_index, s_len, pat, p_index, p_len, delim)) - return true; - } while (s.charAt(s_index) != delim && ++s_index < s_len); - // ran into a delimiter or ran out of string without a match - return false; - - case '*': - if (++p_index >= p_len) // end of pattern? - return true; // unconditional match - do { - if (path(s, s_index, s_len, pat, p_index, p_len, delim)) - return true; - } while (++s_index < s_len); - // ran out of string without a match - return false; - - default: - // if ran out of string or no match, fail - if (s_index >= s_len || c != s.charAt(s_index)) - return false; - - // try the next string and pattern characters - s_index++; - p_index++; - } - } - return s_index >= s_len; - } - - /** - * Directory pattern match - * - * @param s base string - * @param pat pattern string - * @return true if base is a matching directory of pattern - */ - static public boolean dir(String s, String pat, char delim) { - try { - return dir(s, 0, s.length(), pat, 0, pat.length(), delim); - } catch (StringIndexOutOfBoundsException e) { - return false; - } - } - - static private boolean dir(String s, int s_index, int s_len, - String pat, int p_index, int p_len, char delim) - throws StringIndexOutOfBoundsException { - - while (p_index < p_len) { - char c = pat.charAt(p_index); - switch (c) { - case '%': - if (s_index >= s_len) // end of base? - return true; // subset match - if (++p_index >= p_len) // % at end of pattern? - return false; // no inferiors permitted - do { - if (dir(s, s_index, s_len, pat, p_index, p_len, delim)) - return true; - } while (s.charAt(s_index) != delim && ++s_index < s_len); - - if (s_index + 1 == s_len) // s ends with a delimiter - return true; // must be a subset of pattern - return dir(s, s_index, s_len, pat, p_index, p_len, delim); - - case '*': - return true; // unconditional match - - default: - if (s_index >= s_len) // end of base? - return c == delim; // matched if at delimiter - - if (c != s.charAt(s_index)) - return false; - - // try the next string and pattern characters - s_index++; - p_index++; - } - } - return s_index >= s_len; - } -} - -/** - * A ByteArrayOutputStream that allows us to share the byte array - * rather than copy it. Eventually could replace this with something - * that doesn't require a single contiguous byte array. - */ -class SharedByteArrayOutputStream extends ByteArrayOutputStream { - public SharedByteArrayOutputStream(int size) { - super(size); - } - - public InputStream toStream() { - return new SharedByteArrayInputStream(buf, 0, count); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/MboxMessage.java b/app/src/main/java/com/sun/mail/mbox/MboxMessage.java deleted file mode 100644 index db57a2652d..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/MboxMessage.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; -import java.util.StringTokenizer; -import java.util.Date; -import java.text.SimpleDateFormat; -import javax.activation.*; -import javax.mail.*; -import javax.mail.internet.*; -import javax.mail.event.MessageChangedEvent; -import com.sun.mail.util.LineInputStream; - -/** - * This class represents an RFC822 style email message that resides in a file. - * - * @author Bill Shannon - */ - -public class MboxMessage extends MimeMessage { - - boolean writable = false; - // original msg flags, used by MboxFolder to detect modification - Flags origFlags; - /* - * A UNIX From line looks like: - * From address Day Mon DD HH:MM:SS YYYY - */ - String unix_from; - InternetAddress unix_from_user; - Date rcvDate; - int lineCount = -1; - private static OutputStream nullOutputStream = new OutputStream() { - public void write(int b) { } - public void write(byte[] b, int off, int len) { } - }; - - /** - * Construct an MboxMessage from the InputStream. - */ - public MboxMessage(Session session, InputStream is) - throws MessagingException, IOException { - super(session); - BufferedInputStream bis; - if (is instanceof BufferedInputStream) - bis = (BufferedInputStream)is; - else - bis = new BufferedInputStream(is); - LineInputStream dis = new LineInputStream(bis); - bis.mark(1024); - String line = dis.readLine(); - if (line != null && line.startsWith("From ")) - this.unix_from = line; - else - bis.reset(); - parse(bis); - saved = true; - } - - /** - * Construct an MboxMessage using the given InternetHeaders object - * and content from an InputStream. - */ - public MboxMessage(MboxFolder folder, InternetHeaders hdrs, InputStream is, - int msgno, String unix_from, boolean writable) - throws MessagingException { - super(folder, hdrs, null, msgno); - setFlagsFromHeaders(); - origFlags = getFlags(); - this.unix_from = unix_from; - this.writable = writable; - this.contentStream = is; - } - - /** - * Returns the "From" attribute. The "From" attribute contains - * the identity of the person(s) who wished this message to - * be sent.

- * - * If our superclass doesn't have a value, we return the address - * from the UNIX From line. - * - * @return array of Address objects - * @exception MessagingException - */ - public Address[] getFrom() throws MessagingException { - Address[] ret = super.getFrom(); - if (ret == null) { - InternetAddress ia = getUnixFrom(); - if (ia != null) - ret = new InternetAddress[] { ia }; - } - return ret; - } - - /** - * Returns the address from the UNIX "From" line. - * - * @return UNIX From address - * @exception MessagingException - */ - public synchronized InternetAddress getUnixFrom() - throws MessagingException { - if (unix_from_user == null && unix_from != null) { - int i; - // find the space after the address, before the date - i = unix_from.indexOf(' ', 5); - if (i > 5) { - try { - unix_from_user = - new InternetAddress(unix_from.substring(5, i)); - } catch (AddressException e) { - // ignore it - } - } - } - return unix_from_user != null ? - (InternetAddress)unix_from_user.clone() : null; - } - - private String getUnixFromLine() { - if (unix_from != null) - return unix_from; - String from = "unknown"; - try { - Address[] froma = getFrom(); - if (froma != null && froma.length > 0 && - froma[0] instanceof InternetAddress) - from = ((InternetAddress)froma[0]).getAddress(); - } catch (MessagingException ex) { } - Date d = null; - try { - d = getSentDate(); - } catch (MessagingException ex) { - // ignore - } - if (d == null) - d = new Date(); - // From shannon Mon Jun 10 12:06:52 2002 - SimpleDateFormat fmt = new SimpleDateFormat("EEE LLL dd HH:mm:ss yyyy"); - return "From " + from + " " + fmt.format(d); - } - - /** - * Get the date this message was received, from the UNIX From line. - * - * @return the date this message was received - * @exception MessagingException - */ - @SuppressWarnings("deprecation") // for Date constructor - public Date getReceivedDate() throws MessagingException { - if (rcvDate == null && unix_from != null) { - int i; - // find the space after the address, before the date - i = unix_from.indexOf(' ', 5); - if (i > 5) { - try { - rcvDate = new Date(unix_from.substring(i)); - } catch (IllegalArgumentException iae) { - // ignore it - } - } - } - return rcvDate == null ? null : new Date(rcvDate.getTime()); - } - - /** - * Return the number of lines for the content of this message. - * Return -1 if this number cannot be determined.

- * - * Note that this number may not be an exact measure of the - * content length and may or may not account for any transfer - * encoding of the content.

- * - * This implementation returns -1. - * - * @return number of lines in the content. - * @exception MessagingException - */ - public int getLineCount() throws MessagingException { - if (lineCount < 0 && isMimeType("text/plain")) { - LineCounter lc = null; - // writeTo will set the SEEN flag, remember the original state - boolean seen = isSet(Flags.Flag.SEEN); - try { - lc = new LineCounter(nullOutputStream); - getDataHandler().writeTo(lc); - lineCount = lc.getLineCount(); - } catch (IOException ex) { - // ignore it, can't happen - } finally { - try { - if (lc != null) - lc.close(); - } catch (IOException ex) { - // can't happen - } - } - if (!seen) - setFlag(Flags.Flag.SEEN, false); - } - return lineCount; - } - - /** - * Set the specified flags on this message to the specified value. - * - * @param flags the flags to be set - * @param set the value to be set - */ - public void setFlags(Flags newFlags, boolean set) - throws MessagingException { - Flags oldFlags = (Flags)flags.clone(); - super.setFlags(newFlags, set); - if (!flags.equals(oldFlags)) { - setHeadersFromFlags(this); - if (folder != null) - ((MboxFolder)folder).notifyMessageChangedListeners( - MessageChangedEvent.FLAGS_CHANGED, this); - } - } - - /** - * Return the content type, mapping from SunV3 types to MIME types - * as necessary. - */ - public String getContentType() throws MessagingException { - String ct = super.getContentType(); - if (ct.indexOf('/') < 0) - ct = SunV3BodyPart.MimeV3Map.toMime(ct); - return ct; - } - - /** - * Produce the raw bytes of the content. This method is used during - * parsing, to create a DataHandler object for the content. Subclasses - * that can provide a separate input stream for just the message - * content might want to override this method.

- * - * This implementation just returns a ByteArrayInputStream constructed - * out of the content byte array. - * - * @see #content - */ - protected InputStream getContentStream() throws MessagingException { - if (folder != null) - ((MboxFolder)folder).checkOpen(); - if (isExpunged()) - throw new MessageRemovedException("mbox message expunged"); - if (!isSet(Flags.Flag.SEEN)) - setFlag(Flags.Flag.SEEN, true); - return super.getContentStream(); - } - - /** - * Return a DataHandler for this Message's content. - * If this is a SunV3 multipart message, handle it specially. - * - * @exception MessagingException - */ - public synchronized DataHandler getDataHandler() - throws MessagingException { - if (dh == null) { - // XXX - Following is a kludge to avoid having to register - // the "multipart/x-sun-attachment" data type with the JAF. - String ct = getContentType(); - if (ct.equalsIgnoreCase("multipart/x-sun-attachment")) - dh = new DataHandler( - new SunV3Multipart(new MimePartDataSource(this)), ct); - else - return super.getDataHandler(); // will set "dh" - } - return dh; - } - - // here only to allow package private access from MboxFolder - protected void setMessageNumber(int msgno) { - super.setMessageNumber(msgno); - } - - // here to synchronize access to expunged field - public synchronized boolean isExpunged() { - return super.isExpunged(); - } - - // here to synchronize and to allow access from MboxFolder - protected synchronized void setExpunged(boolean expunged) { - super.setExpunged(expunged); - } - - // XXX - We assume that only body parts that are part of a SunV3 - // multipart will use the SunV3 headers (X-Sun-Content-Length, - // X-Sun-Content-Lines, X-Sun-Data-Type, X-Sun-Encoding-Info, - // X-Sun-Data-Description, X-Sun-Data-Name) so we don't handle - // them here. - - /** - * Set the flags for this message based on the Status, - * X-Status, and X-Dt-Delete-Time headers. - * - * SIMS 2.0: - * "X-Status: DFAT", deleted, flagged, answered, draft. - * Unset flags represented as "$". - * User flags not supported. - * - * University of Washington IMAP server: - * "X-Status: DFAT", deleted, flagged, answered, draft. - * Unset flags not present. - * "X-Keywords: userflag1 userflag2" - */ - private synchronized void setFlagsFromHeaders() { - flags = new Flags(Flags.Flag.RECENT); - try { - String s = getHeader("Status", null); - if (s != null) { - if (s.indexOf('R') >= 0) - flags.add(Flags.Flag.SEEN); - if (s.indexOf('O') >= 0) - flags.remove(Flags.Flag.RECENT); - } - s = getHeader("X-Dt-Delete-Time", null); // set by dtmail - if (s != null) - flags.add(Flags.Flag.DELETED); - s = getHeader("X-Status", null); // set by IMAP server - if (s != null) { - if (s.indexOf('D') >= 0) - flags.add(Flags.Flag.DELETED); - if (s.indexOf('F') >= 0) - flags.add(Flags.Flag.FLAGGED); - if (s.indexOf('A') >= 0) - flags.add(Flags.Flag.ANSWERED); - if (s.indexOf('T') >= 0) - flags.add(Flags.Flag.DRAFT); - } - s = getHeader("X-Keywords", null); // set by IMAP server - if (s != null) { - StringTokenizer st = new StringTokenizer(s); - while (st.hasMoreTokens()) - flags.add(st.nextToken()); - } - } catch (MessagingException e) { - // ignore it - } - } - - /** - * Set the various header fields that represent the message flags. - */ - static void setHeadersFromFlags(MimeMessage msg) { - try { - Flags flags = msg.getFlags(); - StringBuilder status = new StringBuilder(); - if (flags.contains(Flags.Flag.SEEN)) - status.append('R'); - if (!flags.contains(Flags.Flag.RECENT)) - status.append('O'); - if (status.length() > 0) - msg.setHeader("Status", status.toString()); - else - msg.removeHeader("Status"); - - boolean sims = false; - String s = msg.getHeader("X-Status", null); - // is it a SIMS 2.0 format X-Status header? - sims = s != null && s.length() == 4 && s.indexOf('$') >= 0; - status.setLength(0); - if (flags.contains(Flags.Flag.DELETED)) - status.append('D'); - else if (sims) - status.append('$'); - if (flags.contains(Flags.Flag.FLAGGED)) - status.append('F'); - else if (sims) - status.append('$'); - if (flags.contains(Flags.Flag.ANSWERED)) - status.append('A'); - else if (sims) - status.append('$'); - if (flags.contains(Flags.Flag.DRAFT)) - status.append('T'); - else if (sims) - status.append('$'); - if (status.length() > 0) - msg.setHeader("X-Status", status.toString()); - else - msg.removeHeader("X-Status"); - - String[] userFlags = flags.getUserFlags(); - if (userFlags.length > 0) { - status.setLength(0); - for (int i = 0; i < userFlags.length; i++) - status.append(userFlags[i]).append(' '); - status.setLength(status.length() - 1); // smash trailing space - msg.setHeader("X-Keywords", status.toString()); - } - if (flags.contains(Flags.Flag.DELETED)) { - s = msg.getHeader("X-Dt-Delete-Time", null); - if (s == null) - // XXX - should be time - msg.setHeader("X-Dt-Delete-Time", "1"); - } - } catch (MessagingException e) { - // ignore it - } - } - - protected void updateHeaders() throws MessagingException { - super.updateHeaders(); - setHeadersFromFlags(this); - } - - /** - * Save any changes made to this message. - */ - public void saveChanges() throws MessagingException { - if (folder != null) - ((MboxFolder)folder).checkOpen(); - if (isExpunged()) - throw new MessageRemovedException("mbox message expunged"); - if (!writable) - throw new MessagingException("Message is read-only"); - - super.saveChanges(); - - try { - /* - * Count the size of the body, in order to set the Content-Length - * header. (Should we only do this to update an existing - * Content-Length header?) - * XXX - We could cache the content bytes here, for use later - * in writeTo. - */ - ContentLengthCounter cos = new ContentLengthCounter(); - OutputStream os = new NewlineOutputStream(cos); - super.writeTo(os); - os.flush(); - setHeader("Content-Length", String.valueOf(cos.getSize())); - // setContentSize((int)cos.getSize()); - } catch (MessagingException e) { - throw e; - } catch (Exception e) { - throw new MessagingException("unexpected exception " + e); - } - } - - /** - * Expose modified flag to MboxFolder. - */ - boolean isModified() { - return modified; - } - - /** - * Put out a byte stream suitable for saving to a file. - * XXX - ultimately implement "ignore headers" here? - */ - public void writeToFile(OutputStream os) throws IOException { - try { - if (getHeader("Content-Length") == null) { - /* - * Count the size of the body, in order to set the - * Content-Length header. - */ - ContentLengthCounter cos = new ContentLengthCounter(); - OutputStream oos = new NewlineOutputStream(cos); - super.writeTo(oos, null); - oos.flush(); - setHeader("Content-Length", String.valueOf(cos.getSize())); - // setContentSize((int)cos.getSize()); - } - - os = new NewlineOutputStream(os, true); - PrintStream pos = new PrintStream(os, false, "iso-8859-1"); - - pos.println(getUnixFromLine()); - super.writeTo(pos, null); - pos.flush(); - } catch (MessagingException e) { - throw new IOException("unexpected exception " + e); - } - } - - public void writeTo(OutputStream os, String[] ignoreList) - throws IOException, MessagingException { - // set the SEEN flag now, which will normally be set by - // getContentStream, so it will show up in our headers - if (!isSet(Flags.Flag.SEEN)) - setFlag(Flags.Flag.SEEN, true); - super.writeTo(os, ignoreList); - } - - /** - * Interpose on superclass method to make sure folder is still open - * and message hasn't been expunged. - */ - public String[] getHeader(String name) - throws MessagingException { - if (folder != null) - ((MboxFolder)folder).checkOpen(); - if (isExpunged()) - throw new MessageRemovedException("mbox message expunged"); - return super.getHeader(name); - } - - /** - * Interpose on superclass method to make sure folder is still open - * and message hasn't been expunged. - */ - public String getHeader(String name, String delimiter) - throws MessagingException { - if (folder != null) - ((MboxFolder)folder).checkOpen(); - if (isExpunged()) - throw new MessageRemovedException("mbox message expunged"); - return super.getHeader(name, delimiter); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/MboxProvider.java b/app/src/main/java/com/sun/mail/mbox/MboxProvider.java deleted file mode 100644 index d0b056d1a1..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/MboxProvider.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import javax.mail.Provider; - -/** - * The Mbox protocol provider. - */ -public class MboxProvider extends Provider { - public MboxProvider() { - super(Provider.Type.STORE, "mbox", MboxStore.class.getName(), - "Oracle", null); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/MboxStore.java b/app/src/main/java/com/sun/mail/mbox/MboxStore.java deleted file mode 100644 index 1ce39bc9b8..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/MboxStore.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; -import javax.mail.*; - -public class MboxStore extends Store { - - String user; - String home; - Mailbox mb; - static Flags permFlags; - - static { - // we support all flags - permFlags = new Flags(); - permFlags.add(Flags.Flag.SEEN); - permFlags.add(Flags.Flag.RECENT); - permFlags.add(Flags.Flag.DELETED); - permFlags.add(Flags.Flag.FLAGGED); - permFlags.add(Flags.Flag.ANSWERED); - permFlags.add(Flags.Flag.DRAFT); - permFlags.add(Flags.Flag.USER); - } - - public MboxStore(Session session, URLName url) { - super(session, url); - - // XXX - handle security exception - user = System.getProperty("user.name"); - home = System.getProperty("user.home"); - String os = System.getProperty("os.name"); - try { - String cl = "com.sun.mail.mbox." + os + "Mailbox"; - mb = (Mailbox)Class.forName(cl). - getDeclaredConstructor().newInstance(); - } catch (Exception e) { - mb = new DefaultMailbox(); - } - } - - /** - * Since we do not have any authentication - * to do and we do not want a dialog put up asking the user for a - * password we always succeed in connecting. - * But if we're given a password, that means the user is - * doing something wrong so fail the request. - */ - protected boolean protocolConnect(String host, int port, String user, - String passwd) throws MessagingException { - - if (passwd != null) - throw new AuthenticationFailedException( - "mbox does not allow passwords"); - // XXX - should we use the user? - return true; - } - - protected void setURLName(URLName url) { - // host, user, password, and file don't matter so we strip them out - if (url != null && (url.getUsername() != null || - url.getHost() != null || - url.getFile() != null)) - url = new URLName(url.getProtocol(), null, -1, null, null, null); - super.setURLName(url); - } - - - public Folder getDefaultFolder() throws MessagingException { - checkConnected(); - - return new MboxFolder(this, null); - } - - public Folder getFolder(String name) throws MessagingException { - checkConnected(); - - return new MboxFolder(this, name); - } - - public Folder getFolder(URLName url) throws MessagingException { - checkConnected(); - return getFolder(url.getFile()); - } - - private void checkConnected() throws MessagingException { - if (!isConnected()) - throw new MessagingException("Not connected"); - } - - MailFile getMailFile(String folder) { - return mb.getMailFile(user, folder); - } - - Session getSession() { - return session; - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/MessageLoader.java b/app/src/main/java/com/sun/mail/mbox/MessageLoader.java deleted file mode 100644 index b5ecaaadd5..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/MessageLoader.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; -import java.util.*; - -/** - * A support class that contains the state and logic needed when - * loading messages from a folder. - */ -final class MessageLoader { - private final TempFile temp; - private FileInputStream fis = null; - private OutputStream fos = null; - private int pos, len; // position in and length of buffer - private long off; // current offset in temp file - private long prevend; // the end of the previous message in temp file - private MboxFolder.MessageMetadata md; - private byte[] buf = null; - // the length of the longest header we'll need to look at - private static final int LINELEN = "Content-Length: XXXXXXXXXX".length(); - private char[] line; - - public MessageLoader(TempFile temp) { - this.temp = temp; - } - - /** - * Load messages from the given file descriptor, starting at the - * specified offset, adding the MessageMetadata to the list.

- * - * The data is assumed to be in UNIX mbox format, with newlines - * only as the line terminators. - */ - public int load(FileDescriptor fd, long offset, - List msgs) - throws IOException { - // XXX - could allocate and deallocate buffers here - int loaded = 0; - try { - fis = new FileInputStream(fd); - if (fis.skip(offset) != offset) - throw new EOFException("Failed to skip to offset " + offset); - this.off = prevend = temp.length(); - pos = len = 0; - line = new char[LINELEN]; - buf = new byte[64 * 1024]; - fos = temp.getAppendStream(); - int n; - // keep loading messages as long as we have headers - while ((n = skipHeader(loaded == 0)) >= 0) { - long start; - if (n == 0) { - // didn't find a Content-Length, skip the body - start = skipBody(); - if (start < 0) { - // md.end = -1; - md.dataend = -1; - msgs.add(md); - loaded++; - break; - } - md.dataend = start; - } else { - // skip over the body - skip(n); - md.dataend = off; - int b; - // skip any blank lines after the body - while ((b = get()) >= 0) { - if (b != '\n') - break; - } - start = off; - if (b >= 0) - start--; // back up one byte if not at EOF - } - // md.end = start; - prevend = start; - msgs.add(md); - loaded++; - } - } finally { - try { - fis.close(); - } catch (IOException ex) { - // ignore - } - try { - fos.close(); - } catch (IOException ex) { - // ignore - } - line = null; - buf = null; - } - return loaded; - } - - /** - * Skip over the message header, returning the content length - * of the body, or 0 if no Content-Length header was seen. - * Update the MessageMetadata based on the headers seen. - * return -1 on EOF. - */ - private int skipHeader(boolean first) throws IOException { - int clen = 0; - boolean bol = true; - int lpos = -1; - int b; - boolean saw_unix_from = false; - int lineno = 0; - md = new MboxFolder.MessageMetadata(); - md.start = prevend; - md.recent = true; - while ((b = get()) >= 0) { - if (bol) { - if (b == '\n') - break; - lpos = 0; - } - if (b == '\n') { - bol = true; - lineno++; - // newline at end of line, was the line one of the headers - // we're looking for? - if (lpos > 7) { - // XXX - make this more efficient? - String s = new String(line, 0, lpos); - // fast check for Content-Length header - if (lineno == 1 && line[0] == 'F' && isPrefix(s, "From ")) { - saw_unix_from = true; - } else if (line[7] == '-' && - isPrefix(s, "Content-Length:")) { - s = s.substring(15).trim(); - try { - clen = Integer.parseInt(s); - } catch (NumberFormatException ex) { - // ignore it - } - // fast check for Status header - } else if ((line[1] == 't' || line[1] == 'T') && - isPrefix(s, "Status:")) { - if (s.indexOf('O') >= 0) - md.recent = false; - // fast check for X-Status header - } else if ((line[3] == 't' || line[3] == 'T') && - isPrefix(s, "X-Status:")) { - if (s.indexOf('D') >= 0) - md.deleted = true; - // fast check for X-Dt-Delete-Time header - } else if (line[4] == '-' && - isPrefix(s, "X-Dt-Delete-Time:")) { - md.deleted = true; - // fast check for X-IMAP header - } else if (line[5] == 'P' && s.startsWith("X-IMAP:")) { - md.imap = true; - } - } - } else { - // accumlate data in line buffer - bol = false; - if (lpos < 0) // ignoring this line - continue; - if (lpos == 0 && (b == ' ' || b == '\t')) - lpos = -1; // ignore continuation lines - else if (lpos < line.length) - line[lpos++] = (char)b; - } - } - - // if we hit EOF, or this is the first message we're loading and - // it doesn't have a UNIX From line, return EOF. - // (After the first message, UNIX From lines are seen by skipBody - // to terminate the message.) - if (b < 0 || (first && !saw_unix_from)) - return -1; - else - return clen; - } - - /** - * Does "s" start with "pre", ignoring case? - */ - private static final boolean isPrefix(String s, String pre) { - return s.regionMatches(true, 0, pre, 0, pre.length()); - } - - /** - * Skip over the body of the message looking for a line that starts - * with "From ". If found, return the offset of the beginning of - * that line. Return -1 on EOF. - */ - private long skipBody() throws IOException { - boolean bol = true; - int lpos = -1; - long loff = off; - int b; - while ((b = get()) >= 0) { - if (bol) { - lpos = 0; - loff = off - 1; - } - if (b == '\n') { - bol = true; - if (lpos >= 5) { // have enough data to test? - if (line[0] == 'F' && line[1] == 'r' && line[2] == 'o' && - line[3] == 'm' && line[4] == ' ') - return loff; - } - } else { - bol = false; - if (lpos < 0) - continue; - if (lpos == 0 && b != 'F') - lpos = -1; // ignore lines that don't start with F - else if (lpos < 5) // only need first 5 chars to test - line[lpos++] = (char)b; - } - } - return -1; - } - - /** - * Skip "n" bytes, returning how much we were able to skip. - */ - private final int skip(int n) throws IOException { - int n0 = n; - if (pos + n < len) { - pos += n; // can do it all within this buffer - off += n; - } else { - do { - n -= (len - pos); // skip rest of this buffer - off += (len - pos); - fill(); - if (len <= 0) // ran out of data - return n0 - n; - } while (n > len); - pos += n; - off += n; - } - return n0; - } - - /** - * Return the next byte. - */ - private final int get() throws IOException { - if (pos >= len) - fill(); - if (pos >= len) - return -1; - else { - off++; - return buf[pos++] & 0xff; - } - } - - /** - * Fill our buffer with more data. - * Every buffer we read is also written to the temp file. - */ - private final void fill() throws IOException { - len = fis.read(buf); - pos = 0; - if (len > 0) - fos.write(buf, 0, len); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/NewlineOutputStream.java b/app/src/main/java/com/sun/mail/mbox/NewlineOutputStream.java deleted file mode 100644 index f4a31cba09..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/NewlineOutputStream.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; -import java.nio.charset.StandardCharsets; - -/** - * Convert the various newline conventions to the local platform's - * newline convention. Optionally, make sure the output ends with - * a blank line. - */ -public class NewlineOutputStream extends FilterOutputStream { - private int lastb = -1; - private int bol = 1; // number of times in a row we're at beginning of line - private final boolean endWithBlankLine; - private static final byte[] newline; - - static { - String s = null; - try { - s = System.lineSeparator(); - } catch (SecurityException sex) { - // ignore, should never happen - } - if (s == null || s.length() <= 0) - s = "\n"; - newline = s.getBytes(StandardCharsets.ISO_8859_1); - } - - public NewlineOutputStream(OutputStream os) { - this(os, false); - } - - public NewlineOutputStream(OutputStream os, boolean endWithBlankLine) { - super(os); - this.endWithBlankLine = endWithBlankLine; - } - - public void write(int b) throws IOException { - if (b == '\r') { - out.write(newline); - bol++; - } else if (b == '\n') { - if (lastb != '\r') { - out.write(newline); - bol++; - } - } else { - out.write(b); - bol = 0; // no longer at beginning of line - } - lastb = b; - } - - public void write(byte b[]) throws IOException { - write(b, 0, b.length); - } - - public void write(byte b[], int off, int len) throws IOException { - for (int i = 0 ; i < len ; i++) { - write(b[off + i]); - } - } - - public void flush() throws IOException { - if (endWithBlankLine) { - if (bol == 0) { - // not at bol, return to bol and add a blank line - out.write(newline); - out.write(newline); - } else if (bol == 1) { - // at bol, add a blank line - out.write(newline); - } - } - bol = 2; - out.flush(); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/SolarisMailbox.java b/app/src/main/java/com/sun/mail/mbox/SolarisMailbox.java deleted file mode 100644 index 84f3abcc9f..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/SolarisMailbox.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.File; - -public class SolarisMailbox extends Mailbox { - private final String home; - private final String user; - - private static final boolean homeRelative = - Boolean.getBoolean("mail.mbox.homerelative"); - - public SolarisMailbox() { - String h = System.getenv("HOME"); - if (h == null) - h = System.getProperty("user.home"); - home = h; - user = System.getProperty("user.name"); - } - - public MailFile getMailFile(String user, String folder) { - if (folder.equalsIgnoreCase("INBOX")) - return new UNIXInbox(user, filename(user, folder)); - else - return new UNIXFolder(filename(user, folder)); - } - - /** - * Given a name of a mailbox folder, expand it to a full path name. - */ - public String filename(String user, String folder) { - try { - switch (folder.charAt(0)) { - case '/': - return folder; - case '~': - int i = folder.indexOf(File.separatorChar); - String tail = ""; - if (i > 0) { - tail = folder.substring(i); - folder = folder.substring(0, i); - } - if (folder.length() == 1) - return home + tail; - else - return "/home/" + folder.substring(1) + tail; // XXX - default: - if (folder.equalsIgnoreCase("INBOX")) { - if (user == null) // XXX - should never happen - user = this.user; - String inbox = System.getenv("MAIL"); - if (inbox == null) - inbox = "/var/mail/" + user; - return inbox; - } else { - if (homeRelative) - return home + File.separator + folder; - else - return folder; - } - } - } catch (StringIndexOutOfBoundsException e) { - return folder; - } - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/SunOSMailbox.java b/app/src/main/java/com/sun/mail/mbox/SunOSMailbox.java deleted file mode 100644 index 55230d1e11..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/SunOSMailbox.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -public class SunOSMailbox extends SolarisMailbox { -} diff --git a/app/src/main/java/com/sun/mail/mbox/SunV3BodyPart.java b/app/src/main/java/com/sun/mail/mbox/SunV3BodyPart.java deleted file mode 100644 index 189ff85a2e..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/SunV3BodyPart.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import javax.mail.*; -import javax.mail.internet.*; -import javax.activation.*; -import java.io.*; - -/** - * This class represents a SunV3 BodyPart. - * - * @author Bill Shannon - * @see javax.mail.Part - * @see javax.mail.internet.MimePart - * @see javax.mail.internet.MimeBodyPart - */ - -public class SunV3BodyPart extends MimeBodyPart { - /** - * Constructs a SunV3BodyPart using the given header and - * content bytes.

- * - * Used by providers. - * - * @param headers The header of this part - * @param content bytes representing the body of this part. - */ - public SunV3BodyPart(InternetHeaders headers, byte[] content) - throws MessagingException { - super(headers, content); - } - - /** - * Return the size of the content of this BodyPart in bytes. - * Return -1 if the size cannot be determined.

- * - * Note that this number may not be an exact measure of the - * content size and may or may not account for any transfer - * encoding of the content.

- * - * @return size in bytes - */ - public int getSize() throws MessagingException { - String s = getHeader("X-Sun-Content-Length", null); - try { - return Integer.parseInt(s); - } catch (NumberFormatException ex) { - return -1; - } - } - - /** - * Return the number of lines for the content of this Part. - * Return -1 if this number cannot be determined.

- * - * Note that this number may not be an exact measure of the - * content length and may or may not account for any transfer - * encoding of the content. - */ - public int getLineCount() throws MessagingException { - String s = getHeader("X-Sun-Content-Lines", null); - try { - return Integer.parseInt(s); - } catch (NumberFormatException ex) { - return -1; - } - } - - /* - * This is just enough to get us going. - * - * For more complete transformation from V3 to MIME, refer to - * sun_att.c from the Sun IMAP server code. - */ - static class MimeV3Map { - String mime; - String v3; - - MimeV3Map(String mime, String v3) { - this.mime = mime; - this.v3 = v3; - } - - private static MimeV3Map[] mimeV3Table = new MimeV3Map[] { - new MimeV3Map("text/plain", "text"), - new MimeV3Map("text/plain", "default"), - new MimeV3Map("multipart/x-sun-attachment", "X-sun-attachment"), - new MimeV3Map("application/postscript", "postscript-file"), - new MimeV3Map("image/gif", "gif-file") - // audio-file - // cshell-script - }; - - // V3 Content-Type to MIME Content-Type - static String toMime(String s) { - for (int i = 0; i < mimeV3Table.length; i++) { - if (mimeV3Table[i].v3.equalsIgnoreCase(s)) - return mimeV3Table[i].mime; - } - return "application/x-" + s; - } - - // MIME Content-Type to V3 Content-Type - static String toV3(String s) { - for (int i = 0; i < mimeV3Table.length; i++) { - if (mimeV3Table[i].mime.equalsIgnoreCase(s)) - return mimeV3Table[i].v3; - } - return s; - } - } - - /** - * Returns the value of the RFC822 "Content-Type" header field. - * This represents the content-type of the content of this - * BodyPart. This value must not be null. If this field is - * unavailable, "text/plain" should be returned.

- * - * This implementation uses getHeader(name) - * to obtain the requisite header field. - * - * @return Content-Type of this BodyPart - */ - public String getContentType() throws MessagingException { - String ct = getHeader("Content-Type", null); - if (ct == null) - ct = getHeader("X-Sun-Data-Type", null); - if (ct == null) - ct = "text/plain"; - else if (ct.indexOf('/') < 0) - ct = MimeV3Map.toMime(ct); - return ct; - } - - /** - * Returns the value of the "Content-Transfer-Encoding" header - * field. Returns null if the header is unavailable - * or its value is absent.

- * - * This implementation uses getHeader(name) - * to obtain the requisite header field. - * - * @see #headers - */ - public String getEncoding() throws MessagingException { - String enc = super.getEncoding(); - if (enc == null) - enc = getHeader("X-Sun-Encoding-Info", null); - return enc; - } - - /** - * Returns the "Content-Description" header field of this BodyPart. - * This typically associates some descriptive information with - * this part. Returns null if this field is unavailable or its - * value is absent.

- * - * If the Content-Description field is encoded as per RFC 2047, - * it is decoded and converted into Unicode. If the decoding or - * conversion fails, the raw data is returned as-is

- * - * This implementation uses getHeader(name) - * to obtain the requisite header field. - * - * @return content-description - */ - public String getDescription() throws MessagingException { - String desc = super.getDescription(); - if (desc == null) - desc = getHeader("X-Sun-Data-Description", null); - return desc; - } - - /** - * Set the "Content-Description" header field for this BodyPart. - * If the description parameter is null, then any - * existing "Content-Description" fields are removed.

- * - * If the description contains non US-ASCII characters, it will - * be encoded using the platform's default charset. If the - * description contains only US-ASCII characters, no encoding - * is done and it is used as-is. - * - * @param description content-description - * @exception IllegalWriteException if the underlying - * implementation does not support modification - * @exception IllegalStateException if this BodyPart is - * obtained from a READ_ONLY folder. - */ - public void setDescription(String description) throws MessagingException { - throw new MethodNotSupportedException("SunV3BodyPart not writable"); - } - - /** - * Set the "Content-Description" header field for this BodyPart. - * If the description parameter is null, then any - * existing "Content-Description" fields are removed.

- * - * If the description contains non US-ASCII characters, it will - * be encoded using the specified charset. If the description - * contains only US-ASCII characters, no encoding is done and - * it is used as-is - * - * @param description Description - * @param charset Charset for encoding - * @exception IllegalWriteException if the underlying - * implementation does not support modification - * @exception IllegalStateException if this BodyPart is - * obtained from a READ_ONLY folder. - */ - public void setDescription(String description, String charset) - throws MessagingException { - throw new MethodNotSupportedException("SunV3BodyPart not writable"); - } - - /** - * Get the filename associated with this BodyPart.

- * - * Returns the value of the "filename" parameter from the - * "Content-Disposition" header field of this BodyPart. If its - * not available, returns the value of the "name" parameter from - * the "Content-Type" header field of this BodyPart. - * Returns null if both are absent. - * - * @return filename - */ - public String getFileName() throws MessagingException { - String name = super.getFileName(); - if (name == null) - name = getHeader("X-Sun-Data-Name", null); - return name; - } - - /** - * Set the filename associated with this BodyPart, if possible.

- * - * Sets the "filename" parameter of the "Content-Disposition" - * header field of this BodyPart. - * - * @exception IllegalWriteException if the underlying - * implementation does not support modification - * @exception IllegalStateException if this BodyPart is - * obtained from a READ_ONLY folder. - */ - public void setFileName(String filename) throws MessagingException { - throw new MethodNotSupportedException("SunV3BodyPart not writable"); - } - - /** - * This method provides the mechanism to set this BodyPart's content. - * The given DataHandler object should wrap the actual content. - * - * @param dh The DataHandler for the content - * @exception IllegalWriteException if the underlying - * implementation does not support modification - * @exception IllegalStateException if this BodyPart is - * obtained from a READ_ONLY folder. - */ - public void setDataHandler(DataHandler dh) - throws MessagingException { - throw new MethodNotSupportedException("SunV3BodyPart not writable"); - } - - /** - * Output the BodyPart as a RFC822 format stream. - * - * @exception MessagingException - * @exception IOException if an error occurs writing to the - * stream or if an error is generated - * by the javax.activation layer. - * @see javax.activation.DataHandler#writeTo() - */ - public void writeTo(OutputStream os) - throws IOException, MessagingException { - throw new MethodNotSupportedException("SunV3BodyPart writeTo"); - } - - /** - * This is the method that has the 'smarts' to query the 'content' - * and update the appropriate headers. Typical headers that get - * set here are: Content-Type, Content-Encoding, boundary (for - * multipart). Now, the tricky part here is when to actually - * activate this method: - * - * - A Message being crafted by a mail-application will certainly - * need to activate this method at some point to fill up its internal - * headers. Typically this is triggered off by our writeTo() method. - * - * - A message read-in from a MessageStore will have obtained - * all its headers from the store, and so does'nt need this. - * However, if this message is editable and if any edits have - * been made to either the content or message-structure, we might - * need to resync our headers. Typically this is triggered off by - * the Message.saveChanges() methods. - */ - protected void updateHeaders() throws MessagingException { - throw new MethodNotSupportedException("SunV3BodyPart updateHeaders"); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/SunV3Multipart.java b/app/src/main/java/com/sun/mail/mbox/SunV3Multipart.java deleted file mode 100644 index 8a642f1fbb..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/SunV3Multipart.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import javax.mail.*; -import javax.mail.internet.*; -import javax.activation.*; -import java.util.*; -import java.io.*; -import java.nio.charset.StandardCharsets; -import com.sun.mail.util.LineInputStream; - -/** - * The SunV3Multipart class is an implementation of the abstract Multipart - * class that uses SunV3 conventions for the multipart data.

- * - * @author Bill Shannon - */ - -public class SunV3Multipart extends MimeMultipart { - private boolean parsing; - - /** - * Constructs a SunV3Multipart object and its bodyparts from the - * given DataSource.

- * - * @param ds DataSource, can be a MultipartDataSource - */ - public SunV3Multipart(DataSource ds) throws MessagingException { - super(ds); - } - - /** - * Set the subtype. Throws MethodNotSupportedException. - * - * @param subtype Subtype - */ - public void setSubType(String subtype) throws MessagingException { - throw new MethodNotSupportedException( - "can't change SunV3Multipart subtype"); - } - - /** - * Get the BodyPart referred to by the given ContentID (CID). - * Throws MethodNotSupportException. - */ - public synchronized BodyPart getBodyPart(String CID) - throws MessagingException { - throw new MethodNotSupportedException( - "SunV3Multipart doesn't support Content-ID"); - } - - /** - * Update headers. Throws MethodNotSupportException. - */ - protected void updateHeaders() throws MessagingException { - throw new MethodNotSupportedException("SunV3Multipart not writable"); - } - - /** - * Iterates through all the parts and outputs each SunV3 part - * separated by a boundary. - */ - public void writeTo(OutputStream os) - throws IOException, MessagingException { - throw new MethodNotSupportedException( - "SunV3Multipart writeTo not supported"); - } - - private static final String boundary = "----------"; - - /* - * Parse the contents of this multipart message and create the - * child body parts. - */ - protected synchronized void parse() throws MessagingException { - /* - * If the data has already been parsed, or we're in the middle of - * parsing it, there's nothing to do. The latter will occur when - * we call addBodyPart, which will call parse again. We really - * want to be able to call super.super.addBodyPart. - */ - if (parsed || parsing) - return; - - InputStream in = null; - - try { - in = ds.getInputStream(); - if (!(in instanceof ByteArrayInputStream) && - !(in instanceof BufferedInputStream)) - in = new BufferedInputStream(in); - } catch (IOException ex) { - throw new MessagingException("No inputstream from datasource"); - } catch (RuntimeException ex) { - throw new MessagingException("No inputstream from datasource"); - } - - byte[] bndbytes = boundary.getBytes(StandardCharsets.ISO_8859_1); - int bl = bndbytes.length; - - String line; - parsing = true; - try { - /* - * Skip any kind of junk until we get to the first - * boundary line. - */ - LineInputStream lin = new LineInputStream(in); - while ((line = lin.readLine()) != null) { - if (line.trim().equals(boundary)) - break; - } - if (line == null) - throw new MessagingException("Missing start boundary"); - - /* - * Read and process body parts until we see the - * terminating boundary line (or EOF). - */ - for (;;) { - /* - * Collect the headers for this body part. - */ - InternetHeaders headers = new InternetHeaders(in); - - if (!in.markSupported()) - throw new MessagingException("Stream doesn't support mark"); - - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - int b; - - /* - * Read and save the content bytes in buf. - */ - while ((b = in.read()) >= 0) { - if (b == '\r' || b == '\n') { - /* - * Found the end of a line, check whether the - * next line is a boundary. - */ - int i; - in.mark(bl + 4 + 1); // "4" for possible "--\r\n" - if (b == '\r' && in.read() != '\n') { - in.reset(); - in.mark(bl + 4); - } - // read bytes, matching against the boundary - for (i = 0; i < bl; i++) - if (in.read() != bndbytes[i]) - break; - if (i == bl) { - int b2 = in.read(); - // check for end of line - if (b2 == '\n') - break; // got it! break out of the while loop - if (b2 == '\r') { - in.mark(1); - if (in.read() != '\n') - in.reset(); - break; // got it! break out of the while loop - } - } - // failed to match, reset and proceed normally - in.reset(); - } - buf.write(b); - } - - /* - * Create a SunV3BodyPart to represent this body part. - */ - SunV3BodyPart body = - new SunV3BodyPart(headers, buf.toByteArray()); - addBodyPart(body); - if (b < 0) - break; - } - } catch (IOException e) { - throw new MessagingException("IO Error"); // XXX - } finally { - parsing = false; - } - - parsed = true; - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/TempFile.java b/app/src/main/java/com/sun/mail/mbox/TempFile.java deleted file mode 100644 index 25f4bd8d87..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/TempFile.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.util.*; -import java.net.*; -import java.io.*; -import java.security.*; - -import com.sun.mail.util.PropUtil; -import javax.mail.util.SharedFileInputStream; - -/** - * A temporary file used to cache messages. - */ -class TempFile { - - private File file; // the temp file name - private WritableSharedFile sf; - - /** - * Create a temp file in the specified directory (if not null). - * The file will be deleted when the JVM exits. - */ - public TempFile(File dir) throws IOException { - file = File.createTempFile("mbox.", ".mbox", dir); - // XXX - need JDK 6 to set permissions on the file to owner-only - file.deleteOnExit(); - sf = new WritableSharedFile(file); - } - - /** - * Return a stream for appending to the temp file. - */ - public AppendStream getAppendStream() throws IOException { - return sf.getAppendStream(); - } - - /** - * Return a stream for reading from part of the file. - */ - public InputStream newStream(long start, long end) { - return sf.newStream(start, end); - } - - public long length() { - return file.length(); - } - - /** - * Close and remove this temp file. - */ - public void close() { - try { - sf.close(); - } catch (IOException ex) { - // ignore it - } - file.delete(); - } - - protected void finalize() throws Throwable { - try { - close(); - } finally { - super.finalize(); - } - } -} - -/** - * A subclass of SharedFileInputStream that also allows writing. - */ -class WritableSharedFile extends SharedFileInputStream { - private RandomAccessFile raf; - private AppendStream af; - - public WritableSharedFile(File file) throws IOException { - super(file); - try { - raf = new RandomAccessFile(file, "rw"); - } catch (IOException ex) { - // if anything goes wrong opening the writable file, - // close the readable file too - super.close(); - } - } - - /** - * Return the writable version of this file. - */ - public RandomAccessFile getWritableFile() { - return raf; - } - - /** - * Close the readable and writable files. - */ - public void close() throws IOException { - try { - super.close(); - } finally { - raf.close(); - } - } - - /** - * Update the size of the readable file after writing - * to the file. Updates the length to be the current - * size of the file. - */ - synchronized long updateLength() throws IOException { - datalen = in.length(); - af = null; - return datalen; - } - - /** - * Return a new AppendStream, but only if one isn't in active use. - */ - public synchronized AppendStream getAppendStream() throws IOException { - if (af != null) - throw new IOException( - "file cache only supports single threaded access"); - af = new AppendStream(this); - return af; - } -} - -/** - * A stream for writing to the temp file, and when done - * can return a stream for reading the data just written. - * NOTE: We assume that only one thread is writing to the - * file at a time. - */ -class AppendStream extends OutputStream { - private final WritableSharedFile tf; - private RandomAccessFile raf; - private final long start; - private long end; - - public AppendStream(WritableSharedFile tf) throws IOException { - this.tf = tf; - raf = tf.getWritableFile(); - start = raf.length(); - raf.seek(start); - } - - public void write(int b) throws IOException { - raf.write(b); - } - - public void write(byte[] b) throws IOException { - raf.write(b); - } - - public void write(byte[] b, int off, int len) throws IOException { - raf.write(b, off, len); - } - - public synchronized void close() throws IOException { - end = tf.updateLength(); - raf = null; // no more writing allowed - } - - public synchronized InputStream getInputStream() throws IOException { - return tf.newStream(start, end); - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/UNIXFile.java b/app/src/main/java/com/sun/mail/mbox/UNIXFile.java deleted file mode 100644 index ab1579e183..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/UNIXFile.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.File; -import java.io.FileDescriptor; -import java.util.StringTokenizer; - -public class UNIXFile extends File { - protected static final boolean loaded; - protected static final int lockType; - - private static final long serialVersionUID = -7972156315284146651L; - - public UNIXFile(String name) { - super(name); - } - - // lock type enum - protected static final int NONE = 0; - protected static final int NATIVE = 1; - protected static final int JAVA = 2; - - static { - String lt = System.getProperty("mail.mbox.locktype", "native"); - int type = NATIVE; - if (lt.equalsIgnoreCase("none")) - type = NONE; - else if (lt.equalsIgnoreCase("java")) - type = JAVA; - lockType = type; - - boolean lloaded = false; - if (lockType == NATIVE) { - try { - System.loadLibrary("mbox"); - lloaded = true; - } catch (UnsatisfiedLinkError e) { - String classpath = System.getProperty("java.class.path"); - String sep = System.getProperty("path.separator"); - String arch = System.getProperty("os.arch"); - StringTokenizer st = new StringTokenizer(classpath, sep); - while (st.hasMoreTokens()) { - String path = st.nextToken(); - if (path.endsWith("/classes") || - path.endsWith("/mail.jar") || - path.endsWith("/javax.mail.jar")) { - int i = path.lastIndexOf('/'); - String libdir = path.substring(0, i + 1) + "lib/"; - String lib = libdir + arch + "/libmbox.so"; - try { - System.load(lib); - lloaded = true; - break; - } catch (UnsatisfiedLinkError e2) { - lib = libdir + "libmbox.so"; - try { - System.load(lib); - lloaded = true; - break; - } catch (UnsatisfiedLinkError e3) { - continue; - } - } - } - } - } - } - loaded = lloaded; - if (loaded) - initIDs(FileDescriptor.class, FileDescriptor.in); - } - - /** - * Return the access time of the file. - */ - public static long lastAccessed(File file) { - return lastAccessed0(file.getPath()); - } - - public long lastAccessed() { - return lastAccessed0(getPath()); - } - - private static native void initIDs(Class fdClass, - FileDescriptor stdin); - - /** - * Lock the file referred to by fd. The string mode is "r" - * for a read lock or "rw" for a write lock. Don't block - * if lock can't be acquired. - */ - public static boolean lock(FileDescriptor fd, String mode) { - return lock(fd, mode, false); - } - - /** - * Lock the file referred to by fd. The string mode is "r" - * for a read lock or "rw" for a write lock. If block is set, - * block waiting for the lock if necessary. - */ - private static boolean lock(FileDescriptor fd, String mode, boolean block) { - //return loaded && lock0(fd, mode); - if (loaded) { - boolean ret; - //System.out.println("UNIXFile.lock(" + fd + ", " + mode + ")"); - ret = lock0(fd, mode, block); - //System.out.println("UNIXFile.lock returns " + ret); - return ret; - } - return false; - } - - private static native boolean lock0(FileDescriptor fd, String mode, - boolean block); - - public static native long lastAccessed0(String name); -} diff --git a/app/src/main/java/com/sun/mail/mbox/UNIXFolder.java b/app/src/main/java/com/sun/mail/mbox/UNIXFolder.java deleted file mode 100644 index 13dc30ad03..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/UNIXFolder.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; - -public class UNIXFolder extends UNIXFile implements MailFile { - protected transient RandomAccessFile file; - - private static final long serialVersionUID = -254578891263785591L; - - public UNIXFolder(String name) { - super(name); - } - - public boolean lock(String mode) { - try { - file = new RandomAccessFile(this, mode); - switch (lockType) { - case NONE: - return true; - case NATIVE: - default: - return UNIXFile.lock(file.getFD(), mode); - case JAVA: - return file.getChannel(). - tryLock(0L, Long.MAX_VALUE, !mode.equals("rw")) != null; - } - } catch (FileNotFoundException fe) { - return false; - } catch (IOException ie) { - file = null; - return false; - } - } - - public void unlock() { - if (file != null) { - try { - file.close(); - } catch (IOException e) { - // ignore it - } - file = null; - } - } - - public void touchlock() { - } - - public FileDescriptor getFD() { - if (file == null) - return null; - try { - return file.getFD(); - } catch (IOException e) { - return null; - } - } -} diff --git a/app/src/main/java/com/sun/mail/mbox/UNIXInbox.java b/app/src/main/java/com/sun/mail/mbox/UNIXInbox.java deleted file mode 100644 index 70ce86541a..0000000000 --- a/app/src/main/java/com/sun/mail/mbox/UNIXInbox.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.mail.mbox; - -import java.io.*; - -public class UNIXInbox extends UNIXFolder implements InboxFile { - private final String user; - - private static final long serialVersionUID = 651261842162777620L; - - /* - * Superclass UNIXFile loads the library containing all the - * native code and sets the "loaded" flag if successful. - */ - - public UNIXInbox(String user, String name) { - super(name); - this.user = user; - if (user == null) - throw new NullPointerException("user name is null in UNIXInbox"); - } - - public boolean lock(String mode) { - if (lockType == NATIVE) { - if (!loaded) - return false; - if (!maillock(user, 5)) - return false; - } - if (!super.lock(mode)) { - if (loaded) - mailunlock(); - return false; - } - return true; - } - - public void unlock() { - super.unlock(); - if (loaded) - mailunlock(); - } - - public void touchlock() { - if (loaded) - touchlock0(); - } - - private transient RandomAccessFile lockfile; // the user's ~/.Maillock file - private transient String lockfileName; // its name - - public boolean openLock(String mode) { - if (mode.equals("r")) - return true; - if (lockfileName == null) { - String home = System.getProperty("user.home"); - lockfileName = home + File.separator + ".Maillock"; - } - try { - lockfile = new RandomAccessFile(lockfileName, mode); - boolean ret; - switch (lockType) { - case NONE: - ret = true; - break; - case NATIVE: - default: - ret = UNIXFile.lock(lockfile.getFD(), mode); - break; - case JAVA: - ret = lockfile.getChannel(). - tryLock(0L, Long.MAX_VALUE, !mode.equals("rw")) != null; - break; - } - if (!ret) - closeLock(); - return ret; - } catch (IOException ex) { - } - return false; - } - - public void closeLock() { - if (lockfile == null) - return; - try { - lockfile.close(); - } catch (IOException ex) { - } finally { - lockfile = null; - } - } - - public boolean equals(Object o) { - if (!(o instanceof UNIXInbox)) - return false; - UNIXInbox other = (UNIXInbox)o; - return user.equals(other.user) && super.equals(other); - } - - public int hashCode() { - return super.hashCode() + user.hashCode(); - } - - private native boolean maillock(String user, int retryCount); - private native void mailunlock(); - private native void touchlock0(); -}