1998-09-09 04:52:38 +04:00
|
|
|
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
1999-11-02 04:51:54 +03:00
|
|
|
* The contents of this file are subject to the Mozilla Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/MPL/
|
1998-09-09 04:52:38 +04:00
|
|
|
*
|
1999-11-02 04:51:54 +03:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1998-09-09 04:52:38 +04:00
|
|
|
*
|
|
|
|
* The Original Code is the Grendel mail/news client.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
1999-11-02 04:51:54 +03:00
|
|
|
* Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1997 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1998-09-09 04:52:38 +04:00
|
|
|
*
|
|
|
|
* Created: Jamie Zawinski <jwz@mozilla.org>, 7-Sep-98.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package grendel;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.RandomAccessFile;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.DataInputStream;
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
|
|
|
import java.util.Properties;
|
|
|
|
import java.util.Hashtable;
|
|
|
|
|
|
|
|
import javax.mail.Message;
|
|
|
|
import javax.mail.MessagingException;
|
|
|
|
import javax.mail.Folder;
|
|
|
|
import javax.mail.Session;
|
|
|
|
|
|
|
|
import java.util.Vector;
|
|
|
|
import java.util.Enumeration;
|
|
|
|
import java.util.NoSuchElementException;
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
|
|
import calypso.util.ByteBuf;
|
|
|
|
import calypso.util.ArrayEnumeration;
|
|
|
|
import calypso.util.QSort;
|
|
|
|
import calypso.util.Comparer;
|
|
|
|
import calypso.util.NetworkDate;
|
|
|
|
|
|
|
|
import grendel.storage.BerkeleyStore;
|
|
|
|
import grendel.storage.MessageExtra;
|
|
|
|
|
|
|
|
import grendel.view.FolderView;
|
|
|
|
import grendel.view.FolderViewFactory;
|
|
|
|
import grendel.view.MessageSetView;
|
|
|
|
import grendel.view.ViewedMessage;
|
|
|
|
|
|
|
|
|
|
|
|
class TestFolderViewer {
|
|
|
|
|
|
|
|
public static void main(String args[])
|
|
|
|
throws IOException, MessagingException {
|
|
|
|
if (args.length != 1) {
|
|
|
|
System.out.println("usage: TestFolderViewer <mail-folder-pathname>\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// First, split the directory and file name, and store the directory
|
|
|
|
// in the "mail.directory" property (since JavaMail expects that.)
|
|
|
|
//
|
|
|
|
File pathname = new File(new File(args[0]).getAbsolutePath());
|
|
|
|
String dir = pathname.getParent();
|
|
|
|
String name = pathname.getName();
|
|
|
|
|
|
|
|
Properties props = new Properties();
|
|
|
|
props.put("mail.directory", dir);
|
|
|
|
|
|
|
|
// Make the global "session" and "store" object.
|
|
|
|
//
|
|
|
|
Session session = Session.getDefaultInstance(props, null);
|
|
|
|
BerkeleyStore store = new BerkeleyStore(session);
|
|
|
|
|
|
|
|
// Parse the folder. This will use a .summary file if one exists and is
|
|
|
|
// up to date; otherwise, it will parse the whole folder. The `list'
|
|
|
|
// array will hold Message (really, BerkeleyMessage) objects representing
|
|
|
|
// each of the messages in the folder. Message objects are lightweight:
|
|
|
|
// really they are just info like sender/subject/offset-in-file, etc.
|
|
|
|
//
|
|
|
|
System.out.println("Folder " + new File(dir, name));
|
|
|
|
Folder folder = store.getDefaultFolder().getFolder(name);
|
|
|
|
Message list[] = folder.getMessages();
|
|
|
|
System.out.println("Found " + list.length + " messages.");
|
|
|
|
|
|
|
|
// Print out a summary of the contents of the folder.
|
|
|
|
threadAndPrint(folder, MessageSetView.DATE, true);
|
|
|
|
|
|
|
|
// Interact with the user.
|
|
|
|
mainLoop(folder);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Gag -- for some reason our Message objects don't have getMessageNumber()
|
|
|
|
// set in them (see FolderBase.noticeInitialMessage()) so until this is
|
|
|
|
// fixed, let's kludge around it by keeping track of the index of the
|
|
|
|
// message in its folder externally, in this hash table. This is totally
|
|
|
|
// the wrong thing, but for now, it's expedient.
|
|
|
|
//
|
|
|
|
static Hashtable msgnum_kludge;
|
|
|
|
|
|
|
|
static void threadAndPrint(Folder folder, int sort_type, boolean thread_p) {
|
|
|
|
FolderView view = FolderViewFactory.Make(folder);
|
|
|
|
int order[] = { sort_type, MessageSetView.NUMBER };
|
|
|
|
|
|
|
|
// See "gag" comment above.
|
|
|
|
// Populate the msgnum_kludge with message -> folder-index numbers.
|
|
|
|
msgnum_kludge = new Hashtable();
|
|
|
|
try {
|
|
|
|
for (int i = 0; i < folder.getMessageCount(); i++)
|
|
|
|
msgnum_kludge.put(folder.getMessage(i+1), new Integer(i+1));
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
System.out.println("Error: " + e);
|
|
|
|
}
|
|
|
|
|
|
|
|
System.out.println("Sorting by " +
|
|
|
|
(sort_type == MessageSetView.NUMBER ? "number" :
|
|
|
|
sort_type == MessageSetView.DATE ? "date" :
|
|
|
|
sort_type == MessageSetView.SUBJECT ? "subject" :
|
|
|
|
sort_type == MessageSetView.AUTHOR ? "author" :
|
|
|
|
sort_type == MessageSetView.READ ? "read" :
|
|
|
|
sort_type == MessageSetView.FLAGGED ? "flagged" :
|
|
|
|
sort_type == MessageSetView.SIZE ? "size" :
|
|
|
|
sort_type == MessageSetView.DELETED ? "deleted" :"?")
|
|
|
|
+ ".");
|
|
|
|
|
|
|
|
System.out.println(thread_p ? "Threading." : "Not threading.");
|
|
|
|
|
|
|
|
// Tell the FolderView how to sort/thread, and then do it.
|
|
|
|
//
|
|
|
|
view.setSortOrder(order);
|
|
|
|
view.setIsThreaded(thread_p);
|
|
|
|
view.reThread();
|
|
|
|
|
|
|
|
// Now show the result.
|
|
|
|
printThread(view.getMessageRoot(), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void printThread(ViewedMessage vm, int depth) {
|
|
|
|
Message msg = (Message) vm.getMessage();
|
|
|
|
String str = "";
|
|
|
|
|
|
|
|
for (int i = 0; i < depth; i++)
|
|
|
|
str += " ";
|
|
|
|
|
|
|
|
if (msg == null) {
|
|
|
|
// A ViewedMessage with no Message inside is a dummy container, holding
|
|
|
|
// a thread together (for example, when the parent message of two
|
|
|
|
// siblings is not present in the folder (expired or deleted.))
|
|
|
|
//
|
|
|
|
str += " [dummy]";
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Construct a string describing this message.
|
|
|
|
//
|
|
|
|
String a = "", s = "", n = "";
|
|
|
|
Date d = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
a = ((MessageExtra) msg).getAuthor();
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
s = msg.getSubject();
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// See "gag" comment, above.
|
|
|
|
int ni = ((Integer) msgnum_kludge.get(msg)).intValue() - 1;
|
|
|
|
// int ni = msg.getMessageNumber();
|
|
|
|
|
|
|
|
n = "" + ni;
|
|
|
|
if (ni < 10) n += " ";
|
|
|
|
else if (ni < 100) n += " ";
|
|
|
|
else if (ni < 1000) n += " ";
|
|
|
|
else if (ni < 10000) n += " ";
|
|
|
|
|
|
|
|
str = n + str;
|
|
|
|
|
|
|
|
int L = str.length();
|
|
|
|
|
|
|
|
if (a.length() > 23-L) a = a.substring(0, 23-L);
|
|
|
|
if (s.length() > 23) s = s.substring(0, 23);
|
|
|
|
|
|
|
|
str += a;
|
|
|
|
for (int i = L+a.length(); i < 25; i++)
|
|
|
|
str += " ";
|
|
|
|
|
|
|
|
str += s;
|
|
|
|
for (int i = s.length(); i < 25; i++)
|
|
|
|
str += " ";
|
|
|
|
|
|
|
|
try {
|
|
|
|
d = msg.getSentDate();
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
}
|
|
|
|
if (d != null && d.getTime() != 0)
|
|
|
|
str += d;
|
|
|
|
else
|
|
|
|
str += "date unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print the string describing this message.
|
|
|
|
System.out.println(str);
|
|
|
|
|
|
|
|
// If this message has children, print them now (indented.)
|
|
|
|
// After printing this message's children/grandchildren,
|
|
|
|
// move on and print the next message in the list. (Note
|
|
|
|
// that we're walking the list by recursing, but that's
|
|
|
|
// probably ok, as its tail-recursion.)
|
|
|
|
//
|
|
|
|
ViewedMessage next = vm.getNext();
|
|
|
|
ViewedMessage kid = vm.getChild();
|
|
|
|
if (kid != null) printThread(kid, depth+1);
|
|
|
|
if (next != null) printThread(next, depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void mainLoop(Folder f) throws IOException {
|
|
|
|
|
|
|
|
DataInputStream in = new DataInputStream(System.in);
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
|
|
// Read a line from the user; parse an integer from it; and dump
|
|
|
|
// the selected message to stdout. Then repeat.
|
|
|
|
//
|
|
|
|
System.out.print("\nDisplay which message: ");
|
|
|
|
String s = in.readLine();
|
|
|
|
try {
|
|
|
|
int n = Integer.parseInt(s, 10);
|
|
|
|
System.out.println("Displaying message " + n + ".");
|
|
|
|
|
|
|
|
try {
|
|
|
|
Message m = f.getMessage(n+1);
|
|
|
|
|
|
|
|
try {
|
|
|
|
InputStream stream =
|
|
|
|
((MessageExtra)m).getInputStreamWithHeaders();
|
|
|
|
// if (makeRealHTML) {
|
|
|
|
// stream = new MakeItHTML(stream).getHTMLInputStream();
|
|
|
|
// }
|
|
|
|
InputStreamReader reader = new InputStreamReader(stream);
|
|
|
|
char buff[] = new char[4096];
|
|
|
|
int count;
|
|
|
|
System.out.println("\n-----------");
|
|
|
|
while ((count = reader.read(buff, 0, 4096)) != -1) {
|
|
|
|
System.out.println(new String(buff, 0, count));
|
|
|
|
}
|
|
|
|
System.out.println("\n-----------");
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
System.out.println("Error: " + e);
|
|
|
|
} catch (IOException e) {
|
|
|
|
System.out.println("Error: " + e);
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (MessagingException e) {
|
|
|
|
System.out.println("Error: " + e);
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
System.out.println("That's not a number.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|