/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Grendel mail/news client. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are Copyright (C) 1997 * Netscape Communications Corporation. All Rights Reserved. * * Created: Jamie Zawinski , 20 Nov 1997. */ package grendel.storage; import calypso.util.Assert; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.awt.Component; import java.net.URL; import java.net.UnknownHostException; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Store; import javax.mail.URLName; //import javax.mail.event.ConnectionEvent; import javax.mail.event.StoreEvent; /** Store for News (NNTP) folders.

This class really shouldn't be public, but I haven't figured out how to tie into javamail's Session class properly. So, instead of using Session.getStore(String), you instead need to call NewsStore.GetDefaultStore(Session). */ public class NewsStore extends Store { protected NNTPConnection nntp = null; protected NewsRC newsrc = null; protected NewsFolderRoot root_folder = null; static protected NewsStore DefaultStore = null; public static Store GetDefaultStore(Session s) { if (DefaultStore == null) { DefaultStore = new NewsStore(s); } return DefaultStore; } public NewsStore(Session s) { super(s, null); } public NewsStore(Session s, URLName u) { super(s, u); } NewsRC getNewsRC() { return newsrc; } private void loadNewsRC(String host) throws IOException { Assert.Assertion(newsrc == null); String dir = System.getProperty("user.home"); boolean secure = false; // #### String name = null; if (Constants.ISUNIX) { String name1 = (secure ? ".snewsrc" : ".newsrc"); String name2 = name1 + "-" + host; if (new File(dir, name2).exists()) name = name2; else if (new File(dir, name1).exists()) name = name1; else name = name2; } else if (Constants.ISWINDOWS) { String name1 = (secure ? "snews" : "news"); String name2 = name1 + "-" + host + ".rc"; String name3 = name1 + ".rc"; if (new File(dir, name2).exists()) name = name2; else if (new File(dir, name3).exists()) name = name3; else name = name2; } else { Assert.NotYetImplemented("newsrc names only implemented for windows 'n' unix..."); } File f = new File(dir, name); newsrc = new NewsRC(f); // If the newsrc file didn't exist, subscribe to some default newsgroups. if (!f.exists()) { String subs[] = getDefaultSubscriptions(); for (int i = 0; i < subs.length; i++) { NewsRCLine ng = newsrc.getNewsgroup(subs[i]); ng.setSubscribed(true); } } } protected boolean protocolConnect(String host, String user, String password) throws MessagingException { if (nntp != null) return true; // Already connected. if (host == null) { // #### better name? host = session.getProperty("mail.default_nntp_server"); if (host == null || host == "") { // #### pop up a dialog box instead? host = "news"; } } try { loadNewsRC(host); } catch (IOException e) { throw new MessagingException("loading newsrc file", e); } nntp = new NNTPConnection(); int port = -1; // #### override this from the url or something. try { boolean status = nntp.connect(host, port, user, password); if (!status) return false; } catch (UnknownHostException e) { // This sucks, Beavis! throw new MessagingException("Unknown host", e); } catch (IOException e) { throw new MessagingException("I/O Error", e); } if (!newsrc.file().exists()) { // #### subscribe to the server's default groups } notifyStoreListeners(StoreEvent.NOTICE, "opened"); // #### ??? // notifyConnectionListeners(ConnectionEvent.OPENED); return true; } public void close() { if (nntp == null) { // already closed. Assert.Assertion(newsrc == null); return; } nntp.close(); nntp = null; Assert.Assertion(newsrc != null); if (newsrc != null) { try { newsrc.save(); } catch (IOException e) { // Sun doesn't allow us to signal here. Bastards... // Just ignore it, I guess... } } notifyStoreListeners(StoreEvent.NOTICE, "closed"); // #### ??? // notifyConnectionListeners(ConnectionEvent.CLOSED); root_folder = null; } public Folder getDefaultFolder() { if (root_folder == null) { synchronized (this) { if (root_folder == null) { // double check root_folder = new NewsFolderRoot(this); } } } return root_folder; } public Folder getFolder(String name) throws MessagingException { return getDefaultFolder().getFolder(name); } public Folder getFolder(URL url) { Assert.NotYetImplemented("NewsStore.getFolder(URL)"); return null; } public Folder getFolder(URLName urlName) { Assert.NotYetImplemented("NewsStore.getFolder(URLName)"); return null; } InputStream getMessageStream(NewsMessage message, boolean headers_too) throws NNTPException, IOException { Folder f = message.getFolder(); String group = (f == null ? null : f.getFullName()); int n = (group == null ? -1 : message.getStorageFolderIndex()); if (n == -1) { /* String id = #### ; if (headers_too) return nntp.ARTICLE(id); else return nntp.BODY(id); */ Assert.NotYetImplemented("NewsStore.getMessageStream via Message-ID"); return null; } else { if (headers_too) return nntp.ARTICLE(group, n); else return nntp.BODY(group, n); } } /** Returns array of int: [ nmessages low hi ] */ int[] getGroupCounts(NewsFolder folder) { String group = folder.getFullName(); try { return nntp.GROUP(group); } catch (IOException e) { return null; } } /** Returns a list of newsgroups to which new users should be subscribed, if they don't have a newsrc file. Tries to ask the news server for this list; otherwise, uses some builtin defaults. */ String[] getDefaultSubscriptions() { String s[] = null; try { s = nntp.LIST_SUBSCRIPTIONS(); } catch (NNTPException e) { // command unsupported } catch (IOException e) { // something else } if (s == null || s.length == 0) s = new String[] { "news.announce.newusers", "news.newusers.questions", "news.groups.questions", "alt.fan.mozilla" }; return s; } void openNewsgroup(NewsFolder folder, long from, long to) { Enumeration e; try { e = nntp.getMessages(folder, from, to); } catch (NNTPException ex) { return; } catch (IOException ex) { return; } while (e.hasMoreElements()) { Message m = (Message) e.nextElement(); folder.noticeInitialMessage(m); } } }