diff --git a/.classpath b/.classpath
index 9a8214e8f..3eabaaea9 100644
--- a/.classpath
+++ b/.classpath
@@ -1,26 +1,28 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java b/api/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
index 3eb5ea136..a71b1e8f7 100644
--- a/api/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
+++ b/api/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java
@@ -1,5 +1,6 @@
package net.sf.briar.api.plugins.simplex;
+import java.io.IOException;
import java.io.InputStream;
/**
@@ -8,8 +9,9 @@ import java.io.InputStream;
*/
public interface SimplexTransportReader {
- /** Returns an input stream for reading from the transport. */
- InputStream getInputStream();
+ /** Returns an input stream for reading from the transport.
+ * @throws IOException */
+ InputStream getInputStream() throws IOException;
/**
* Closes the reader and disposes of any associated resources. The first
diff --git a/api/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java b/api/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
index ea5c31684..a6f55ed4c 100644
--- a/api/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
+++ b/api/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java
@@ -1,5 +1,6 @@
package net.sf.briar.api.plugins.simplex;
+import java.io.IOException;
import java.io.OutputStream;
/**
@@ -11,8 +12,9 @@ public interface SimplexTransportWriter {
/** Returns the capacity of the transport in bytes. */
long getCapacity();
- /** Returns an output stream for writing to the transport. */
- OutputStream getOutputStream();
+ /** Returns an output stream for writing to the transport.
+ * @throws IOException */
+ OutputStream getOutputStream() throws IOException;
/**
* Returns true if the output stream should be flushed after each packet.
diff --git a/components/net/sf/briar/plugins/email/GmailPlugin.java b/components/net/sf/briar/plugins/email/GmailPlugin.java
new file mode 100644
index 000000000..311273e67
--- /dev/null
+++ b/components/net/sf/briar/plugins/email/GmailPlugin.java
@@ -0,0 +1,306 @@
+package net.sf.briar.plugins.email;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+import javax.mail.Flags;
+import javax.mail.Flags.Flag;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.NoSuchProviderException;
+import javax.mail.PasswordAuthentication;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.mail.search.FlagTerm;
+import javax.microedition.io.StreamConnection;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportConfig;
+import net.sf.briar.api.TransportProperties;
+import net.sf.briar.api.crypto.PseudoRandom;
+import net.sf.briar.api.plugins.simplex.SimplexPlugin;
+import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
+import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
+import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
+import net.sf.briar.api.protocol.TransportId;
+import net.sf.briar.util.StringUtils;
+
+public class GmailPlugin implements SimplexPlugin {
+
+ public static final byte[] TRANSPORT_ID =
+ StringUtils.fromHexString("57ead1961d2120bbbbe8256ff9ce6ae2"
+ + "ef5535e44330c04cedcbafac4d756f0c"
+ + "e8dd928ed1d7a9e7b89fd62210aa30bf");
+
+ private static final TransportId ID = new TransportId(TRANSPORT_ID);
+ private final Executor pluginExecutor;
+ private final SimplexPluginCallback callback;
+// private static GmailTransportConnectionReader reader;
+// private static GmailTransportConnectionWriter writer;
+
+
+ public GmailPlugin(Executor pluginExecutor, SimplexPluginCallback callback) {
+ this.pluginExecutor = pluginExecutor;
+ this.callback = callback;
+ }
+
+
+ public TransportId getId() {
+ return ID;
+ }
+
+ public void start() throws IOException {
+
+ pluginExecutor.execute(new Runnable() {
+ public void run() {
+ connectIMAP();
+ }
+ });
+ }
+
+ protected void checkUnreadEmails(Folder inbox) {
+
+ try {
+ FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
+ Message msg[] = inbox.search(ft);
+// System.out.println("Unread Messages: "+ msg.length);
+
+ for(final Message message:msg) {
+ try {
+ callback.readerCreated(new SimplexTransportReader() {
+
+ public InputStream getInputStream() throws IOException {
+ try {
+ return message.getInputStream();
+ } catch (MessagingException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public void dispose(boolean exception,
+ boolean recognised) {
+ try {
+ message.setFlag(Flag.DELETED, recognised);
+ message.setFlag(Flag.SEEN, recognised);
+ } catch (MessagingException e) {
+ e.printStackTrace();
+ }
+ }});
+
+ System.out.println("DATE: " + message.getSentDate().toString());
+ System.out.println("FROM: " + message.getFrom()[0].toString());
+ System.out.println("SUBJECT: " + message.getSubject().toString());
+ System.out.println("CONTENT: " + message.getContent().toString());
+ System.out.println("=================================================");
+
+
+ } catch (Exception e) {
+ System.out.println("No Information");
+ }
+ }
+
+ } catch (MessagingException e) {
+ System.out.println(e.toString());
+ }
+ }
+
+
+ protected void connectIMAP() {
+ Properties props = System.getProperties();
+ props.setProperty("mail.store.protocol", "imaps");
+ final ArrayList userPass = getAuthenticationDetails(callback.getConfig());
+ if (userPass != null)
+ {
+ try {
+
+ Session session = Session.getDefaultInstance(props, null);
+ Store store = session.getStore("imaps");
+
+ synchronized(this)
+ {
+ store.connect("imap.gmail.com", userPass.get(0), userPass.get(1));
+ }
+
+ Folder inbox = store.getFolder("Inbox");
+ inbox.open(Folder.READ_ONLY);
+
+ checkUnreadEmails(inbox);
+
+ }
+ catch (NoSuchProviderException e) {
+ System.out.println(e.toString());
+ System.exit(1);
+ } catch (MessagingException e) {
+ System.out.println(e.toString());
+ System.exit(2);
+ }
+ }
+ }
+
+ protected boolean connectSMTP(ContactId cid)
+ {
+ boolean sent = false;
+ if(discoverContactEmail(cid) != null)
+ {
+ Properties prop = new Properties();
+ prop.put("mail.smtp.host", "smtp.gmail.com");
+ prop.put("mail.smtp.socketFactory.port", "465");
+ prop.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+ prop.put("mail.smtp.auth", "true");
+ prop.put("mail.smtp.port", "465");
+
+ final ArrayList userPass = getAuthenticationDetails(callback.getConfig());
+
+ if (userPass != null)
+ {
+ Session session;
+
+ synchronized(this)
+ {
+ session = Session.getDefaultInstance(prop, new javax.mail.Authenticator() {
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(userPass.get(0),userPass.get(1));
+ }
+ });
+ }
+
+// SimplexTransportWriter writer = createWriter(cid);
+
+ sent = sendMessage(session,cid);
+ }
+ }
+ return sent;
+ }
+
+
+ private synchronized boolean sendMessage(Session session, ContactId cid)
+ {
+ boolean sent = false;
+
+ try {
+ Message message = new MimeMessage(session);
+ TransportProperties props = callback.getLocalProperties();
+ String userEmail = props.get("email");
+
+ message.setFrom(new InternetAddress(userEmail));
+ message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(discoverContactEmail(cid)));
+
+ message.setSubject("Test Subject");
+ message.setText("Test content");
+
+ Transport.send(message);
+
+ sent = true;
+ return sent;
+
+ } catch (MessagingException e) {
+ return sent;
+ }
+
+ }
+
+
+ public void stop() throws IOException {
+ synchronized(this) {
+ //close open connections
+ }
+ }
+
+ public boolean shouldPoll() {
+ return false;
+ }
+
+ public long getPollingInterval() throws UnsupportedOperationException {
+ return 0;
+ }
+
+ public void poll(Collection connected) throws UnsupportedOperationException{
+
+ }
+
+ public boolean supportsInvitations() {
+ return false;
+ }
+
+ /*
+ * Gets the user's authentication details
+ * ArrayList.get(0) = username, ArrayList.get(1) = password,
+ * or null if either value is null.
+ */
+ private ArrayList getAuthenticationDetails(TransportConfig config)
+ {
+ try {
+ ArrayList usernamePass = new ArrayList();
+ usernamePass.add(0, config.get("username"));
+ usernamePass.add(1, config.get("password"));
+
+ if(usernamePass.get(0)!=null && usernamePass.get(1)!=null)
+ return usernamePass;
+ else
+ return null;
+ } catch(Exception e) {
+ return null;
+ }
+
+ }
+
+ /*
+ * looks up the contact's email address given the contactID
+ * @param ContactId
+ * @return String email
+ */
+ private String discoverContactEmail(ContactId cid)
+ {
+ try {
+ Map remote = callback.getRemoteProperties();
+ TransportProperties tp = remote.get(cid);
+ String address = tp.get("email");
+ return address;
+ } catch(Exception e) {
+ return null;
+ }
+ }
+
+ public SimplexTransportReader createReader(ContactId c) {
+
+ return null;
+ }
+
+ public SimplexTransportWriter createWriter(ContactId c) {
+
+ return null;
+ }
+
+ public SimplexTransportWriter sendInvitation(PseudoRandom r, long timeout) throws UnsupportedOperationException {
+
+ return null;
+ }
+
+ public SimplexTransportReader acceptInvitation(PseudoRandom r, long timeout) throws UnsupportedOperationException {
+
+ return null;
+ }
+
+ public SimplexTransportWriter sendInvitationResponse(PseudoRandom r,
+ long timeout) throws UnsupportedOperationException{
+
+ return null;
+ }
+
+ public SimplexTransportReader acceptInvitationResponse(PseudoRandom r,
+ long timeout) throws UnsupportedOperationException{
+
+ return null;
+ }
+
+}
diff --git a/components/net/sf/briar/plugins/email/GmailPluginFactory.java b/components/net/sf/briar/plugins/email/GmailPluginFactory.java
new file mode 100644
index 000000000..244a89373
--- /dev/null
+++ b/components/net/sf/briar/plugins/email/GmailPluginFactory.java
@@ -0,0 +1,18 @@
+package net.sf.briar.plugins.email;
+
+import java.util.concurrent.Executor;
+
+import net.sf.briar.api.plugins.simplex.SimplexPlugin;
+import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
+import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
+
+public class GmailPluginFactory implements SimplexPluginFactory {
+
+ public SimplexPlugin createPlugin(Executor pluginExecutor,
+ SimplexPluginCallback callback) {
+
+ return new GmailPlugin(pluginExecutor, callback);
+ }
+
+
+}
diff --git a/components/net/sf/briar/plugins/email/GmailTransportConnectionReader.java b/components/net/sf/briar/plugins/email/GmailTransportConnectionReader.java
new file mode 100644
index 000000000..6689e8d21
--- /dev/null
+++ b/components/net/sf/briar/plugins/email/GmailTransportConnectionReader.java
@@ -0,0 +1,35 @@
+package net.sf.briar.plugins.email;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.microedition.io.StreamConnection;
+
+import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
+
+public class GmailTransportConnectionReader implements SimplexTransportReader{
+
+ private static final Logger LOG = Logger.getLogger(GmailTransportConnectionReader.class.getName());
+
+ private final StreamConnection stream;
+
+ GmailTransportConnectionReader(StreamConnection stream) {
+ this.stream = stream;
+ }
+
+ public InputStream getInputStream() throws IOException {
+
+ return stream.openInputStream();
+ }
+
+ public void dispose(boolean exception, boolean recognised) {
+ try {
+ stream.close();
+ } catch(IOException e) {
+ if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
+ }
+ }
+
+}
diff --git a/components/net/sf/briar/plugins/email/GmailTransportConnectionWriter.java b/components/net/sf/briar/plugins/email/GmailTransportConnectionWriter.java
new file mode 100644
index 000000000..2fa6bf430
--- /dev/null
+++ b/components/net/sf/briar/plugins/email/GmailTransportConnectionWriter.java
@@ -0,0 +1,43 @@
+package net.sf.briar.plugins.email;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.microedition.io.StreamConnection;
+
+import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
+
+public class GmailTransportConnectionWriter implements SimplexTransportWriter {
+
+ private static final Logger LOG = Logger.getLogger(GmailTransportConnectionWriter.class.getName());
+
+ private final StreamConnection stream;
+ private final long capacity = 25 * 1000 * 1000;
+
+ public GmailTransportConnectionWriter(StreamConnection stream) {
+ this.stream = stream;
+ }
+
+ public long getCapacity() {
+ return capacity;
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ return stream.openOutputStream();
+ }
+
+ public boolean shouldFlush() {
+ return false;
+ }
+
+ public void dispose(boolean exception) {
+ try {
+ stream.close();
+ } catch(IOException e) {
+ if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
+ }
+ }
+
+}
diff --git a/components/net/sf/briar/plugins/email/PipeDataSource.java b/components/net/sf/briar/plugins/email/PipeDataSource.java
new file mode 100644
index 000000000..06f23cd89
--- /dev/null
+++ b/components/net/sf/briar/plugins/email/PipeDataSource.java
@@ -0,0 +1,31 @@
+package net.sf.briar.plugins.email;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import javax.activation.DataSource;
+
+public class PipeDataSource implements DataSource{
+
+ public String getContentType() {
+ return "application/octet-stream";
+ }
+
+ public PipedInputStream getInputStream() throws IOException {
+ return null;
+ }
+
+ public String getName() {
+ return "foo";
+ }
+
+ public PipedOutputStream getOutputStream() throws UnsupportedOperationException {
+ return null;
+ }
+
+
+
+}
diff --git a/components/net/sf/briar/plugins/file/FilePlugin.java b/components/net/sf/briar/plugins/file/FilePlugin.java
index 4a5987acf..2d5a6582e 100644
--- a/components/net/sf/briar/plugins/file/FilePlugin.java
+++ b/components/net/sf/briar/plugins/file/FilePlugin.java
@@ -22,7 +22,7 @@ import net.sf.briar.util.StringUtils;
import org.apache.commons.io.FileSystemUtils;
-abstract class FilePlugin implements SimplexPlugin {
+public abstract class FilePlugin implements SimplexPlugin {
private static final Logger LOG =
Logger.getLogger(FilePlugin.class.getName());
diff --git a/lib/activation.jar b/lib/activation.jar
new file mode 100644
index 000000000..29a59a9ee
Binary files /dev/null and b/lib/activation.jar differ
diff --git a/lib/mail.jar b/lib/mail.jar
new file mode 100644
index 000000000..300f436ad
Binary files /dev/null and b/lib/mail.jar differ
diff --git a/test/net/sf/briar/plugins/email/GmailPluginTester.java b/test/net/sf/briar/plugins/email/GmailPluginTester.java
new file mode 100644
index 000000000..412caa6f8
--- /dev/null
+++ b/test/net/sf/briar/plugins/email/GmailPluginTester.java
@@ -0,0 +1,127 @@
+package net.sf.briar.plugins.email;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.Executors;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.TransportConfig;
+import net.sf.briar.api.TransportProperties;
+import net.sf.briar.api.plugins.simplex.SimplexPluginCallback;
+import net.sf.briar.api.plugins.simplex.SimplexTransportReader;
+import net.sf.briar.api.plugins.simplex.SimplexTransportWriter;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class GmailPluginTester {
+
+SimplexPluginCallback callback;
+TransportProperties local, props1;
+TransportConfig config;
+ContactId test1;
+Map map = new HashMap();
+
+ @Before
+ public void setup()
+ {
+
+ local = new TransportProperties();
+ local.put("email",System.getenv("USER_GMAIL_ADDRESS"));
+
+ config = new TransportConfig();
+ config.put("username", System.getenv("GMAIL_USERNAME"));
+ config.put("password", System.getenv("GMAIL_PASSWORD"));
+
+ props1 = new TransportProperties();
+ props1.put("email", System.getenv("CONTACT1_EMAIL"));
+ test1 = new ContactId(12);
+
+ map.put(test1, props1);
+ assertEquals(1,map.size());
+
+ callback = new SimplexPluginCallback() {
+
+ public void showMessage(String... message) {
+
+ }
+
+ public boolean showConfirmationMessage(String... message) {
+ return false;
+ }
+
+ public int showChoice(String[] options, String... message) {
+ return 0;
+ }
+
+ public void setLocalProperties(TransportProperties p) {
+
+ }
+
+ public void setConfig(TransportConfig c) {
+ config = c;
+ }
+
+
+ public Map getRemoteProperties() {
+ return map;
+ }
+
+ public TransportProperties getLocalProperties() {
+ return local;
+ }
+
+ public TransportConfig getConfig() {
+ return config;
+ }
+
+ public void writerCreated(ContactId c, SimplexTransportWriter w) {
+
+ }
+
+ public void readerCreated(SimplexTransportReader r) {
+
+ }
+ };
+
+ callback.setLocalProperties(local);
+ callback.setConfig(config);
+
+
+ }
+
+ @Test
+ public void testPluginFactoryCreation()
+ {
+ GmailPluginFactory plugin = new GmailPluginFactory();
+ plugin.createPlugin(Executors.newSingleThreadExecutor(), callback);
+
+ }
+
+ @Test
+ public void testGmailPluginIMAP()
+ {
+ GmailPlugin pluginTest = new GmailPlugin(Executors.newSingleThreadExecutor(), callback);
+ try {
+ pluginTest.start();
+ } catch (IOException e) {
+ System.out.println("IO Exception got caught");
+ }
+ }
+
+ @Test
+ public void testGmailSMTP()
+ {
+ GmailPlugin pluginTest = new GmailPlugin(Executors.newSingleThreadExecutor(), callback);
+ assertEquals(true, pluginTest.connectSMTP(test1));
+ assertEquals(false, pluginTest.connectSMTP(new ContactId(7)));
+ }
+
+}