/* * $Id: IMAPConnection.java,v 1.1 2003/10/19 08:51:37 dog Exp $ * Copyright (C) 2003 The Free Software Foundation * * This file is part of GNU inetlib, a library. * * GNU inetlib is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GNU inetlib is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * As a special exception, if you link this library with other files to * produce an executable, this library does not by itself cause the * resulting executable to be covered by the GNU General Public License. * This exception does not however invalidate any other reasons why the * executable file might be covered by the GNU General Public License. */ package gnu.inet.imap; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.net.ProtocolException; import java.net.Socket; import java.net.UnknownHostException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.net.ssl.SSLSocketFactory; import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; import gnu.inet.util.BASE64; import gnu.inet.util.CRLFOutputStream; import gnu.inet.util.Logger; import gnu.inet.util.SaslCallbackHandler; import gnu.inet.util.SaslInputStream; import gnu.inet.util.SaslOutputStream; /** * The protocol class implementing IMAP4rev1. * * @author Chris Burdess * @version $Revision: 1.1 $ $Date: 2003/10/19 08:51:37 $ */ public class IMAPConnection implements IMAPConstants { /** * Prefix for tags. */ protected static final String TAG_PREFIX = "A"; /** * The encoding used to create strings for IMAP commands. */ protected static final String US_ASCII = "US-ASCII"; /** * The default IMAP port. */ protected static final int DEFAULT_PORT = 143; /** * The socket used for communication with the server. */ protected Socket socket; /** * The tokenizer used to read IMAP responses from. */ protected IMAPResponseTokenizer in; /** * The output stream. */ protected CRLFOutputStream out; /** * List of responses received asynchronously. */ protected List asyncResponses; /** * List of alert strings. */ private List alerts; /* * Used to generate new tags for tagged commands. */ private int tagIndex = 0; /* * Print debugging output to stderr. */ private boolean debug; /* * Print debugging output using ANSI colour escape sequences. */ private boolean ansiDebug = false; /** * Creates a new connection. * @param host the name of the host to connect to * @param port the port to connect to */ public IMAPConnection(String host, int port) throws UnknownHostException, IOException { this(host, port, -1, -1, false); } /** * Creates a new connection. * @param host the name of the host to connect to * @param port the port to connect to */ public IMAPConnection(String host, int port, int connectionTimeout, int timeout, boolean debug) throws UnknownHostException, IOException { this.debug = debug; // TODO connectionTimeout if (port<0) port = DEFAULT_PORT; // Set up socket socket = new Socket(host, port); if (timeout>0) socket.setSoTimeout(timeout); InputStream in = socket.getInputStream(); in = new BufferedInputStream(in); this.in = new IMAPResponseTokenizer(in); OutputStream out = socket.getOutputStream(); out = new BufferedOutputStream(out); this.out = new CRLFOutputStream(out); asyncResponses = new ArrayList(); alerts = new ArrayList(); } /** * Sets whether debugging output should use ANSI colour escape sequences. */ public void setAnsiDebug(boolean flag) { ansiDebug = flag; } /** * Returns a new tag for a command. */ protected String newTag() { return new StringBuffer(TAG_PREFIX).append(++tagIndex).toString(); } /** * Sends the specified IMAP tagged command to the server. */ protected void sendCommand(String tag, String command) throws IOException { if (debug) { Logger logger = Logger.getInstance(); logger.log("imap", "> "+tag+" "+command); } String cmd = new StringBuffer(tag) .append(' ') .append(command) .toString(); out.write(cmd); out.writeln(); out.flush(); } /** * Sends the specified IMAP command. * @param command the command * @return true if OK was received, or false if NO was received * @exception IOException if BAD was received or an I/O error occurred */ protected boolean invokeSimpleCommand(String command) throws IOException { String tag = newTag(); sendCommand(tag, command); while (true) { IMAPResponse response = readResponse(); String id = response.getID(); if (tag.equals(response.getTag())) { processAlerts(response); if (id==OK) return true; else if (id==NO) return false; else throw new IMAPException(id, response.getText()); } else if (response.isUntagged()) asyncResponses.add(response); else throw new IMAPException(id, response.getText()); } } /** * Reads an IMAP response from the server. * The response will consist of either: *