Merge branch 'master' of github.com:zeapo/Android-Password-Store

This commit is contained in:
kLeZ 2014-09-23 09:21:24 +02:00
commit cac3e8e71c
8 changed files with 112 additions and 151 deletions

22
.travis.yml Normal file
View file

@ -0,0 +1,22 @@
language: android
android:
components:
# Uncomment the lines below if you want to
# use the latest revision of Android SDK Tools
# - platform-tools
# - tools
# The BuildTools version used by your project
- build-tools-19.1.0
# The SDK version used to compile your project
- android-19
# Additional components
- extra-google-m2repository
- extra-android-m2repository
# Specify at least one system image,
# if you need to run emulator(s) during your tests
- sys-img-armeabi-v7a-android-19
- sys-img-x86-android-17

Binary file not shown.

View file

@ -9,8 +9,8 @@ android {
applicationId "com.zeapo.pwdstore" applicationId "com.zeapo.pwdstore"
minSdkVersion 15 minSdkVersion 15
targetSdkVersion 19 targetSdkVersion 19
versionCode 11 versionCode 13
versionName "1.1-b5" versionName "1.1-b6"
} }
buildTypes { buildTypes {
release { release {
@ -18,6 +18,11 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
// avoid Travis failures
lintOptions {
abortOnError false
}
} }
repositories { repositories {
maven { url 'http://clinker.47deg.com/nexus/content/groups/public' } maven { url 'http://clinker.47deg.com/nexus/content/groups/public' }

View file

@ -1,10 +1,15 @@
package com.zeapo.pwdstore; package com.zeapo.pwdstore;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.util.Log; import android.util.Log;
import com.zeapo.pwdstore.utils.PasswordRepository;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.GitCommand;
@ -13,16 +18,18 @@ import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.api.errors.TransportException;
public class GitAsyncTask extends AsyncTask<GitCommand, Integer, Integer> { public class GitAsyncTask extends AsyncTask<GitCommand, Integer, String> {
private Activity activity; private Activity activity;
private boolean finishOnEnd; private boolean finishOnEnd;
private boolean refreshListOnEnd; private boolean refreshListOnEnd;
private ProgressDialog dialog; private ProgressDialog dialog;
private Class operation;
public GitAsyncTask(Activity activity, boolean finishOnEnd, boolean refreshListOnEnd) { public GitAsyncTask(Activity activity, boolean finishOnEnd, boolean refreshListOnEnd, Class operation) {
this.activity = activity; this.activity = activity;
this.finishOnEnd = finishOnEnd; this.finishOnEnd = finishOnEnd;
this.refreshListOnEnd = refreshListOnEnd; this.refreshListOnEnd = refreshListOnEnd;
this.operation = operation;
dialog = new ProgressDialog(this.activity); dialog = new ProgressDialog(this.activity);
} }
@ -34,43 +41,55 @@ public class GitAsyncTask extends AsyncTask<GitCommand, Integer, Integer> {
} }
@Override @Override
protected Integer doInBackground(GitCommand... cmd) { protected String doInBackground(GitCommand... cmd) {
int count = cmd.length; int count = cmd.length;
Integer totalSize = 0;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
try { try {
cmd[i].call(); cmd[i].call();
} catch (JGitInternalException e) {
e.printStackTrace();
return -99;
} catch (InvalidRemoteException e) {
e.printStackTrace();
return -1;
} catch (TransportException e) {
e.printStackTrace();
return -2;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return -98; return e.getMessage();
} }
totalSize++;
} }
return totalSize; return "";
} }
protected void onPostExecute(Integer result) { protected void onPostExecute(String result) {
Log.i("GIT_ASYNC", result + "");
this.dialog.dismiss(); this.dialog.dismiss();
if (finishOnEnd) {
this.activity.setResult(Activity.RESULT_OK);
this.activity.finish();
}
if (refreshListOnEnd) { if (!result.isEmpty()) {
try { new AlertDialog.Builder(activity).
((PasswordStore) this.activity).refreshListAdapter(); setTitle("Internal exception occurred").
} catch (ClassCastException e){ setMessage("Message from jgit:\n" + result).
// oups, mistake setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (operation.equals(CloneCommand.class)) {
// if we were unable to finish the job
try {
FileUtils.deleteDirectory(PasswordRepository.getWorkTree());
} catch (Exception e) {
e.printStackTrace();
}
} else {
activity.setResult(Activity.RESULT_CANCELED);
activity.finish();
}
}
}).show();
} else {
if (finishOnEnd) {
this.activity.setResult(Activity.RESULT_OK);
this.activity.finish();
}
if (refreshListOnEnd) {
try {
((PasswordStore) this.activity).refreshListAdapter();
} catch (ClassCastException e) {
// oups, mistake
}
} }
} }
} }

View file

