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

Revert "Revert "Improved autoconfiguration screen. User can follow progress better, has an indicator the phone is busy. Added buttons to cancel or continue.""

This reverts commit 555318de515f962a742281b025821b96f6ad463a.
This commit is contained in:
dzan 2011-07-16 14:51:29 +02:00 committed by Andrew Chen
parent 70e25c93e8
commit 9df96d07c5
4 changed files with 151 additions and 110 deletions

View File

@ -12,14 +12,40 @@
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:paddingBottom="6dip"/> android:paddingBottom="6dip"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<TextView android:id="@+id/autoconfig_warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Warning blaat blaat" />
<ProgressBar android:id="@+id/autoconfig_progress" <ProgressBar android:id="@+id/autoconfig_progress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/status_message" android:layout_below="@id/status_message"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginTop="30dp" android:layout_marginBottom="60dp"
style="@android:style/Widget.ProgressBar.Large" /> style="@android:style/Widget.ProgressBar.Large" />
<!-- TODO: add a cancel button <Button android:id="@+id/autoconfig_button_cancel"
<include layout="@layout/wizard_cancel"/> --> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/autoconfig_progress"
android:text="@string/cancel_action"/>
<Button android:id="@+id/autoconfig_button_next"
android:drawableRight="@drawable/button_indicator_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/autoconfig_progress"
android:layout_toRightOf="@id/autoconfig_button_cancel"
android:text="@string/next_action"/>
</RelativeLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -379,6 +379,8 @@ http://k9mail.googlecode.com/
<string name="account_setup_autoconfig_missing">not found!</string> <string name="account_setup_autoconfig_missing">not found!</string>
<string name="account_setup_autoconfig_succesful">successful!</string> <string name="account_setup_autoconfig_succesful">successful!</string>
<string name="account_setup_autoconfig_fail">failed!</string> <string name="account_setup_autoconfig_fail">failed!</string>
<string name="account_setup_autoconfig_forcemanual">No settings found, use manual configuration.</string>
<string name="account_setup_autoconfig_trynext">Searching other places for configuration settings...</string>
<string name="account_setup_names_title">You\'re almost done!</string> <string name="account_setup_names_title">You\'re almost done!</string>
<string name="account_setup_names_instructions">Your account is set up, and mail is on its way!</string> <string name="account_setup_names_instructions">Your account is set up, and mail is on its way!</string>

View File

