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