@ -2,12 +2,10 @@ package com.zeapo.pwdstore;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.InputType; import android.text.InputType;
@ -32,9 +30,8 @@ import org.eclipse.jgit.api.Git;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.UnsupportedCredentialItem; import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.transport.CredentialItem; import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.CredentialsProvider;
@ -200,99 +197,6 @@ public class GitHandler extends Activity {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
/* The clone process has to be on a different thread than the main one */
private class CloneTask extends AsyncTask<CloneCommand, Integer, Integer> {
private ProgressDialog dialog;
public CloneTask(Activity activity) {
context = activity;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
this.dialog.setMessage("Cloning...");
this.dialog.setCancelable(false);
// TODO: Handle a dialog leak when there is no error
this.dialog.show();
}
protected void onPostExecute(Integer result) {
switch (result) {
case -1:
new AlertDialog.Builder(activity).
setTitle("Please check that the repository path is correct.").
setMessage("Did you forget to specify the path after the hostname?").
setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}).show();
break;
case -2:
new AlertDialog.Builder(activity).
setTitle("Communication error").
setMessage("JGit said that the server didn't like our request. Either an authentication issue or the host is not reachable. Check the debug messages.").
setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}).show();
break;
case -99:
new AlertDialog.Builder(activity).
setTitle("JGit raised an internal exception").
setMessage("OUPS, JGit didn't like what you did... Check that you provided it with a correct URI. Check also debug messages.").
setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}).show();
break;
default:
this.dialog.dismiss();
setResult(RESULT_OK);
finish();
return;
}
this.dialog.dismiss();
// if we were unable to finish the job
try {
FileUtils.deleteDirectory(localDir);
} catch (Exception e) {
e.printStackTrace();
}
}
protected Integer doInBackground(CloneCommand... cmd) {
int count = cmd.length;
Integer totalSize = 0;
for (int i = 0; i < count; i++) {
try {
cmd[i].call();
} catch (JGitInternalException e) {
e.printStackTrace();
return -99;
} catch (InvalidRemoteException e) {
e.printStackTrace();
return -1;
} catch (TransportException e) {
e.printStackTrace();
return -2;
} catch (Exception e) {
e.printStackTrace();
return -99;
}
totalSize++;
}
return totalSize;
}
}
protected class GitConfigSessionFactory extends JschConfigSessionFactory { protected class GitConfigSessionFactory extends JschConfigSessionFactory {
protected void configure(OpenSshConfig.Host hc, Session session) { protected void configure(OpenSshConfig.Host hc, Session session) {
@ -452,7 +356,7 @@ public class GitHandler extends Activity {
setDirectory(localDir). setDirectory(localDir).
setURI(hostname); setURI(hostname);
new CloneTask(activity).execute(cmd); new GitAsyncTask(activity, true, false, CloneCommand.class).execute(cmd);
} }
public void pullOperation(UsernamePasswordCredentialsProvider provider) { public void pullOperation(UsernamePasswordCredentialsProvider provider) {
@ -500,7 +404,7 @@ public class GitHandler extends Activity {
.setRebase(true) .setRebase(true)
.setRemote("origin"); .setRemote("origin");
new GitAsyncTask(activity, true, false).execute(cmd); new GitAsyncTask(activity, true, false, PullCommand.class).execute(cmd);
} }
} }
@ -550,7 +454,7 @@ public class GitHandler extends Activity {
.setRemote("origin"); .setRemote("origin");
new GitAsyncTask(activity, true, false).execute(cmd); new GitAsyncTask(activity, true, false, PushCommand.class).execute(cmd);
} }
} }
@ -661,14 +565,7 @@ public class GitHandler extends Activity {
} }
}).show(); }).show();
} else { } else {
CloneCommand cmd = Git.cloneRepository() // BUG: we do not support HTTP yet...
.setDirectory(localDir)
.setURI(hostname)
.setBare(false)
.setNoCheckout(false)
.setCloneAllBranches(true);
new CloneTask(activity).execute(cmd);
} }
} }
} }

View file

