1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-30 13:12:25 -05:00

Add support for incoming-server and outgoing-server elements on import

This commit is contained in:
cketti 2011-06-09 05:50:43 +02:00
parent 4d11c80f65
commit ded489daab
10 changed files with 399 additions and 8 deletions

View File

@ -56,6 +56,8 @@ public class Account implements BaseAccount {
public static final boolean DEFAULT_REPLY_AFTER_QUOTE = false;
public static final String ACCOUNT_DESCRIPTION_KEY = "description";
public static final String STORE_URI_KEY = "storeUri";
public static final String TRANSPORT_URI_KEY = "transportUri";
public static final String IDENTITY_NAME_KEY = "name";
public static final String IDENTITY_EMAIL_KEY = "email";

View File

@ -108,6 +108,31 @@ public abstract class Store {
}
}
/**
* Creates a store URI from the information supplied in the {@link ServerSettings} object.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A store URI that holds the same information as the {@code server} parameter.
*
* @see ImapStore#createUri(ServerSettings)
* @see Pop3Store#createUri(ServerSettings)
* @see WebDavStore#createUri(ServerSettings)
*/
public static String createStoreUri(ServerSettings server) {
if (ImapStore.STORE_TYPE.equals(server.type)) {
return ImapStore.createUri(server);
} else if (Pop3Store.STORE_TYPE.equals(server.type)) {
return Pop3Store.createUri(server);
} else if (WebDavStore.STORE_TYPE.equals(server.type)) {
return WebDavStore.createUri(server);
} else {
throw new IllegalArgumentException("Not a valid store URI");
}
}
protected final Account mAccount;

View File

@ -44,6 +44,27 @@ public abstract class Transport {
}
}
/**
* Creates a transport URI from the information supplied in the {@link ServerSettings} object.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A transport URI that holds the same information as the {@code server} parameter.
*
* @see SmtpTransport#createUri(ServerSettings)
* @see WebDavTransport#createUri(ServerSettings)
*/
public static String createTransportUri(ServerSettings server) {
if (SmtpTransport.TRANSPORT_TYPE.equals(server.type)) {
return SmtpTransport.createUri(server);
} else if (WebDavTransport.TRANSPORT_TYPE.equals(server.type)) {
return WebDavTransport.createUri(server);
} else {
throw new IllegalArgumentException("Not a valid transport URI");
}
}
public abstract void open() throws MessagingException;

View File

