working on fixes for mail test server
This commit is contained in:
parent
d803fab767
commit
0849a6decf
15 changed files with 340 additions and 376 deletions
|
@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test;
|
|||
import org.xbib.net.mail.test.test.TestServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -80,7 +81,7 @@ public final class IMAPAlertTest {
|
|||
store.close();
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
//e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
} finally {
|
||||
if (server != null) {
|
||||
|
@ -94,9 +95,9 @@ public final class IMAPAlertTest {
|
|||
*/
|
||||
private static final class IMAPHandlerAlert extends IMAPHandler {
|
||||
@Override
|
||||
public void login() throws IOException {
|
||||
untagged("OK [ALERT] account is over quota");
|
||||
super.login();
|
||||
public void login(OutputStream outputStream) throws IOException {
|
||||
untagged(outputStream, "OK [ALERT] account is over quota");
|
||||
super.login(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test;
|
|||
import org.xbib.net.mail.test.test.TestServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Properties;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
@ -37,11 +38,11 @@ public final class IMAPCloseFailureTest {
|
|||
static boolean first = true;
|
||||
|
||||
@Override
|
||||
public void examine(String line) throws IOException {
|
||||
public void examine(OutputStream outputStream, String line) throws IOException {
|
||||
if (first)
|
||||
no("mailbox gone");
|
||||
no(outputStream, "mailbox gone");
|
||||
else
|
||||
super.examine(line);
|
||||
super.examine(outputStream, line);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
@ -50,11 +51,11 @@ public final class IMAPCloseFailureTest {
|
|||
static boolean first = true;
|
||||
|
||||
@Override
|
||||
public void examine(String line) throws IOException {
|
||||
public void examine(OutputStream outputStream, String line) throws IOException {
|
||||
if (first)
|
||||
bad("mailbox gone");
|
||||
bad(outputStream, "mailbox gone");
|
||||
else
|
||||
super.examine(line);
|
||||
super.examine(outputStream, line);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.xbib.net.mail.test.test.TestServer;
|
|||
import org.xbib.net.mail.util.MailConnectException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Properties;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
@ -89,12 +90,12 @@ public final class IMAPConnectFailureTest {
|
|||
try {
|
||||
final IMAPHandler handler = new IMAPHandler() {
|
||||
@Override
|
||||
public void sendGreetings() throws IOException {
|
||||
untagged("OK IMAPHandler");
|
||||
public void sendGreetings(OutputStream outputStream) throws IOException {
|
||||
untagged(outputStream, "OK IMAPHandler");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void capability() throws IOException {
|
||||
public void capability(OutputStream outputStream) throws IOException {
|
||||
exit();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.xbib.net.mail.imap.IMAPFolder;
|
|||
import org.xbib.net.mail.test.test.TestServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
@ -75,11 +76,12 @@ public final class IMAPFetchProfileTest {
|
|||
},
|
||||
new IMAPHandlerFetch() {
|
||||
@Override
|
||||
public void fetch(String line) throws IOException {
|
||||
if (line.contains("INTERNALDATE"))
|
||||
public void fetch(OutputStream outputStream, String line) throws IOException {
|
||||
if (line.contains("INTERNALDATE")) {
|
||||
saw.add("INTERNALDATE");
|
||||
untagged("1 FETCH (INTERNALDATE \"" + RDATE + "\")");
|
||||
ok();
|
||||
}
|
||||
untagged(outputStream, "1 FETCH (INTERNALDATE \"" + RDATE + "\")");
|
||||
ok(outputStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -103,11 +105,12 @@ public final class IMAPFetchProfileTest {
|
|||
},
|
||||
new IMAPHandlerFetch() {
|
||||
@Override
|
||||
public void fetch(String line) throws IOException {
|
||||
if (line.contains("INTERNALDATE"))
|
||||
public void fetch(OutputStream outputStream, String line) throws IOException {
|
||||
if (line.contains("INTERNALDATE")) {
|
||||
saw.add("INTERNALDATE");
|
||||
untagged("1 FETCH (INTERNALDATE \"" + RDATE + "\")");
|
||||
ok();
|
||||
}
|
||||
untagged(outputStream, "1 FETCH (INTERNALDATE \"" + RDATE + "\")");
|
||||
ok(outputStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -126,12 +129,13 @@ public final class IMAPFetchProfileTest {
|
|||
},
|
||||
new IMAPHandlerFetch() {
|
||||
@Override
|
||||
public void fetch(String line) throws IOException {
|
||||
if (line.contains("INTERNALDATE"))
|
||||
public void fetch(OutputStream outputStream, String line) throws IOException {
|
||||
if (line.contains("INTERNALDATE")) {
|
||||
saw.add("INTERNALDATE");
|
||||
untagged("1 FETCH (ENVELOPE " + ENVELOPE +
|
||||
}
|
||||
untagged(outputStream, "1 FETCH (ENVELOPE " + ENVELOPE +
|
||||
" INTERNALDATE \"" + RDATE + "\" RFC822.SIZE 0)");
|
||||
ok();
|
||||
ok(outputStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -182,9 +186,9 @@ public final class IMAPFetchProfileTest {
|
|||
protected static Set<String> saw = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void select(String line) throws IOException {
|
||||
public void select(OutputStream outputStream, String line) throws IOException {
|
||||
numberOfMessages = 1;
|
||||
super.select(line);
|
||||
super.select(outputStream, line);
|
||||
}
|
||||
|
||||
public boolean saw(String item) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.xbib.net.mail.imap.IMAPFolder;
|
|||
import org.xbib.net.mail.test.test.TestServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.logging.Level;
|
||||
|
@ -75,21 +76,21 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void create(String line) throws IOException {
|
||||
public void create(OutputStream outputStream,String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "CREATE"
|
||||
String name = st.nextToken();
|
||||
if (name.equals(utf7Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void list(String line) throws IOException {
|
||||
untagged("LIST (\\HasNoChildren) \"/\" " + utf7Folder);
|
||||
ok();
|
||||
public void list(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, "LIST (\\HasNoChildren) \"/\" " + utf7Folder);
|
||||
ok(outputStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -111,22 +112,21 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPUtf8Handler() {
|
||||
@Override
|
||||
public void create(String line) throws IOException {
|
||||
public void create(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "CREATE"
|
||||
String name = unquote(st.nextToken());
|
||||
if (name.equals(utf8Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void list(String line) throws IOException {
|
||||
untagged("LIST (\\HasNoChildren) \"/\" \"" +
|
||||
utf8Folder + "\"");
|
||||
ok();
|
||||
public void list(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, "LIST (\\HasNoChildren) \"/\" \"" + utf8Folder + "\"");
|
||||
ok(outputStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -148,15 +148,15 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void delete(String line) throws IOException {
|
||||
public void delete(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "DELETE"
|
||||
String name = st.nextToken();
|
||||
if (name.equals(utf7Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -178,15 +178,16 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPUtf8Handler() {
|
||||
@Override
|
||||
public void delete(String line) throws IOException {
|
||||
public void delete(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "DELETE"
|
||||
String name = unquote(st.nextToken());
|
||||
if (name.equals(utf8Folder))
|
||||
ok();
|
||||
else
|
||||
no("wrong name");
|
||||
if (name.equals(utf8Folder)) {
|
||||
ok(outputStream);
|
||||
} else {
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -210,15 +211,15 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void select(String line) throws IOException {
|
||||
public void select(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "SELECT"
|
||||
String name = st.nextToken();
|
||||
if (name.equals(utf7Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -242,15 +243,15 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPUtf8Handler() {
|
||||
@Override
|
||||
public void select(String line) throws IOException {
|
||||
public void select(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "SELECT"
|
||||
String name = unquote(st.nextToken());
|
||||
if (name.equals(utf8Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -274,15 +275,15 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void examine(String line) throws IOException {
|
||||
public void examine(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "EXAMINE"
|
||||
String name = st.nextToken();
|
||||
if (name.equals(utf7Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -306,15 +307,15 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPUtf8Handler() {
|
||||
@Override
|
||||
public void examine(String line) throws IOException {
|
||||
public void examine(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "EXAMINE"
|
||||
String name = unquote(st.nextToken());
|
||||
if (name.equals(utf8Folder))
|
||||
ok();
|
||||
ok(outputStream);
|
||||
else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -336,17 +337,17 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void status(String line) throws IOException {
|
||||
public void status(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "STATUS"
|
||||
String name = st.nextToken();
|
||||
if (name.equals(utf7Folder)) {
|
||||
untagged("STATUS " + utf7Folder +
|
||||
untagged(outputStream, "STATUS " + utf7Folder +
|
||||
" (UIDVALIDITY 123)");
|
||||
ok();
|
||||
ok(outputStream);
|
||||
} else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -368,17 +369,17 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPUtf8Handler() {
|
||||
@Override
|
||||
public void status(String line) throws IOException {
|
||||
public void status(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
st.nextToken(); // skip tag
|
||||
st.nextToken(); // skip "STATUS"
|
||||
String name = unquote(st.nextToken());
|
||||
if (name.equals(utf8Folder)) {
|
||||
untagged("STATUS \"" + utf8Folder +
|
||||
untagged(outputStream, "STATUS \"" + utf8Folder +
|
||||
"\" (UIDVALIDITY 123)");
|
||||
ok();
|
||||
ok(outputStream);
|
||||
} else
|
||||
no("wrong name");
|
||||
no(outputStream, "wrong name");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -426,9 +427,9 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void select(String line) throws IOException {
|
||||
untagged("NO [UIDNOTSTICKY]");
|
||||
super.select(line);
|
||||
public void select(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, "NO [UIDNOTSTICKY]");
|
||||
super.select(outputStream, line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -457,10 +458,10 @@ class IMAPFolderTest {
|
|||
},
|
||||
new IMAPHandler() {
|
||||
@Override
|
||||
public void search(String line) throws IOException {
|
||||
untagged("1 EXPUNGE");
|
||||
untagged("0 EXISTS");
|
||||
super.search(line);
|
||||
public void search(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, "1 EXPUNGE");
|
||||
untagged(outputStream, "0 EXISTS");
|
||||
super.search(outputStream, line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -527,8 +528,8 @@ class IMAPFolderTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void enable(String line) throws IOException {
|
||||
ok();
|
||||
public void enable(OutputStream outputStream, String line) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,12 @@ import org.xbib.net.mail.test.test.ProtocolHandler;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Handle IMAP connection.
|
||||
|
@ -33,6 +35,8 @@ import java.util.logging.Level;
|
|||
*/
|
||||
public class IMAPHandler extends ProtocolHandler {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(IMAPHandler.class.getName());
|
||||
|
||||
/**
|
||||
* Current line.
|
||||
*/
|
||||
|
@ -58,19 +62,14 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*/
|
||||
protected int numberOfRecentMessages = 0;
|
||||
|
||||
public IMAPHandler(InputStream inputStream,
|
||||
OutputStream outputStream) {
|
||||
super(inputStream, outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send greetings.
|
||||
*
|
||||
* @throws IOException unable to write to socket
|
||||
*/
|
||||
@Override
|
||||
public void sendGreetings() throws IOException {
|
||||
untagged("OK [CAPABILITY " + capabilities + "] IMAPHandler");
|
||||
public void sendGreetings(OutputStream outputStream) throws IOException {
|
||||
untagged(outputStream, "OK [CAPABILITY " + capabilities + "] IMAPHandler");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,10 +78,9 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param str String to send
|
||||
* @throws IOException unable to write to socket
|
||||
*/
|
||||
public void println(final String str) throws IOException {
|
||||
writer.print(str);
|
||||
writer.print("\r\n");
|
||||
writer.flush();
|
||||
public void println(OutputStream outputStream, final String str) throws IOException {
|
||||
Channels.newChannel(outputStream).write(StandardCharsets.UTF_8.encode(str + "\r\n"));
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,8 +89,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param resp the response to send
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void tagged(final String resp) throws IOException {
|
||||
println(tag + " " + resp);
|
||||
public void tagged(OutputStream outputStream, final String resp) throws IOException {
|
||||
println(outputStream, tag + " " + resp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,8 +99,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param resp the response to send
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void untagged(final String resp) throws IOException {
|
||||
println("* " + resp);
|
||||
public void untagged(OutputStream outputStream, final String resp) throws IOException {
|
||||
println(outputStream, "* " + resp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,8 +108,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void ok() throws IOException {
|
||||
tagged("OK");
|
||||
public void ok(OutputStream outputStream) throws IOException {
|
||||
tagged(outputStream, "OK");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,8 +118,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param msg the message to send
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void ok(final String msg) throws IOException {
|
||||
tagged("OK " + (msg != null ? msg : ""));
|
||||
public void ok(OutputStream outputStream, final String msg) throws IOException {
|
||||
tagged(outputStream, "OK " + (msg != null ? msg : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,8 +128,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param msg the message to send
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void no(final String msg) throws IOException {
|
||||
tagged("NO " + (msg != null ? msg : ""));
|
||||
public void no(OutputStream outputStream, final String msg) throws IOException {
|
||||
tagged(outputStream, "NO " + (msg != null ? msg : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,8 +138,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param msg the message to send
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void bad(final String msg) throws IOException {
|
||||
tagged("BAD " + (msg != null ? msg : ""));
|
||||
public void bad(OutputStream outputStream, final String msg) throws IOException {
|
||||
tagged(outputStream, "BAD " + (msg != null ? msg : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,8 +148,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @param msg the message to send
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void bye(final String msg) throws IOException {
|
||||
untagged("BYE " + (msg != null ? msg : ""));
|
||||
public void bye(OutputStream outputStream, final String msg) throws IOException {
|
||||
untagged(outputStream, "BYE " + (msg != null ? msg : ""));
|
||||
exit();
|
||||
}
|
||||
|
||||
|
@ -160,8 +158,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void cont() throws IOException {
|
||||
println("+ please continue");
|
||||
public void cont(OutputStream outputStream) throws IOException {
|
||||
println(outputStream, "+ please continue");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,8 +167,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void cont(String msg) throws IOException {
|
||||
println("+ " + (msg != null ? msg : ""));
|
||||
public void cont(OutputStream outputStream, String msg) throws IOException {
|
||||
println(outputStream, "+ " + (msg != null ? msg : ""));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,96 +177,92 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand() throws IOException {
|
||||
currentLine = super.readLine();
|
||||
|
||||
public void handleCommand(InputStream inputStream, OutputStream outputStream) throws IOException {
|
||||
currentLine = super.readLine(inputStream);
|
||||
if (currentLine == null) {
|
||||
// probably just EOF because the socket was closed
|
||||
//LOGGER.severe("Current line is null!");
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
|
||||
StringTokenizer ct = new StringTokenizer(currentLine, " ");
|
||||
if (!ct.hasMoreTokens()) {
|
||||
LOGGER.log(Level.SEVERE, "ERROR no command tag: {0}",
|
||||
escape(currentLine));
|
||||
bad("no command tag");
|
||||
logger.log(Level.SEVERE, "ERROR no command tag: {0}", escape(currentLine));
|
||||
bad(outputStream, "no command tag");
|
||||
return;
|
||||
}
|
||||
tag = ct.nextToken();
|
||||
if (!ct.hasMoreTokens()) {
|
||||
LOGGER.log(Level.SEVERE, "ERROR no command: {0}",
|
||||
logger.log(Level.SEVERE, "ERROR no command: {0}",
|
||||
escape(currentLine));
|
||||
bad("no command");
|
||||
bad(outputStream, "no command");
|
||||
return;
|
||||
}
|
||||
final String commandName = ct.nextToken().toUpperCase();
|
||||
if (commandName == null) {
|
||||
LOGGER.severe("Command name is empty!");
|
||||
if (commandName.isEmpty()) {
|
||||
logger.severe("Command name is empty!");
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandName.equals("LOGIN")) {
|
||||
login();
|
||||
login(outputStream);
|
||||
} else if (commandName.equals("AUTHENTICATE")) {
|
||||
String mech = ct.nextToken().toUpperCase();
|
||||
String ir = null;
|
||||
if (ct.hasMoreTokens())
|
||||
if (ct.hasMoreTokens()) {
|
||||
ir = ct.nextToken();
|
||||
authenticate(mech, ir);
|
||||
}
|
||||
authenticate(inputStream, outputStream, mech, ir);
|
||||
} else if (commandName.equals("CAPABILITY")) {
|
||||
capability();
|
||||
capability(outputStream);
|
||||
} else if (commandName.equals("NOOP")) {
|
||||
noop();
|
||||
noop(outputStream);
|
||||
} else if (commandName.equals("SELECT")) {
|
||||
select(currentLine);
|
||||
select(outputStream, currentLine);
|
||||
} else if (commandName.equals("EXAMINE")) {
|
||||
examine(currentLine);
|
||||
examine(outputStream, currentLine);
|
||||
} else if (commandName.equals("LIST")) {
|
||||
list(currentLine);
|
||||
list(outputStream, currentLine);
|
||||
} else if (commandName.equals("IDLE")) {
|
||||
idle();
|
||||
idle(inputStream, outputStream);
|
||||
} else if (commandName.equals("FETCH")) {
|
||||
fetch(currentLine);
|
||||
fetch(outputStream, currentLine);
|
||||
} else if (commandName.equals("STORE")) {
|
||||
store(currentLine);
|
||||
store(outputStream, currentLine);
|
||||
} else if (commandName.equals("SEARCH")) {
|
||||
search(currentLine);
|
||||
search(outputStream, currentLine);
|
||||
} else if (commandName.equals("APPEND")) {
|
||||
append(currentLine);
|
||||
append(inputStream, outputStream, currentLine);
|
||||
} else if (commandName.equals("CLOSE")) {
|
||||
close();
|
||||
close(outputStream);
|
||||
} else if (commandName.equals("LOGOUT")) {
|
||||
logout();
|
||||
logout(outputStream);
|
||||
} else if (commandName.equals("UID")) {
|
||||
String subcommandName = ct.nextToken().toUpperCase();
|
||||
if (subcommandName.equals("FETCH")) {
|
||||
uidfetch(currentLine);
|
||||
uidfetch(outputStream, currentLine);
|
||||
} else if (subcommandName.equals("STORE")) {
|
||||
uidstore(currentLine);
|
||||
uidstore(outputStream, currentLine);
|
||||
} else {
|
||||
LOGGER.log(Level.SEVERE, "ERROR UID command unknown: {0}",
|
||||
subcommandName);
|
||||
bad("unknown UID command");
|
||||
logger.log(Level.SEVERE, "ERROR UID command unknown: {0}", subcommandName);
|
||||
bad(outputStream, "unknown UID command");
|
||||
}
|
||||
} else if (commandName.equals("ID")) {
|
||||
id(currentLine);
|
||||
id(outputStream, currentLine);
|
||||
} else if (commandName.equals("ENABLE")) {
|
||||
enable(currentLine);
|
||||
enable(outputStream, currentLine);
|
||||
} else if (commandName.equals("CREATE")) {
|
||||
create(currentLine);
|
||||
create(outputStream, currentLine);
|
||||
} else if (commandName.equals("DELETE")) {
|
||||
delete(currentLine);
|
||||
delete(outputStream, currentLine);
|
||||
} else if (commandName.equals("STATUS")) {
|
||||
status(currentLine);
|
||||
status(outputStream, currentLine);
|
||||
} else if (commandName.equals("NAMESPACE")) {
|
||||
namespace();
|
||||
namespace(outputStream);
|
||||
} else {
|
||||
LOGGER.log(Level.SEVERE, "ERROR command unknown: {0}",
|
||||
logger.log(Level.SEVERE, "ERROR command unknown: {0}",
|
||||
escape(currentLine));
|
||||
bad("unknown command");
|
||||
bad(outputStream, "unknown command");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,8 +271,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void login() throws IOException {
|
||||
ok("[CAPABILITY " + capabilities + "]");
|
||||
public void login(OutputStream outputStream) throws IOException {
|
||||
ok(outputStream, "[CAPABILITY " + capabilities + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -286,13 +280,13 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void authenticate(String mech, String ir) throws IOException {
|
||||
public void authenticate(InputStream inputStream, OutputStream outputStream, String mech, String ir) throws IOException {
|
||||
if (mech.equals("LOGIN"))
|
||||
authlogin(ir);
|
||||
authlogin(inputStream, outputStream, ir);
|
||||
else if (mech.equals("PLAIN"))
|
||||
authplain(ir);
|
||||
authplain(inputStream, outputStream, ir);
|
||||
else
|
||||
bad("AUTHENTICATE not supported");
|
||||
bad(outputStream, "AUTHENTICATE not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,14 +294,14 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void authlogin(String ir) throws IOException {
|
||||
public void authlogin(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
|
||||
if (ir != null)
|
||||
bad("AUTHENTICATE LOGIN does not support initial response");
|
||||
cont(base64encode("Username"));
|
||||
String username = readLine();
|
||||
cont(base64encode("Password"));
|
||||
String password = readLine();
|
||||
ok("[CAPABILITY " + capabilities + "]");
|
||||
bad(outputStream, "AUTHENTICATE LOGIN does not support initial response");
|
||||
cont(outputStream, base64encode("Username"));
|
||||
String username = readLine(inputStream);
|
||||
cont(outputStream, base64encode("Password"));
|
||||
String password = readLine(inputStream);
|
||||
ok(outputStream, "[CAPABILITY " + capabilities + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -315,12 +309,12 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void authplain(String ir) throws IOException {
|
||||
public void authplain(InputStream inputStream, OutputStream outputStream, String ir) throws IOException {
|
||||
if (ir == null) {
|
||||
cont("");
|
||||
String resp = readLine();
|
||||
cont(outputStream, "");
|
||||
String resp = readLine(inputStream);
|
||||
}
|
||||
ok("[CAPABILITY " + capabilities + "]");
|
||||
ok(outputStream, "[CAPABILITY " + capabilities + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -328,9 +322,9 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void capability() throws IOException {
|
||||
untagged("CAPABILITY " + capabilities);
|
||||
ok();
|
||||
public void capability(OutputStream outputStream) throws IOException {
|
||||
untagged(outputStream, "CAPABILITY " + capabilities);
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -338,10 +332,10 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void select(String line) throws IOException {
|
||||
untagged(numberOfMessages + " EXISTS");
|
||||
untagged(numberOfRecentMessages + " RECENT");
|
||||
ok();
|
||||
public void select(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, numberOfMessages + " EXISTS");
|
||||
untagged(outputStream, numberOfRecentMessages + " RECENT");
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,10 +343,10 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void examine(String line) throws IOException {
|
||||
untagged(numberOfMessages + " EXISTS");
|
||||
untagged(numberOfRecentMessages + " RECENT");
|
||||
ok();
|
||||
public void examine(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, numberOfMessages + " EXISTS");
|
||||
untagged(outputStream, numberOfRecentMessages + " RECENT");
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -360,8 +354,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void list(String line) throws IOException {
|
||||
ok();
|
||||
public void list(OutputStream outputStream, String line) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,29 +363,27 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void idle() throws IOException {
|
||||
cont();
|
||||
idleWait();
|
||||
ok();
|
||||
public void idle(InputStream inputStream, OutputStream outputStream) throws IOException {
|
||||
cont(outputStream);
|
||||
idleWait(inputStream, outputStream);
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String readLine() throws IOException {
|
||||
currentLine = super.readLine();
|
||||
protected String readLine(InputStream inputStream) throws IOException {
|
||||
currentLine = super.readLine(inputStream);
|
||||
if (currentLine == null) {
|
||||
LOGGER.severe("Current line is null!");
|
||||
logger.severe("Current line is null!");
|
||||
exit();
|
||||
}
|
||||
return currentLine;
|
||||
}
|
||||
|
||||
protected void idleWait() throws IOException {
|
||||
String line = readLine();
|
||||
|
||||
protected void idleWait(InputStream inputStream, OutputStream outputStream) throws IOException {
|
||||
String line = readLine(inputStream);
|
||||
if (line != null && !line.equalsIgnoreCase("DONE")) {
|
||||
LOGGER.severe("Didn't get DONE response to IDLE");
|
||||
logger.severe("Didn't get DONE response to IDLE");
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,8 +392,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void fetch(String line) throws IOException {
|
||||
ok(); // XXX
|
||||
public void fetch(OutputStream outputStream, String line) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -409,8 +401,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void store(String line) throws IOException {
|
||||
ok(); // XXX
|
||||
public void store(OutputStream outputStream, String line) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -418,9 +410,9 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void search(String line) throws IOException {
|
||||
untagged("SEARCH");
|
||||
ok(); // XXX
|
||||
public void search(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, "SEARCH");
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -428,8 +420,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void uidfetch(String line) throws IOException {
|
||||
ok(); // XXX
|
||||
public void uidfetch(OutputStream outputStream, String line) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -437,8 +429,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void uidstore(String line) throws IOException {
|
||||
ok(); // XXX
|
||||
public void uidstore(OutputStream outputStream, String line) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -446,13 +438,13 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void append(String line) throws IOException {
|
||||
public void append(InputStream inputStream, OutputStream outputStream, String line) throws IOException {
|
||||
int left = line.lastIndexOf('{');
|
||||
int right = line.indexOf('}', left);
|
||||
int bytes = Integer.parseInt(line.substring(left + 1, right));
|
||||
cont("waiting for message");
|
||||
collectMessage(bytes);
|
||||
ok(); // XXX
|
||||
cont(outputStream, "waiting for message");
|
||||
collectMessage(inputStream, outputStream, bytes);
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -460,9 +452,9 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void id(String line) throws IOException {
|
||||
untagged("ID NIL");
|
||||
ok();
|
||||
public void id(OutputStream outputStream, String line) throws IOException {
|
||||
untagged(outputStream, "ID NIL");
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -470,8 +462,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void enable(String line) throws IOException {
|
||||
no("can't enable");
|
||||
public void enable(OutputStream outputStream, String line) throws IOException {
|
||||
no(outputStream, "can't enable");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -479,8 +471,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void create(String line) throws IOException {
|
||||
no("can't create");
|
||||
public void create(OutputStream outputStream, String line) throws IOException {
|
||||
no(outputStream, "can't create");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -488,8 +480,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void delete(String line) throws IOException {
|
||||
no("can't delete");
|
||||
public void delete(OutputStream outputStream, String line) throws IOException {
|
||||
no(outputStream, "can't delete");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -497,8 +489,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void status(String line) throws IOException {
|
||||
no("can't get status");
|
||||
public void status(OutputStream outputStream, String line) throws IOException {
|
||||
no(outputStream, "can't get status");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,23 +498,23 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void namespace() throws IOException {
|
||||
no("no namespaces");
|
||||
public void namespace(OutputStream outputStream) throws IOException {
|
||||
no(outputStream, "no namespaces");
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect "bytes" worth of data for the message being appended.
|
||||
*/
|
||||
protected void collectMessage(int bytes) throws IOException {
|
||||
readLiteral(bytes); // read the data and throw it away
|
||||
super.readLine(); // data followed by a newline
|
||||
protected void collectMessage(InputStream inputStream, OutputStream outputStream, int bytes) throws IOException {
|
||||
readLiteral(inputStream, outputStream, bytes); // read the data and throw it away
|
||||
super.readLine(inputStream); // data followed by a newline
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a literal of "bytes" bytes and return it as a UTF-8 string.
|
||||
*/
|
||||
protected String readLiteral(int bytes) throws IOException {
|
||||
println("+");
|
||||
protected String readLiteral(InputStream inputStream, OutputStream outputStream, int bytes) throws IOException {
|
||||
println(outputStream, "+");
|
||||
byte[] data = new byte[bytes];
|
||||
int len = data.length;
|
||||
int off = 0;
|
||||
|
@ -539,8 +531,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
ok();
|
||||
public void close(OutputStream outputStream) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -548,8 +540,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void noop() throws IOException {
|
||||
ok();
|
||||
public void noop(OutputStream outputStream) throws IOException {
|
||||
ok(outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -557,8 +549,8 @@ public class IMAPHandler extends ProtocolHandler {
|
|||
*
|
||||
* @throws IOException unable to read/write to socket
|
||||
*/
|
||||
public void logout() throws IOException {
|
||||
ok();
|
||||
public void logout(OutputStream outputStream) throws IOException {
|
||||
ok(outputStream);
|
||||
exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.xbib.net.mail.imap.IMAPStore;
|
|||
import org.xbib.net.mail.test.test.TestServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
@ -79,13 +80,13 @@ public final class IMAPIDTest {
|
|||
private static final class IMAPHandlerID extends IMAPHandler {
|
||||
|
||||
@Override
|
||||
public void id(String line) throws IOException {
|
||||
public void id(OutputStream outputStream, String line) throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(line);
|
||||
String tag = st.nextToken();
|
||||
String cmd = st.nextToken();
|
||||
String arg = st.nextToken();
|
||||
untagged("ID (\"test\" \"" + arg.equals("NIL") + "\")");
|
||||
ok();
|
||||
untagged(outputStream, "ID (\"test\" \"" + arg.equals("NIL") + "\")");
|
||||
ok(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.xbib.net.mail.imap.IMAPStore;
|
|||
import org.xbib.net.mail.imap.IdleManager;
|
||||
import org.xbib.net.mail.test.test.TestServer;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -347,9 +348,9 @@ public final class IMAPIdleManagerTest {
|
|||
*/
|
||||
private static abstract class IMAPHandlerIdle extends IMAPHandler {
|
||||
@Override
|
||||
public void select(String line) throws IOException {
|
||||
public void select(OutputStream outputStream, String line) throws IOException {
|
||||
numberOfMessages = 1;
|
||||
super.select(line);
|
||||
super.select(outputStream, line);
|
||||
}
|
||||
|
||||
public abstract void waitForIdle() throws InterruptedException;
|
||||
|
|
|
@ -57,11 +57,11 @@ public class IMAPSaslHandler extends IMAPHandler {
|
|||
CallbackHandler cbh = new CallbackHandler() {
|
||||
@Override
|
||||
public void handle(Callback[] callbacks) {
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL callback length: " + callbacks.length);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL callback length: " + callbacks.length);
|
||||
for (int i = 0; i < callbacks.length; i++) {
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL callback " + i + ": " + callbacks[i]);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL callback " + i + ": " + callbacks[i]);
|
||||
if (callbacks[i] instanceof NameCallback) {
|
||||
NameCallback ncb = (NameCallback) callbacks[i];
|
||||
ncb.setName(u);
|
||||
|
@ -70,8 +70,8 @@ public class IMAPSaslHandler extends IMAPHandler {
|
|||
pcb.setPassword(p.toCharArray());
|
||||
} else if (callbacks[i] instanceof AuthorizeCallback) {
|
||||
AuthorizeCallback ac = (AuthorizeCallback) callbacks[i];
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL authorize: " +
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL authorize: " +
|
||||
"authn: " + ac.getAuthenticationID() + ", " +
|
||||
"authz: " + ac.getAuthorizationID() + ", " +
|
||||
"authorized: " + ac.getAuthorizedID());
|
||||
|
@ -104,17 +104,17 @@ public class IMAPSaslHandler extends IMAPHandler {
|
|||
try {
|
||||
ss = Sasl.createSaslServer(mech, "imap", "localhost", null, cbh);
|
||||
} catch (SaslException sex) {
|
||||
LOGGER.log(Level.FINE, "Failed to create SASL server", sex);
|
||||
logger.log(Level.FINE, "Failed to create SASL server", sex);
|
||||
no("Failed to create SASL server");
|
||||
return;
|
||||
}
|
||||
if (ss == null) {
|
||||
LOGGER.fine("No SASL support");
|
||||
logger.fine("No SASL support");
|
||||
no("No SASL support");
|
||||
return;
|
||||
}
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL server " + ss.getMechanismName());
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL server " + ss.getMechanismName());
|
||||
|
||||
byte[] response = new byte[0];
|
||||
while (!ss.isComplete()) {
|
||||
|
@ -124,8 +124,8 @@ public class IMAPSaslHandler extends IMAPHandler {
|
|||
break;
|
||||
} else {
|
||||
// send challenge
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL challenge: " +
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL challenge: " +
|
||||
ASCIIUtility.toString(chal, 0, chal.length));
|
||||
byte[] ba = Base64.getEncoder().encode(chal);
|
||||
if (ba.length > 0)
|
||||
|
@ -148,7 +148,7 @@ public class IMAPSaslHandler extends IMAPHandler {
|
|||
if (qop != null && (qop.equalsIgnoreCase("auth-int") ||
|
||||
qop.equalsIgnoreCase("auth-conf"))) {
|
||||
// XXX - NOT SUPPORTED!!!
|
||||
LOGGER.fine(
|
||||
logger.fine(
|
||||
"SASL Mechanism requires integrity or confidentiality");
|
||||
no("SASL Mechanism requires integrity or confidentiality");
|
||||
return;
|
||||
|
|
|
@ -118,7 +118,7 @@ public class POP3Handler extends ProtocolHandler {
|
|||
final String commandName = st.nextToken().toUpperCase();
|
||||
final String arg = st.hasMoreTokens() ? st.nextToken() : null;
|
||||
if (commandName == null) {
|
||||
LOGGER.severe("Command name is empty!");
|
||||
logger.severe("Command name is empty!");
|
||||
this.exit();
|
||||
return;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public class POP3Handler extends ProtocolHandler {
|
|||
} else if (commandName.equals("AUTH")) {
|
||||
this.auth();
|
||||
} else {
|
||||
LOGGER.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
|
||||
logger.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
|
||||
this.println("-ERR unknown command");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public class SMTPHandler extends ProtocolHandler {
|
|||
final StringTokenizer st = new StringTokenizer(currentLine, " ");
|
||||
final String commandName = st.nextToken().toUpperCase();
|
||||
if (commandName == null) {
|
||||
LOGGER.severe("Command name is empty!");
|
||||
logger.severe("Command name is empty!");
|
||||
exit();
|
||||
return;
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ public class SMTPHandler extends ProtocolHandler {
|
|||
} else if (commandName.equals("AUTH")) {
|
||||
auth(currentLine);
|
||||
} else {
|
||||
LOGGER.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
|
||||
logger.log(Level.SEVERE, "ERROR command unknown: {0}", commandName);
|
||||
println("-ERR unknown command");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ public class SMTPLoginHandler extends SMTPHandler {
|
|||
if (ct.hasMoreTokens())
|
||||
ir = ct.nextToken();
|
||||
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine(line);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine(line);
|
||||
if (mech.equalsIgnoreCase("PLAIN"))
|
||||
plain(ir);
|
||||
else if (mech.equalsIgnoreCase("LOGIN"))
|
||||
|
@ -82,8 +82,8 @@ public class SMTPLoginHandler extends SMTPHandler {
|
|||
byte[] response = resp.getBytes(StandardCharsets.US_ASCII);
|
||||
response = Base64.getDecoder().decode(response);
|
||||
String u = new String(response, StandardCharsets.UTF_8);
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("USER: " + u);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("USER: " + u);
|
||||
println("334");
|
||||
|
||||
// read password
|
||||
|
@ -95,8 +95,8 @@ public class SMTPLoginHandler extends SMTPHandler {
|
|||
response = resp.getBytes(StandardCharsets.US_ASCII);
|
||||
response = Base64.getDecoder().decode(response);
|
||||
String p = new String(response, StandardCharsets.UTF_8);
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("PASSWORD: " + p);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("PASSWORD: " + p);
|
||||
|
||||
//System.out.printf("USER: %s, PASSWORD: %s%n", u, p);
|
||||
if (!u.equals(username) || !p.equals(password)) {
|
||||
|
|
|
@ -72,11 +72,11 @@ public class SMTPSaslHandler extends SMTPHandler {
|
|||
CallbackHandler cbh = new CallbackHandler() {
|
||||
@Override
|
||||
public void handle(Callback[] callbacks) {
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL callback length: " + callbacks.length);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL callback length: " + callbacks.length);
|
||||
for (int i = 0; i < callbacks.length; i++) {
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL callback " + i + ": " + callbacks[i]);
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL callback " + i + ": " + callbacks[i]);
|
||||
if (callbacks[i] instanceof NameCallback) {
|
||||
NameCallback ncb = (NameCallback) callbacks[i];
|
||||
ncb.setName(u);
|
||||
|
@ -85,8 +85,8 @@ public class SMTPSaslHandler extends SMTPHandler {
|
|||
pcb.setPassword(p.toCharArray());
|
||||
} else if (callbacks[i] instanceof AuthorizeCallback) {
|
||||
AuthorizeCallback ac = (AuthorizeCallback) callbacks[i];
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL authorize: " +
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL authorize: " +
|
||||
"authn: " + ac.getAuthenticationID() + ", " +
|
||||
"authz: " + ac.getAuthorizationID() + ", " +
|
||||
"authorized: " + ac.getAuthorizedID());
|
||||
|
@ -119,25 +119,25 @@ public class SMTPSaslHandler extends SMTPHandler {
|
|||
try {
|
||||
ss = Sasl.createSaslServer(mech, "smtp", "localhost", null, cbh);
|
||||
} catch (SaslException sex) {
|
||||
LOGGER.log(Level.FINE, "Failed to create SASL server", sex);
|
||||
logger.log(Level.FINE, "Failed to create SASL server", sex);
|
||||
println("501 Failed to create SASL server");
|
||||
return;
|
||||
}
|
||||
if (ss == null) {
|
||||
LOGGER.fine("No SASL support");
|
||||
logger.fine("No SASL support");
|
||||
println("501 No SASL support");
|
||||
return;
|
||||
}
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL server " + ss.getMechanismName());
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL server " + ss.getMechanismName());
|
||||
|
||||
byte[] response = ir.getBytes();
|
||||
while (!ss.isComplete()) {
|
||||
try {
|
||||
byte[] chal = ss.evaluateResponse(response);
|
||||
// send challenge
|
||||
if (LOGGER.isLoggable(Level.FINE))
|
||||
LOGGER.fine("SASL challenge: " +
|
||||
if (logger.isLoggable(Level.FINE))
|
||||
logger.fine("SASL challenge: " +
|
||||
ASCIIUtility.toString(chal, 0, chal.length));
|
||||
byte[] ba = Base64.getEncoder().encode(chal);
|
||||
if (ba.length > 0)
|
||||
|
@ -164,7 +164,7 @@ public class SMTPSaslHandler extends SMTPHandler {
|
|||
if (qop != null && (qop.equalsIgnoreCase("auth-int") ||
|
||||
qop.equalsIgnoreCase("auth-conf"))) {
|
||||
// XXX - NOT SUPPORTED!!!
|
||||
LOGGER.fine(
|
||||
logger.fine(
|
||||
"SASL Mechanism requires integrity or confidentiality");
|
||||
println("501 " +
|
||||
"SASL Mechanism requires integrity or confidentiality");
|
||||
|
|
|
@ -16,12 +16,9 @@
|
|||
|
||||
package org.xbib.net.mail.test.test;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.logging.Level;
|
||||
|
@ -35,64 +32,82 @@ import java.util.logging.Logger;
|
|||
* @author sbo
|
||||
* @author Bill Shannon
|
||||
*/
|
||||
public abstract class ProtocolHandler implements Runnable {
|
||||
public abstract class ProtocolHandler {
|
||||
|
||||
/**
|
||||
* Logger for this class.
|
||||
*/
|
||||
protected final Logger LOGGER = Logger.getLogger(this.getClass().getName());
|
||||
private static final Logger logger = Logger.getLogger(ProtocolHandler.class.getName());
|
||||
|
||||
/**
|
||||
* Quit?
|
||||
*/
|
||||
protected boolean quit;
|
||||
|
||||
/**
|
||||
* Writer to socket.
|
||||
*/
|
||||
protected PrintWriter writer;
|
||||
|
||||
/**
|
||||
* Input from socket.
|
||||
*/
|
||||
protected InputStream inputStream;
|
||||
|
||||
public ProtocolHandler(InputStream inputStream, OutputStream outputStream) {
|
||||
this.inputStream = new BufferedInputStream(inputStream);
|
||||
this.writer = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
|
||||
public void handle(InputStream inputStream, OutputStream outputStream) {
|
||||
try {
|
||||
sendGreetings(outputStream);
|
||||
while (!quit) {
|
||||
handleCommand(inputStream, outputStream);
|
||||
}
|
||||
if (quit) {
|
||||
try {
|
||||
if (inputStream != null)
|
||||
inputStream.close();
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
logger.log(Level.SEVERE, "Error", e);
|
||||
}
|
||||
}
|
||||
} catch (IOException sex) {
|
||||
// ignore it, often get "connection reset" when client closes
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error", e);
|
||||
} finally {
|
||||
try {
|
||||
if (inputStream != null)
|
||||
inputStream.close();
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
logger.log(Level.SEVERE, "Error", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally send a greeting when first connected.
|
||||
*/
|
||||
public void sendGreetings() throws IOException {
|
||||
public void sendGreetings(OutputStream outputStream) throws IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and process a single command.
|
||||
*/
|
||||
public abstract void handleCommand() throws IOException;
|
||||
public abstract void handleCommand(InputStream inputStream, OutputStream outputStream) throws IOException;
|
||||
|
||||
/**
|
||||
* Read a single line terminated by newline or CRLF.
|
||||
* Convert the UTF-8 bytes in the line (minus the line terminator)
|
||||
* to a String.
|
||||
*/
|
||||
protected String readLine() throws IOException {
|
||||
protected String readLine(InputStream inputStream) throws IOException {
|
||||
byte[] buf = new byte[128];
|
||||
|
||||
int room = buf.length;
|
||||
int offset = 0;
|
||||
int c;
|
||||
|
||||
while ((c = inputStream.read()) != -1) {
|
||||
if (c == '\n') {
|
||||
break;
|
||||
} else if (c == '\r') {
|
||||
int c2 = inputStream.read();
|
||||
if ((c2 != '\n') && (c2 != -1)) {
|
||||
if (!(inputStream instanceof PushbackInputStream))
|
||||
this.inputStream = new PushbackInputStream(inputStream);
|
||||
if (!(inputStream instanceof PushbackInputStream)) {
|
||||
inputStream = new PushbackInputStream(inputStream);
|
||||
}
|
||||
((PushbackInputStream) inputStream).unread(c2);
|
||||
}
|
||||
break;
|
||||
|
@ -106,51 +121,13 @@ public abstract class ProtocolHandler implements Runnable {
|
|||
buf[offset++] = (byte) c;
|
||||
}
|
||||
}
|
||||
if ((c == -1) && (offset == 0))
|
||||
if ((c == -1) && (offset == 0)) {
|
||||
return null;
|
||||
}
|
||||
return new String(buf, 0, offset, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final void run() {
|
||||
try {
|
||||
sendGreetings();
|
||||
while (!quit) {
|
||||
handleCommand();
|
||||
}
|
||||
} catch (IOException sex) {
|
||||
// ignore it, often get "connection reset" when client closes
|
||||
} catch (Exception e) {
|
||||
LOGGER.log(Level.SEVERE, "Error", e);
|
||||
} finally {
|
||||
try {
|
||||
if (inputStream != null)
|
||||
inputStream.close();
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
LOGGER.log(Level.SEVERE, "Error", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quit.
|
||||
*/
|
||||
public void exit() {
|
||||
quit = true;
|
||||
try {
|
||||
if (inputStream != null)
|
||||
inputStream.close();
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
LOGGER.log(Level.SEVERE, "Error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package org.xbib.net.mail.test.test;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -32,8 +35,11 @@ import java.net.InetSocketAddress;
|
|||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A simple server for testing.
|
||||
|
@ -46,13 +52,17 @@ import java.util.List;
|
|||
* @author sbo
|
||||
* @author Bill Shannon
|
||||
*/
|
||||
public final class TestServer extends Thread {
|
||||
public final class TestServer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TestServer.class.getName());
|
||||
|
||||
/**
|
||||
* Server socket.
|
||||
*/
|
||||
private ServerSocket serverSocket;
|
||||
|
||||
private final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
|
||||
/**
|
||||
* Keep on?
|
||||
*/
|
||||
|
@ -63,7 +73,6 @@ public final class TestServer extends Thread {
|
|||
*/
|
||||
private final ProtocolHandler handler;
|
||||
|
||||
private List<Thread> clients = new ArrayList<Thread>();
|
||||
|
||||
/**
|
||||
* Test server.
|
||||
|
@ -83,7 +92,6 @@ public final class TestServer extends Thread {
|
|||
public TestServer(final ProtocolHandler handler, final boolean isSSL)
|
||||
throws IOException {
|
||||
this.handler = handler;
|
||||
|
||||
/*
|
||||
* Allowing the JDK to pick a port number sometimes results in it
|
||||
* picking a number that's already in use by another process, but
|
||||
|
@ -96,10 +104,6 @@ public final class TestServer extends Thread {
|
|||
* already in use.
|
||||
*/
|
||||
for (int port = 49152; port < 50000 /*65535*/; port++) {
|
||||
/*
|
||||
if (isListening(port))
|
||||
continue;
|
||||
*/
|
||||
try {
|
||||
serverSocket = createServerSocket(port, isSSL);
|
||||
return;
|
||||
|
@ -170,12 +174,7 @@ public final class TestServer extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
super.start();
|
||||
// don't return until server is really listening
|
||||
// XXX - this might not be necessary
|
||||
for (int tries = 0; tries < 10; tries++) {
|
||||
|
@ -193,25 +192,23 @@ public final class TestServer extends Thread {
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
keepOn = true;
|
||||
|
||||
while (keepOn) {
|
||||
try {
|
||||
final Socket clientSocket = serverSocket.accept();
|
||||
final ProtocolHandler pHandler = handler;
|
||||
pHandler.setClientSocket(clientSocket);
|
||||
Thread t = new Thread(pHandler);
|
||||
synchronized (clients) {
|
||||
clients.add(t);
|
||||
executorService.submit(new Callable<Object>() {
|
||||
final InputStream inputStream = new BufferedInputStream(clientSocket.getInputStream());
|
||||
final OutputStream outputStream = clientSocket.getOutputStream();
|
||||
@Override
|
||||
public Object call() {
|
||||
handler.handle(inputStream, outputStream);
|
||||
return null;
|
||||
}
|
||||
t.start();
|
||||
} catch (final IOException e) {
|
||||
//e.printStackTrace();
|
||||
} catch (NullPointerException nex) {
|
||||
// serverSocket can be set to null before we could check
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -219,20 +216,14 @@ public final class TestServer extends Thread {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of clients ever created.
|
||||
*/
|
||||
public int clientCount() {
|
||||
/*public int clientCount() {
|
||||
synchronized (clients) {
|
||||
// isListening creates a client that we don't count
|
||||
return clients.size() - 1;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Wait for at least n clients to terminate.
|
||||
*/
|
||||
public void waitForClients(int n) {
|
||||
/*public void waitForClients(int n) {
|
||||
if (n > clientCount())
|
||||
throw new RuntimeException("not that many clients");
|
||||
for (; ; ) {
|
||||
|
@ -250,7 +241,7 @@ public final class TestServer extends Thread {
|
|||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private boolean isListening(int port) {
|
||||
try {
|
||||
|
@ -265,10 +256,4 @@ public final class TestServer extends Thread {
|
|||
return false;
|
||||
}
|
||||
|
||||
class WrappedProtocolHandler {
|
||||
Socket clientSocket;
|
||||
ProtocolHandler handler;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue