/*
* Universal Password Manager
* Copyright (c) 2010-2011 Adrian Smith
*
* This file is part of Universal Password Manager.
*
* Universal Password Manager is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Universal Password Manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Universal Password Manager; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.u17od.upm;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.u17od.upm.database.PasswordDatabase;
import com.u17od.upm.transport.HTTPTransport;
import com.u17od.upm.transport.TransportException;
public class DownloadRemoteDatabase extends Activity implements OnClickListener {
private static final int ENTER_PW_REQUEST_CODE = 111;
private EditText urlEditText;
private EditText userid;
private EditText password;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download_remote_db);
urlEditText = (EditText) findViewById(R.id.remote_db_url);
userid = (EditText) findViewById(R.id.remote_url_userid);
password = (EditText) findViewById(R.id.remote_url_password);
Button downloadButton = (Button) findViewById(R.id.download_button);
downloadButton.setOnClickListener(this);
Button cancelButton = (Button) findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
public void onClick(View v) {
new DownloadDatabase().execute();
}
/**
* The only way this method can be called is if we're returning from EnterMasterPassword
* because we downloaded a remote db and the current master password didn't work.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode == Activity.RESULT_CANCELED) {
UIUtilities.showToast(this, R.string.enter_password_cancalled);
} else {
if (requestCode == ENTER_PW_REQUEST_CODE) {
// Setting the DatabaseFileName preference effectively says
// that this is the db to open when the app starts
Utilities.setDatabaseFileName(getDatabaseFileNameFromURL(), DownloadRemoteDatabase.this);
// Put a reference to the decrypted database on the Application object
UPMApplication app = (UPMApplication) getApplication();
app.setPasswordDatabase(EnterMasterPassword.decryptedPasswordDatabase);
app.setTimeOfLastSync(new Date());
setResult(RESULT_OK);
finish();
}
}
}
private String getDatabaseFileNameFromURL() {
// We need to store the database file name so that we know
// the name of the db to open when starting up
String url = urlEditText.getText().toString();
int slashIndex = url.lastIndexOf('/');
String fileName = url.substring(slashIndex + 1);
return fileName;
}
private class DownloadDatabase extends AsyncTask<Void, Void, Integer> {
private static final int PROBLEM_DOWNLOADING_DB = 1;
private static final int PROBLEM_SAVING_DB = 2;
private static final int NOT_UPM_DB = 3;
private String errorMessage;
private ProgressDialog progressDialog;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(DownloadRemoteDatabase.this, "", getString(R.string.downloading_db));
}
/**
* Download the remote database file.
* Check that it's a proper UPM database file.
* Copy the downloaded file to the application database location.
*/
@Override
protected Integer doInBackground(Void... params) {
int errorCode = 0;
SharedPreferences settings = getSharedPreferences(Prefs.PREFS_NAME, 0);
String trustedHostname = settings.getString(Prefs.PREF_TRUSTED_HOSTNAME, "");
HTTPTransport transport = new HTTPTransport(getFileStreamPath(
FullAccountList.CERT_FILE_NAME), trustedHostname,
getApplicationContext().getFilesDir());
try {
byte[] passwordDBBytes = transport.get(
urlEditText.getText().toString(),
userid.getText().toString(),
password.getText().toString());
if (PasswordDatabase.isPasswordDatabase(passwordDBBytes)) {
// Copy the downloaded bytes to the app's files dir.
// We retain the file name so that we know what file to delete
// on the server when doing a sync.
File destFile = new File(getFilesDir(), getDatabaseFileNameFromURL());
BufferedOutputStream buf = new BufferedOutputStream(
new FileOutputStream(destFile));
buf.write(passwordDBBytes);
buf.close();
EnterMasterPassword.databaseFileToDecrypt = destFile;
} else {
errorCode = NOT_UPM_DB;
}
} catch (TransportException e) {
Log.e("DownloadRemoteDatabase", "Problem downloading database", e);
errorMessage = e.getMessage();
errorCode = PROBLEM_DOWNLOADING_DB;
} catch (IOException e) {
Log.e("DownloadRemoteDatabase", "Problem writing to database file", e);
errorMessage = e.getMessage();
errorCode = PROBLEM_SAVING_DB;
}
return errorCode;
}
/*
* If there was an error downloading the database then display it.
* Otherwise launch the EnterMasterPassword activity.
*/
protected void onPostExecute(Integer result) {
progressDialog.dismiss();
Intent i = null;
switch (result) {
case 0:
// Call up the EnterMasterPassword activity
// When it returns we'll pick up in the method onActivityResult
i = new Intent(DownloadRemoteDatabase.this, EnterMasterPassword.class);
startActivityForResult(i, ENTER_PW_REQUEST_CODE);
break;
case NOT_UPM_DB:
UIUtilities.showToast(DownloadRemoteDatabase.this, R.string.not_password_database, true);
break;
case PROBLEM_DOWNLOADING_DB:
UIUtilities.showToast(DownloadRemoteDatabase.this,
String.format(getString(R.string.problem_downloading_db), errorMessage),
true);
break;
case PROBLEM_SAVING_DB:
UIUtilities.showToast(DownloadRemoteDatabase.this,
String.format(getString(R.string.problem_saving_db), errorMessage),
true);
break;
}
}
}
}