@ -16,6 +16,7 @@ import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
@ -102,6 +103,8 @@ import java.util.zip.InflaterInputStream;
* </pre>
*/
public class ImapStore extends Store {
public static final String STORE_TYPE = "IMAP";
public static final int CONNECTION_SECURITY_NONE = 0;
public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
public static final int CONNECTION_SECURITY_TLS_REQUIRED = 2;
@ -218,13 +221,66 @@ public class ImapStore extends Store {
password, pathPrefix);
}
/**
* Creates an ImapStore URI with the supplied settings.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return An ImapStore URI that holds the same information as the {@code server} parameter.
*
* @see Account#getStoreUri()
* @see ImapStore#decodeUri(String)
*/
public static String createUri(ServerSettings server) {
String userEnc;
String passwordEnc;
try {
userEnc = URLEncoder.encode(server.username, "UTF-8");
passwordEnc = URLEncoder.encode(server.password, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("Could not encode username or password", e);
}
String scheme;
switch (server.connectionSecurity) {
case SSL_TLS_OPTIONAL:
scheme = "imap+ssl";
break;
case SSL_TLS_REQUIRED:
scheme = "imap+ssl+";
break;
case STARTTLS_OPTIONAL:
scheme = "imap+tls";
break;
case STARTTLS_REQUIRED:
scheme = "imap+tls+";
break;
default:
case NONE:
scheme = "imap";
break;
}
String userInfo = server.authenticationType + ":" + userEnc + ":" + passwordEnc;
try {
Map<String, String> extra = server.getExtra();
String prefix = (extra != null) ? extra.get(ImapStoreSettings.PATH_PREFIX_KEY) : null;
return new URI(scheme, userInfo, server.host, server.port,
prefix,
null, null).toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Can't create ImapStore URI", e);
}
}
/**
* This class is used to store the decoded contents of an ImapStore URI.
*
* @see ImapStore#decodeUri(String)
*/
private static class ImapStoreSettings extends ServerSettings {
private static final String STORE_TYPE = "IMAP";
private static final String PATH_PREFIX_KEY = "pathPrefix";
public final String pathPrefix;

View File

@ -26,7 +26,7 @@ import java.util.HashSet;
import java.util.List;
public class Pop3Store extends Store {
private static final String STORE_TYPE = "POP3";
public static final String STORE_TYPE = "POP3";
public static final int CONNECTION_SECURITY_NONE = 0;
public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
@ -105,6 +105,57 @@ public class Pop3Store extends Store {
password);
}
/**
* Creates a Pop3Store URI with the supplied settings.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A Pop3Store URI that holds the same information as the {@code server} parameter.
*
* @see Account#getStoreUri()
* @see Pop3Store#decodeUri(String)
*/
public static String createUri(ServerSettings server) {
String userEnc;
String passwordEnc;
try {
userEnc = URLEncoder.encode(server.username, "UTF-8");
passwordEnc = URLEncoder.encode(server.password, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("Could not encode username or password", e);
}
String scheme;
switch (server.connectionSecurity) {
case SSL_TLS_OPTIONAL:
scheme = "pop3+ssl";
break;
case SSL_TLS_REQUIRED:
scheme = "pop3+ssl+";
break;
case STARTTLS_OPTIONAL:
scheme = "pop3+tls";
break;
case STARTTLS_REQUIRED:
scheme = "pop3+tls+";
break;
default:
case NONE:
scheme = "pop3";
break;
}
String userInfo = userEnc + ":" + passwordEnc;
try {
return new URI(scheme, userInfo, server.host, server.port, null, null,
null).toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Can't create Pop3Store URI", e);
}
}
private String mHost;
private int mPort;

View File

@ -62,6 +62,8 @@ import java.util.zip.GZIPInputStream;
* </pre>
*/
public class WebDavStore extends Store {
public static final String STORE_TYPE = "WebDAV";
// Security options
private static final short CONNECTION_SECURITY_NONE = 0;
private static final short CONNECTION_SECURITY_TLS_OPTIONAL = 1;
@ -185,13 +187,72 @@ public class WebDavStore extends Store {
alias, path, authPath, mailboxPath);
}
/**
* Creates a WebDavStore URI with the supplied settings.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A WebDavStore URI that holds the same information as the {@code server} parameter.
*
* @see Account#getStoreUri()
* @see WebDavStore#decodeUri(String)
*/
public static String createUri(ServerSettings server) {
String userEnc;
String passwordEnc;
try {
userEnc = URLEncoder.encode(server.username, "UTF-8");
passwordEnc = URLEncoder.encode(server.password, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("Could not encode username or password", e);
}
String scheme;
switch (server.connectionSecurity) {
case SSL_TLS_OPTIONAL:
scheme = "webdav+ssl";
break;
case SSL_TLS_REQUIRED:
scheme = "webdav+ssl+";
break;
case STARTTLS_OPTIONAL:
scheme = "webdav+tls";
break;
case STARTTLS_REQUIRED:
scheme = "webdav+tls+";
break;
default:
case NONE:
scheme = "webdav";
break;
}
Map<String, String> extra = server.getExtra();
String userInfo = userEnc + ":" + passwordEnc;
String path = extra.get(WebDavStoreSettings.PATH_KEY);
path = (path != null) ? path : "";
String authPath = extra.get(WebDavStoreSettings.AUTH_PATH_KEY);
authPath = (authPath != null) ? authPath : "";
String mailboxPath = extra.get(WebDavStoreSettings.MAILBOX_PATH_KEY);
mailboxPath = (mailboxPath != null) ? mailboxPath : "";
String uriPath = path + "|" + authPath + "|" + mailboxPath;
try {
return new URI(scheme, userInfo, server.host, server.port, uriPath,
null, null).toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Can't create WebDavStore URI", e);
}
}
/**
* This class is used to store the decoded contents of an WebDavStore URI.
*
* @see WebDavStore#decodeUri(String)
*/
private static class WebDavStoreSettings extends ServerSettings {
private static final String STORE_TYPE = "WebDAV";
private static final String ALIAS_KEY = "alias";
private static final String PATH_KEY = "path";
private static final String AUTH_PATH_KEY = "authPath";

View File

@ -2,6 +2,7 @@
package com.fsck.k9.mail.transport;
import android.util.Log;
import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.mail.*;
import com.fsck.k9.mail.Message.RecipientType;
@ -31,7 +32,7 @@ import org.apache.commons.codec.binary.Hex;
import java.util.*;
public class SmtpTransport extends Transport {
private static final String TRANSPORT_TYPE = "SMTP";
public static final String TRANSPORT_TYPE = "SMTP";
public static final int CONNECTION_SECURITY_NONE = 0;
public static final int CONNECTION_SECURITY_TLS_OPTIONAL = 1;
@ -113,6 +114,57 @@ public class SmtpTransport extends Transport {
authenticationType, username, password);
}
/**
* Creates a SmtpTransport URI with the supplied settings.
*
* @param server
* The {@link ServerSettings} object that holds the server settings.
*
* @return A SmtpTransport URI that holds the same information as the {@code server} parameter.
*
* @see Account#getTransportUri()
* @see SmtpTransport#decodeUri(String)
*/
public static String createUri(ServerSettings server) {
String userEnc;
String passwordEnc;
try {
userEnc = URLEncoder.encode(server.username, "UTF-8");
passwordEnc = URLEncoder.encode(server.password, "UTF-8");
}
catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("Could not encode username or password", e);
}
String scheme;
switch (server.connectionSecurity) {
case SSL_TLS_OPTIONAL:
scheme = "smtp+ssl";
break;
case SSL_TLS_REQUIRED:
scheme = "smtp+ssl+";
break;
case STARTTLS_OPTIONAL:
scheme = "smtp+tls";
break;
case STARTTLS_REQUIRED:
scheme = "smtp+tls+";
break;
default:
case NONE:
scheme = "smtp";
break;
}
String userInfo = userEnc + ":" + passwordEnc + ":" + server.authenticationType;
try {
return new URI(scheme, userInfo, server.host, server.port, null, null,
null).toString();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Can't create SmtpTransport URI", e);
}
}
String mHost;
int mPort;

View File

@ -12,18 +12,30 @@ import com.fsck.k9.mail.Transport;
import com.fsck.k9.mail.store.WebDavStore;
public class WebDavTransport extends Transport {
private static final String TRANSPORT_TYPE = "WebDAV";
public static final String TRANSPORT_TYPE = WebDavStore.STORE_TYPE;
/**
* Decodes a WebDavTransport URI.
*
* <p>
* <b>Note:</b> Right now there is nothing to decode. Everything related to sending messages
* via WebDAV is handled by {@link WebDavStore}.
* <b>Note:</b> Everything related to sending messages via WebDAV is handled by
* {@link WebDavStore}. So the transport URI is the same as the store URI.
* </p>
*/
public static ServerSettings decodeUri(String uri) {
return new ServerSettings(TRANSPORT_TYPE);
return WebDavStore.decodeUri(uri);
}
/**
* Creates a WebDavTransport URI.
*
* <p>
* <b>Note:</b> Everything related to sending messages via WebDAV is handled by
* {@link WebDavStore}. So the transport URI is the same as the store URI.
* </p>
*/
public static String createUri(ServerSettings server) {
return WebDavStore.createUri(server);
}

View File

@ -23,11 +23,13 @@ public class AccountSettings {
SETTINGS = new LinkedHashMap<String, SettingsDescription>();
// mandatory
/*
SETTINGS.put("storeUri",
SD(SettingType.STRING, Settings.EXCEPTION_DEFAULT_VALUE, new StoreUriValidator()));
SETTINGS.put("transportUri",
SD(SettingType.STRING, Settings.EXCEPTION_DEFAULT_VALUE,
new TransportUriValidator()));
*/
SETTINGS.put("archiveFolderName",
SD(SettingType.STRING, "Archive", null));

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -23,6 +24,10 @@ import com.fsck.k9.K9;
import com.fsck.k9.Preferences;
import com.fsck.k9.helper.DateFormatter;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.ConnectionSecurity;
import com.fsck.k9.mail.ServerSettings;
import com.fsck.k9.mail.Store;
import com.fsck.k9.mail.Transport;
public class StorageImporter {
@ -204,6 +209,7 @@ public class StorageImporter {
errorneousAccounts.add(importResult.original);
}
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Exception while importing account", e); //XXX
errorneousAccounts.add(new AccountDescription(account.name, account.uuid));
}
} else {
@ -302,6 +308,7 @@ public class StorageImporter {
//TODO: validate account name
//TODO: validate server settings
//TODO: validate identity settings
//TODO: validate folder settings
@ -321,6 +328,16 @@ public class StorageImporter {
String accountKeyPrefix = uuid + ".";
editor.putString(accountKeyPrefix + Account.ACCOUNT_DESCRIPTION_KEY, accountName);
// Write incoming server settings (storeUri)
ServerSettings incoming = new ImportedServerSettings(account.incoming);
String storeUri = Store.createStoreUri(incoming);
editor.putString(accountKeyPrefix + Account.STORE_URI_KEY, Utility.base64Encode(storeUri));
// Write outgoing server settings (transportUri)
ServerSettings outgoing = new ImportedServerSettings(account.outgoing);
String transportUri = Transport.createTransportUri(outgoing);
editor.putString(accountKeyPrefix + Account.TRANSPORT_URI_KEY, Utility.base64Encode(transportUri));
// Write account settings
for (Map.Entry<String, String> setting : writeSettings.entrySet()) {
String key = accountKeyPrefix + setting.getKey();
@ -639,6 +656,18 @@ public class StorageImporter {
String element = xpp.getName();
if (StorageExporter.NAME_ELEMENT.equals(element)) {
account.name = getText(xpp);
} else if (StorageExporter.INCOMING_SERVER_ELEMENT.equals(element)) {
if (overview) {
skipToEndTag(xpp, StorageExporter.INCOMING_SERVER_ELEMENT);
} else {
account.incoming = parseServerSettings(xpp, StorageExporter.INCOMING_SERVER_ELEMENT);
}
} else if (StorageExporter.OUTGOING_SERVER_ELEMENT.equals(element)) {
if (overview) {
skipToEndTag(xpp, StorageExporter.OUTGOING_SERVER_ELEMENT);
} else {
account.outgoing = parseServerSettings(xpp, StorageExporter.OUTGOING_SERVER_ELEMENT);
}
} else if (StorageExporter.SETTINGS_ELEMENT.equals(element)) {
if (overview) {
skipToEndTag(xpp, StorageExporter.SETTINGS_ELEMENT);
@ -671,6 +700,40 @@ public class StorageImporter {
return account;
}
private static ImportedServer parseServerSettings(XmlPullParser xpp, String endTag)
throws XmlPullParserException, IOException {
ImportedServer server = new ImportedServer();
server.type = xpp.getAttributeValue(null, StorageExporter.TYPE_ATTRIBUTE);
int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && endTag.equals(xpp.getName()))) {
if(eventType == XmlPullParser.START_TAG) {
String element = xpp.getName();
if (StorageExporter.HOST_ELEMENT.equals(element)) {
server.host = getText(xpp);
} else if (StorageExporter.PORT_ELEMENT.equals(element)) {
server.port = getText(xpp);
} else if (StorageExporter.CONNECTION_SECURITY_ELEMENT.equals(element)) {
server.connectionSecurity = getText(xpp);
} else if (StorageExporter.AUTHENTICATION_TYPE_ELEMENT.equals(element)) {
server.authenticationType = getText(xpp);
} else if (StorageExporter.USERNAME_ELEMENT.equals(element)) {
server.username = getText(xpp);
} else if (StorageExporter.PASSWORD_ELEMENT.equals(element)) {
server.password = getText(xpp);
} else if (StorageExporter.EXTRA_ELEMENT.equals(element)) {
server.extras = parseSettings(xpp, StorageExporter.EXTRA_ELEMENT);
} else {
Log.w(K9.LOG_TAG, "Unexpected start tag: " + xpp.getName());
}
}
eventType = xpp.next();
}
return server;
}
private static List<ImportedIdentity> parseIdentities(XmlPullParser xpp)
throws XmlPullParserException, IOException {
List<ImportedIdentity> identities = null;
@ -765,6 +828,39 @@ public class StorageImporter {
return folder;
}
private static class ImportedServerSettings extends ServerSettings {
private final ImportedServer mImportedServer;
public ImportedServerSettings(ImportedServer server) {
super(server.type, server.host, convertPort(server.port),
convertConnectionSecurity(server.connectionSecurity),
server.authenticationType, server.username, server.password);
mImportedServer = server;
}
@Override
public Map<String, String> getExtra() {
return (mImportedServer.extras != null) ?
Collections.unmodifiableMap(mImportedServer.extras.settings) : null;
}
private static int convertPort(String port) {
try {
return Integer.parseInt(port);
} catch (NumberFormatException e) {
return -1;
}
}
private static ConnectionSecurity convertConnectionSecurity(String connectionSecurity) {
try {
return ConnectionSecurity.valueOf(connectionSecurity);
} catch (Exception e) {
return ConnectionSecurity.NONE;
}
}
}
private static class Imported {
public ImportedSettings globalSettings;
public Map<String, ImportedAccount> accounts;
@ -777,11 +873,24 @@ public class StorageImporter {
private static class ImportedAccount {
public String uuid;
public String name;
public ImportedServer incoming;
public ImportedServer outgoing;
public ImportedSettings settings;
public List<ImportedIdentity> identities;
public List<ImportedFolder> folders;
}
private static class ImportedServer {
public String type;
public String host;
public String port;
public String connectionSecurity;
public String authenticationType;
public String username;
public String password;
public ImportedSettings extras;
}
private static class ImportedIdentity {
public String name;
public String email;