@ -8,6 +8,7 @@ import android.os.*;
import android.os.Process; import android.os.Process;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.fsck.k9.K9; import com.fsck.k9.K9;
@ -15,6 +16,7 @@ import com.fsck.k9.R;
import com.fsck.k9.activity.K9Activity; import com.fsck.k9.activity.K9Activity;
import com.fsck.k9.helper.configxmlparser.ConfigurationXMLHandler; import com.fsck.k9.helper.configxmlparser.ConfigurationXMLHandler;
import com.fsck.k9.mail.store.TrustManagerFactory; import com.fsck.k9.mail.store.TrustManagerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.XMLReader; import org.xml.sax.XMLReader;
@ -27,6 +29,7 @@ import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.TimeoutException;
/** /**
* User: dzan * User: dzan
@ -35,14 +38,11 @@ import java.util.Arrays;
public class AccountSetupAutoConfiguration extends K9Activity implements View.OnClickListener { public class AccountSetupAutoConfiguration extends K9Activity implements View.OnClickListener {
// constants for the intent/activity system
// TODO: read about intents and make this one result right
public static final int ACTIVITY_REQUEST_CODE = 1;
private static final String EMAIL_ADDRESS = "account"; private static final String EMAIL_ADDRESS = "account";
private static final String PASSWORD = "password"; private static final String PASSWORD = "password";
// timeout for testing services availability ( in ms ) // timeout for testing services availability ( in ms )
private static final int TIMEOUT = 20000; private static final int TIMEOUT = 5000;
// location of mozilla's ispdb // location of mozilla's ispdb
private String databaseBaseUrl = "https://live.mozillamessaging.com/autoconfig/v1.1/"; private String databaseBaseUrl = "https://live.mozillamessaging.com/autoconfig/v1.1/";
@ -78,10 +78,17 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
private TextView mMessageView; private TextView mMessageView;
private ProgressBar mProgressCircle; private ProgressBar mProgressCircle;
private Button mCancelButton;
private Button mNextButton;
private TextView mWarningMsg;
private String mEmailAddress; private String mEmailAddress;
private String mPassword; private String mPassword;
private String mLastMessage; private String mLastMessage;
private boolean bForceManual = false;
private boolean bDoneSearching = false;
private boolean bFound = false;
private boolean bParseFailed = false;
/* /*
Start the auto-configuration activity Start the auto-configuration activity
@ -90,7 +97,7 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
Intent i = new Intent(context, AccountSetupAutoConfiguration.class); Intent i = new Intent(context, AccountSetupAutoConfiguration.class);
i.putExtra(EMAIL_ADDRESS, email); i.putExtra(EMAIL_ADDRESS, email);
i.putExtra(PASSWORD, password); i.putExtra(PASSWORD, password);
context.startActivityForResult(i, ACTIVITY_REQUEST_CODE); context.startActivity(i);
} }
/* /*
@ -103,10 +110,17 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
// Setting up the view // Setting up the view
setContentView(R.layout.account_setup_autoconfig); setContentView(R.layout.account_setup_autoconfig);
mMessageView = (TextView)findViewById(R.id.status_message); mMessageView = (TextView)findViewById(R.id.status_message);
mWarningMsg = (TextView)findViewById(R.id.autoconfig_warning);
mWarningMsg.setVisibility(View.GONE);
mProgressCircle = (ProgressBar)findViewById(R.id.autoconfig_progress); mProgressCircle = (ProgressBar)findViewById(R.id.autoconfig_progress);
mProgressCircle.setIndeterminate(true); mProgressCircle.setIndeterminate(true);
mProgressCircle.setVisibility(View.VISIBLE); mProgressCircle.setVisibility(View.VISIBLE);
// ((Button)findViewById(R.id.cancel)).setOnClickListener(this);
mCancelButton = (Button)findViewById(R.id.autoconfig_button_cancel);
mCancelButton.setOnClickListener(this);
mNextButton = (Button)findViewById(R.id.autoconfig_button_next);
mNextButton.setOnClickListener(this);
mNextButton.setEnabled(false);
// Getting our data to work with // Getting our data to work with
mEmailAddress = getIntent().getStringExtra(EMAIL_ADDRESS); mEmailAddress = getIntent().getStringExtra(EMAIL_ADDRESS);
@ -134,11 +148,16 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
Check if configuration data exists and if it does read in Check if configuration data exists and if it does read in
*/ */
int i = 0; int i = 0;
while( i < urlTemplates.size() ){ while( i < urlTemplates.size() && !bFound ){
try{ try{
// inform the user // inform the user
setMessage(urlInfoStatements.get(i),true); setMessage(urlInfoStatements.get(i),true);
// to make sure
bParseFailed = false;
bForceManual = false;
bDoneSearching = false;
// preparing the urls // preparing the urls
if( !domain.contains("%user%") ){ // else SHIT if( !domain.contains("%user%") ){ // else SHIT
tmpURL = urlTemplates.get(i).replaceAll("%domain%",domain); tmpURL = urlTemplates.get(i).replaceAll("%domain%",domain);
@ -147,24 +166,26 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
data = getXMLData(new URL(tmpURL)); data = getXMLData(new URL(tmpURL));
// might be the user cancelled by now or the app was destroyed
if (mDestroyed) return;
if (mCanceled) { finish(); return; }
if( !data.isEmpty() ){ if( !data.isEmpty() ){
setMessage(R.string.account_setup_autoconfig_found,false); setMessage(R.string.account_setup_autoconfig_found,false);
// parse and finish // parse and finish
// remember if i >= UNSAFE_URL_START => POSSIBLE UNSAFE DATA, alert user!!! setMessage(R.string.account_setup_autoconfig_processing,true);
parse(data); parse(data);
setMessage(R.string.account_setup_autoconfig_succesful,false);
// Give user some time to read output // alert user these settings might be tampered with!!! ( no https )
try { Thread.sleep(1750); if( i >= UNSAFE_URL_START )
} catch (InterruptedException e) { e.printStackTrace(); } mWarningMsg.setVisibility(View.VISIBLE);
finish(); bFound = true;
return; continue;
} }
// end the output if needed
closeUserInformationIfNeeded(i);
}catch (SocketTimeoutException ex){ }catch (SocketTimeoutException ex){
Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '"+ Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '"+
tmpURL+"' ( time-out is"+TIMEOUT+" )", ex); tmpURL+"' ( time-out is"+TIMEOUT+" )", ex);
@ -174,18 +195,21 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
}catch (UnknownHostException ex){ }catch (UnknownHostException ex){
Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '"+ Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '"+
tmpURL+"'", ex); tmpURL+"'", ex);
} }catch (SSLPeerUnverifiedException ex){
catch (SSLPeerUnverifiedException ex){
Log.e(K9.LOG_TAG, "Error while testing settings", ex); Log.e(K9.LOG_TAG, "Error while testing settings", ex);
acceptKeyDialog( acceptKeyDialog(R.string.account_setup_failed_dlg_certificate_message_fmt,i,ex);
R.string.account_setup_failed_dlg_certificate_message_fmt,i,ex); }catch (SAXException e) {
} setMessage(R.string.account_setup_autoconfig_fail,false);
catch(IOException ex) { bParseFailed = true;
Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '"+ }catch (ParserConfigurationException e) {
tmpURL+"'", ex); setMessage(R.string.account_setup_autoconfig_fail,false);
bParseFailed = true;
}catch (ErrorCodeException ex) { }catch (ErrorCodeException ex) {
Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '" + Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '" +
tmpURL + "' site didn't respond as expected. Got code: " + ex.getErrorCode(), ex); tmpURL + "' site didn't respond as expected. Got code: " + ex.getErrorCode(), ex);
}catch(IOException ex) {
Log.e(K9.LOG_TAG, "Error while attempting auto-configuration with url '"+
tmpURL+"'", ex);
} finally { } finally {
// might be the user cancelled by now or the app was destroyed // might be the user cancelled by now or the app was destroyed
if (mDestroyed) return; if (mDestroyed) return;
@ -193,37 +217,56 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
// check next url // check next url
++i; ++i;
// this was the last option..
if(i == urlTemplates.size() ){
bForceManual = true;
setMessage(R.string.account_setup_autoconfig_forcemanual, true);
}else{
if( bParseFailed )
setMessage(R.string.account_setup_autoconfig_trynext,true);
}
} }
// no server-side config was found // no server-side config was found
closeUserInformationIfNeeded(i-1); closeUserInformationIfNeeded(i-1);
} }
bDoneSearching = true;
runOnUiThread(new Runnable() {
public void run() {
// TODO: set appropriate warning messages in here
// 1. All good, continue
// 2. Nothing came up, must manually config.. + help?
// 3. Data did not came over HTTPS this could be UNSAFE !!!!!!
mProgressCircle.setVisibility(View.INVISIBLE);
mWarningMsg.setVisibility(View.VISIBLE);
mNextButton.setEnabled(true);
if( bForceManual )
mNextButton.setText(getString(R.string.account_setup_basics_manual_setup_action));
}
});
} }
} }
.start(); .start();
} }
/* /*
Start parsing the xml Start parsing the xml
*/ */
private void parse(String data) { private void parse(String data) throws IOException, SAXException, ParserConfigurationException {
try{
XMLReader xr = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); XMLReader xr = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
xr.setContentHandler(new ConfigurationXMLHandler()); xr.setContentHandler(new ConfigurationXMLHandler());
//xr.parse(data); // TODO: see if this has performance consequences, otherwise change all so we pass around InputSource not string
xr.parse(new InputSource(new StringReader(data)));
// TODO: take care of these
} catch (ParserConfigurationException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (SAXException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
} }
/* /*
Checks if an url is available / exists Checks if an url is available / exists
*/ */
private String getXMLData(URL url) throws IOException, ErrorCodeException{ private String getXMLData(URL url) throws IOException, ErrorCodeException, SocketTimeoutException {
// think we should assume no redirects // think we should assume no redirects
// TODO: use k9's own TrustManager so the right exception gets throwed and the user can choose to accept the certificate // TODO: use k9's own TrustManager so the right exception gets throwed and the user can choose to accept the certificate
HttpURLConnection conn = (HttpURLConnection)url.openConnection(); HttpURLConnection conn = (HttpURLConnection)url.openConnection();
@ -234,14 +277,23 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
// get the data // get the data
String tmp, line; String tmp, line;
BufferedReader reader;
tmp = ""; tmp = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
try{
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while( (line = reader.readLine()) != null) while( (line = reader.readLine()) != null)
tmp += line; tmp += line;
if( conn.getResponseCode() != 200 ) if( conn.getResponseCode() != 200 )
throw new ErrorCodeException("Server did not return as expected.",conn.getResponseCode()); throw new ErrorCodeException("Server did not return as expected.",conn.getResponseCode());
conn.disconnect(); }
catch (SocketTimeoutException ex)
{ throw ex; }
finally
{ conn.disconnect(); }
return tmp; return tmp;
} }
@ -251,7 +303,7 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
private void setMessage(int resId, final boolean newLine){ private void setMessage(int resId, final boolean newLine){
setMessage(getString(resId), newLine); setMessage(getString(resId), newLine);
} }
private void setMessage(final String msg, final boolean newline) { private synchronized void setMessage(final String msg, final boolean newline) {
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
public void run() { public void run() {
// don't print if same as last message or when process should be destroyed // don't print if same as last message or when process should be destroyed
@ -270,9 +322,10 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
} }
private void closeUserInformationIfNeeded(int urlNumb) { private void closeUserInformationIfNeeded(int urlNumb) {
int a = urlInfoStatements.get(urlNumb); if( bForceManual ) return;
int b = urlInfoStatements.get(urlNumb+1);
if( urlNumb == urlInfoStatements.size() - 1 || a != b ){ if( urlNumb == urlInfoStatements.size() - 1
|| (int)urlInfoStatements.get(urlNumb) != urlInfoStatements.get(urlNumb+1) ){
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
public void run() { public void run() {
mMessageView.setText(mMessageView.getText().toString()+ mMessageView.setText(mMessageView.getText().toString()+
@ -295,6 +348,10 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
Alert user he canceled and stop the thread Alert user he canceled and stop the thread
*/ */
private void onCancel() { private void onCancel() {
if( bDoneSearching ){
finish();
return;
}
mCanceled = true; mCanceled = true;
setMessage(R.string.account_setup_check_settings_canceling_msg, true); setMessage(R.string.account_setup_check_settings_canceling_msg, true);
} }
@ -318,9 +375,19 @@ public class AccountSetupAutoConfiguration extends K9Activity implements View.On
public void onClick(View v) { public void onClick(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.cancel: case R.id.autoconfig_button_cancel:
onCancel(); onCancel();
break; break;
case R.id.autoconfig_button_next:
// autoconfig failed, proceed by manual setup
if( bForceManual ){
// launch confirm activities
}else{
}
break;
default: return;
} }
} }

View File

@ -1,54 +0,0 @@
// This could be useful later ( if this way of parsing is too slow )
/*
Strings
*/
/*// main structure tags
private final static String CLIENT_CONFIG = "clientConfig"; // root
private final static String CLIENT_CONFIG_UPDATE = "clientConfigUpdate";
private final static String EMAIL_PROVIDER = "emailProvider"; // semi-root, container of whole isp data
private final static String ID = "id";
private final static String INCOMING_SERVER = "incomingServer";
private final static String OUTGOING_SERVER = "outgoingServer";
private final static String TYPE = "type";
// email provider extra information
private final static String DOMAIN = "domain";
private final static String DISPLAY_NAME = "displayName";
private final static String DISPLAY_SHORT_NAME = "displayShortName";
private final static String ENABLE = "enable";
private final static String VISIT_URL = "visiturl"; // attribute of enable
private final static String INSTRUCTION = "instruction"; // child of ^ containing text instructions
//private final static String INSTRUCTION = "instruction"; // could also be tag
private final static String URL = "url"; // attribute of instruction as a tag
private final static String DESCR = "descr"; // child containing urls
private final static String LANG = "lang"; // language of description
private final static String IDENTITY = "identity";
private final static String INPUT_FIELD = "inputField";
private final static String KEY = "key";
private final static String LABEL = "label";
private final static String DOCUMENTATION = "documentation"; // has all kinds of subelements urls & descriptions
// server settings
private final static String HOSTNAME = "hostname";
private final static String PORT = "port";
private final static String SOCKET_TYPE = "socketType";
private final static String USERNAME = "username";
private final static String AUTHENTICATION = "authentication";
// server types ( attributes of outgoing/incoming-Server
private final static String POP3 = "pop3"; // also a tag with extra info
private final static String IMAP = "imap";
private final static String SMTP = "smtp";
// pop3 options
private final static String LEAVE_MESSAGES_ON_SERVER = "leaveMessagesOnServer";
private final static String DOWNLOAD_ON_BIFF = "downloadOnBiff";
private final static String DAYS_TO_LEAVE_MESSAGES_ON_SERVER = "daysToLeaveMessagesOnServer";
private final static String CHECK_INTERVAL = "checkInterval";
private final static String MINUTES = "minutes";
// outgoing server settings
private final static String RESTRICTION = "restriction";
private final static String ADD_THIS_SERVER = "addThisServer";
private final static String USE_GLOBAL_PREFERRED_SERVER = "useGlobalPreferredServer"; */