@ -28,6 +28,7 @@ import com.zeapo.pwdstore.utils.PasswordItem;
import com.zeapo.pwdstore.utils.PasswordRepository; import com.zeapo.pwdstore.utils.PasswordRepository;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.JschConfigSessionFactory; import org.eclipse.jgit.transport.JschConfigSessionFactory;
@ -214,6 +215,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
} }
private void checkLocalRepository(File localDir) { private void checkLocalRepository(File localDir) {
Log.d("PASS", localDir.getAbsolutePath());
FragmentManager fragmentManager = getFragmentManager(); FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
@ -323,7 +325,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
setResult(RESULT_CANCELED); setResult(RESULT_CANCELED);
Git git = new Git(PasswordRepository.getRepository(new File(""))); Git git = new Git(PasswordRepository.getRepository(new File("")));
GitAsyncTask tasks = new GitAsyncTask(activity, false, true); GitAsyncTask tasks = new GitAsyncTask(activity, false, true, CommitCommand.class);
System.out.println(tasks); System.out.println(tasks);
tasks.execute( tasks.execute(
git.rm().addFilepattern(path.replace(PasswordRepository.getWorkTree() + "/", "")), git.rm().addFilepattern(path.replace(PasswordRepository.getWorkTree() + "/", "")),
@ -366,7 +368,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
switch (requestCode) { switch (requestCode) {
case PgpHandler.REQUEST_CODE_ENCRYPT : case PgpHandler.REQUEST_CODE_ENCRYPT :
Git git = new Git(PasswordRepository.getRepository(new File(""))); Git git = new Git(PasswordRepository.getRepository(new File("")));
GitAsyncTask tasks = new GitAsyncTask(this, false, false); GitAsyncTask tasks = new GitAsyncTask(this, false, false, CommitCommand.class);
tasks.execute( tasks.execute(
git.add().addFilepattern("."), git.add().addFilepattern("."),
git.commit().setMessage("[ANDROID PwdStore] Add " + data.getExtras().getString("NAME") + " from store.") git.commit().setMessage("[ANDROID PwdStore] Add " + data.getExtras().getString("NAME") + " from store.")

View file

@ -63,6 +63,7 @@ public class PgpHandler extends Activity implements OpenPgpServiceConnection.OnB
private ProgressDialog bindingDialog; private ProgressDialog bindingDialog;
private boolean registered;
public static final int REQUEST_CODE_SIGN = 9910; public static final int REQUEST_CODE_SIGN = 9910;
public static final int REQUEST_CODE_ENCRYPT = 9911; public static final int REQUEST_CODE_ENCRYPT = 9911;
@ -90,6 +91,8 @@ public class PgpHandler extends Activity implements OpenPgpServiceConnection.OnB
accountName = settings.getString("openpgp_account_name", ""); accountName = settings.getString("openpgp_account_name", "");
keyIDs = settings.getString("openpgp_key_ids", ""); keyIDs = settings.getString("openpgp_key_ids", "");
registered = false;
if (TextUtils.isEmpty(providerPackageName)) { if (TextUtils.isEmpty(providerPackageName)) {
Toast.makeText(this, "No OpenPGP Provider selected!", Toast.LENGTH_LONG).show(); Toast.makeText(this, "No OpenPGP Provider selected!", Toast.LENGTH_LONG).show();
Intent intent = new Intent(this, UserPreference.class); Intent intent = new Intent(this, UserPreference.class);
@ -110,6 +113,8 @@ public class PgpHandler extends Activity implements OpenPgpServiceConnection.OnB
bindingDialog.setCancelable(false); bindingDialog.setCancelable(false);
bindingDialog.show(); bindingDialog.show();
registered = true;
ActionBar actionBar = getActionBar(); ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true);
} }
@ -118,8 +123,12 @@ public class PgpHandler extends Activity implements OpenPgpServiceConnection.OnB
@Override @Override
public void onStop(){ public void onStop(){
super.onStop(); super.onStop();
if (this.mServiceConnection.isBound()) if (this.registered && this.mServiceConnection.isBound())
this.mServiceConnection.unbindFromService(); try {
this.mServiceConnection.unbindFromService();
} catch (Exception e){
}
} }
@Override @Override

View file

@ -1,6 +1,9 @@
package com.zeapo.pwdstore.utils; package com.zeapo.pwdstore.utils;
import android.util.Log;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
@ -10,7 +13,10 @@ import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.transport.URIish;
import java.io.File; import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -115,7 +121,10 @@ public class PasswordRepository {
public static ArrayList<File> getFilesList(File path){ public static ArrayList<File> getFilesList(File path){
if (!path.exists()) return new ArrayList<File>(); if (!path.exists()) return new ArrayList<File>();
List<File> files = (List<File>) FileUtils.listFiles(path, new String[] {"gpg"}, true); Log.d("REPO", path.getAbsolutePath());
ArrayList<File> files = new ArrayList<File>(Arrays.asList(path.listFiles((FileFilter) FileFilterUtils.directoryFileFilter())));
files.addAll( new ArrayList<File>((List<File>)FileUtils.listFiles(path, new String[] {"gpg"}, false)));
return new ArrayList<File>(files); return new ArrayList<File>(files);
} }
@ -129,15 +138,13 @@ public class PasswordRepository {
ArrayList<PasswordItem> passwordList = new ArrayList<PasswordItem>(); ArrayList<PasswordItem> passwordList = new ArrayList<PasswordItem>();
for (File file : passList) { for (File file : passList) {
String fileName = file.getAbsolutePath().replace(path.getAbsolutePath() + "/", ""); if (file.isFile()) {
passwordList.add(PasswordItem.newPassword(file.getName(), file));
String[] parts = fileName.split("/");
if (parts.length == 1) {
passwordList.add(PasswordItem.newPassword(parts[0], file));
} else { } else {
if (!passwordList.contains(PasswordItem.newCategory(parts[0], file.getParentFile()))) { // ignore .git directory
passwordList.add(PasswordItem.newCategory(parts[0], file.getParentFile())); if (file.getName().equals(".git"))
} continue;
passwordList.add(PasswordItem.newCategory(file.getName(), file));
} }
} }
sort(passwordList); sort(passwordList);