more refactoring and ability to pull from server
This commit is contained in:
parent
9db42440fb
commit
42f1abfa76
9 changed files with 217 additions and 102 deletions
|
@ -17,7 +17,7 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".GitClone"
|
||||
android:name=".GitHandler"
|
||||
android:label="@string/title_activity_git_clone"
|
||||
android:parentActivityName=".PasswordStore">
|
||||
<meta-data
|
||||
|
|
52
app/src/main/java/com/zeapo/pwdstore/GitAsyncTask.java
Normal file
52
app/src/main/java/com/zeapo/pwdstore/GitAsyncTask.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
package com.zeapo.pwdstore;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.GitCommand;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.api.errors.TransportException;
|
||||
|
||||
|
||||
public class GitAsyncTask extends AsyncTask<GitCommand, Integer, Integer> {
|
||||
private Activity activity;
|
||||
private boolean finishOnEnd;
|
||||
public GitAsyncTask(Activity activity, boolean finishOnEnd) {
|
||||
this.activity = activity;
|
||||
this.finishOnEnd = finishOnEnd;
|
||||
}
|
||||
@Override
|
||||
protected Integer doInBackground(GitCommand... 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();
|
||||
}
|
||||
totalSize++;
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Integer result) {
|
||||
Log.i("GIT_ASYNC", result + "");
|
||||
if (finishOnEnd) {
|
||||
this.activity.finish();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import android.widget.TextView;
|
|||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository;
|
||||
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
|
@ -30,31 +31,18 @@ import org.apache.commons.io.FileUtils;
|
|||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.api.errors.TransportException;
|
||||
import org.eclipse.jgit.errors.NotSupportedException;
|
||||
import org.eclipse.jgit.internal.storage.file.FileRepository;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||
import org.eclipse.jgit.transport.RefSpec;
|
||||
import org.eclipse.jgit.transport.RemoteConfig;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.Transport;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
// TODO move the messages to strings.xml
|
||||
|
||||
public class GitClone extends Activity {
|
||||
public class GitHandler extends Activity {
|
||||
|
||||
private Activity activity;
|
||||
private Context context;
|
||||
|
@ -66,81 +54,95 @@ public class GitClone extends Activity {
|
|||
private String hostname;
|
||||
private String username;
|
||||
|
||||
public static final int REQUEST_PULL = 101;
|
||||
public static final int REQUEST_PUSH = 102;
|
||||
public static final int REQUEST_CLONE = 103;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_git_clone);
|
||||
|
||||
context = getApplicationContext();
|
||||
activity = this;
|
||||
|
||||
// init the spinner for protocols
|
||||
Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol);
|
||||
ArrayAdapter<CharSequence> protocol_adapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.clone_protocols, android.R.layout.simple_spinner_item);
|
||||
protocol_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
protcol_spinner.setAdapter(protocol_adapter);
|
||||
protcol_spinner.setOnItemSelectedListener(
|
||||
new AdapterView.OnItemSelectedListener() {
|
||||
switch (getIntent().getExtras().getInt("Operation")) {
|
||||
case REQUEST_CLONE:
|
||||
setContentView(R.layout.activity_git_clone);
|
||||
|
||||
// init the spinner for protocols
|
||||
Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol);
|
||||
ArrayAdapter<CharSequence> protocol_adapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.clone_protocols, android.R.layout.simple_spinner_item);
|
||||
protocol_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
protcol_spinner.setAdapter(protocol_adapter);
|
||||
protcol_spinner.setOnItemSelectedListener(
|
||||
new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
protocol = ((Spinner)findViewById(R.id.clone_protocol)).getSelectedItem().toString();
|
||||
if (protocol.equals("ssh://")) {
|
||||
((EditText)findViewById(R.id.clone_uri)).setHint("user@hostname:path");
|
||||
} else {
|
||||
((EditText)findViewById(R.id.clone_uri)).setHint("hostname/path");
|
||||
new AlertDialog.Builder(activity).
|
||||
setMessage("You are about to use a read-only repository, you will not be able to push to it").
|
||||
setCancelable(true).
|
||||
setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// init the spinner for connection modes
|
||||
Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode);
|
||||
ArrayAdapter<CharSequence> connection_mode_adapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.connection_modes, android.R.layout.simple_spinner_item);
|
||||
connection_mode_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
connection_mode_spinner.setAdapter(connection_mode_adapter);
|
||||
connection_mode_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
protocol = ((Spinner)findViewById(R.id.clone_protocol)).getSelectedItem().toString();
|
||||
if (protocol.equals("ssh://")) {
|
||||
((EditText)findViewById(R.id.clone_uri)).setHint("user@hostname:path");
|
||||
} else {
|
||||
((EditText)findViewById(R.id.clone_uri)).setHint("hostname/path");
|
||||
new AlertDialog.Builder(activity).
|
||||
setMessage("You are about to use a read-only repository, you will not be able to push to it").
|
||||
setCancelable(true).
|
||||
setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
String selection = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString();
|
||||
|
||||
}
|
||||
}).show();
|
||||
if (selection.equalsIgnoreCase("ssh-key")) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage("Authentication method not implemented yet")
|
||||
.setPositiveButton("OK",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}
|
||||
).show();
|
||||
((Button) findViewById(R.id.clone_button)).setEnabled(false);
|
||||
} else {
|
||||
((Button) findViewById(R.id.clone_button)).setEnabled(true);
|
||||
}
|
||||
connectionMode = selection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
break;
|
||||
case REQUEST_PULL:
|
||||
authenticateThenPull(this);
|
||||
break;
|
||||
}
|
||||
|
||||
// init the spinner for connection modes
|
||||
Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode);
|
||||
ArrayAdapter<CharSequence> connection_mode_adapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.connection_modes, android.R.layout.simple_spinner_item);
|
||||
connection_mode_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
connection_mode_spinner.setAdapter(connection_mode_adapter);
|
||||
connection_mode_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
String selection = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString();
|
||||
|
||||
if (selection.equalsIgnoreCase("ssh-key")) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage("Authentication method not implemented yet")
|
||||
.setPositiveButton("OK",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}
|
||||
).show();
|
||||
((Button) findViewById(R.id.clone_button)).setEnabled(false);
|
||||
} else {
|
||||
((Button) findViewById(R.id.clone_button)).setEnabled(true);
|
||||
}
|
||||
connectionMode = selection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -380,6 +382,36 @@ public class GitClone extends Activity {
|
|||
}
|
||||
}
|
||||
|
||||
private void authenticateThenPull(final Activity activity) {
|
||||
//TODO recall the username
|
||||
//TODO offer the choice ssh and user/pwd
|
||||
final EditText password = new EditText(activity);
|
||||
password.setHint("Password");
|
||||
password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle("Authenticate")
|
||||
.setMessage("Please provide the password for this repository")
|
||||
.setView(password)
|
||||
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
|
||||
SshSessionFactory.setInstance(new GitConfigSessionFactory());
|
||||
|
||||
new GitAsyncTask(activity, true).execute(new Git(PasswordRepository.getRepository(new File("")))
|
||||
.pull()
|
||||
.setRebase(true)
|
||||
.setCredentialsProvider(new UsernamePasswordCredentialsProvider("git", password.getText().toString())));
|
||||
|
||||
|
||||
}
|
||||
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
// Do nothing.
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,26 +1,35 @@
|
|||
package com.zeapo.pwdstore;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.zeapo.pwdstore.crypto.PgpHandler;
|
||||
import com.zeapo.pwdstore.utils.PasswordItem;
|
||||
import com.zeapo.pwdstore.utils.PasswordRepository;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -85,9 +94,19 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
|
|||
createPassword(getCurrentFocus());
|
||||
break;
|
||||
|
||||
case R.id.menu_add_category:
|
||||
// case R.id.menu_add_category:
|
||||
// break;
|
||||
|
||||
case R.id.git_push:
|
||||
break;
|
||||
|
||||
case R.id.git_pull:
|
||||
Intent intent = new Intent(this, GitHandler.class);
|
||||
intent.putExtra("Operation", GitHandler.REQUEST_PULL);
|
||||
startActivity(intent);
|
||||
this.leftActivity = true;
|
||||
return true;
|
||||
|
||||
case R.id.referesh:
|
||||
refreshListAdapter();
|
||||
return true;
|
||||
|
@ -100,7 +119,8 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
|
|||
}
|
||||
|
||||
public void getClone(View view){
|
||||
Intent intent = new Intent(this, GitClone.class);
|
||||
Intent intent = new Intent(this, GitHandler.class);
|
||||
intent.putExtra("Operation", GitHandler.REQUEST_CLONE);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
@ -183,7 +203,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
|
|||
intent.putExtra("NAME", item.toString());
|
||||
intent.putExtra("FILE_PATH", item.getFile().getAbsolutePath());
|
||||
intent.putExtra("Operation", "DECRYPT");
|
||||
startActivityForResult(intent, 0);
|
||||
startActivityForResult(intent, PgpHandler.REQUEST_CODE_DECRYPT_AND_VERIFY);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -207,8 +227,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
|
|||
intent.putExtra("PGP-ID", FileUtils.readFileToString(PasswordRepository.getFile("/.gpg-id")));
|
||||
intent.putExtra("FILE_PATH", this.currentDir.getAbsolutePath());
|
||||
intent.putExtra("Operation", "ENCRYPT");
|
||||
// TODO Define different operations here
|
||||
startActivityForResult(intent, 0);
|
||||
startActivityForResult(intent, PgpHandler.REQUEST_CODE_ENCRYPT);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -231,10 +250,17 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
|
|||
if (resultCode == RESULT_OK) {
|
||||
refreshListAdapter();
|
||||
|
||||
// do not froget to commit the file
|
||||
if (requestCode == PgpHandler.REQUEST_CODE_ENCRYPT) {
|
||||
|
||||
switch (requestCode) {
|
||||
case PgpHandler.REQUEST_CODE_ENCRYPT :
|
||||
Git git = new Git(PasswordRepository.getRepository(new File("")));
|
||||
GitAsyncTask tasks = new GitAsyncTask(this, false);
|
||||
tasks.execute(
|
||||
git.add().addFilepattern(data.getExtras().getString("CREATED_FILE")),
|
||||
git.commit().setMessage("Added " + data.getExtras().getString("NAME"))
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -294,20 +294,15 @@ public class PgpHandler extends Activity {
|
|||
// encrypt
|
||||
if (requestCode == REQUEST_CODE_ENCRYPT && os != null) {
|
||||
try {
|
||||
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length
|
||||
+ " str=" + os.toString("UTF-8"));
|
||||
|
||||
if (returnToCiphertextField) {
|
||||
String path = getIntent().getExtras().getString("FILE_PATH")
|
||||
+ "/" + ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString()
|
||||
+ ".gpg";
|
||||
OutputStream outputStream = FileUtils.openOutputStream(new File(path));
|
||||
outputStream.write(os.toByteArray());
|
||||
} else {
|
||||
showToast(os.toString());
|
||||
}
|
||||
|
||||
setResult(RESULT_OK);
|
||||
String path = getIntent().getExtras().getString("FILE_PATH")
|
||||
+ "/" + ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString()
|
||||
+ ".gpg";
|
||||
OutputStream outputStream = FileUtils.openOutputStream(new File(path));
|
||||
outputStream.write(os.toByteArray());
|
||||
Intent data = new Intent();
|
||||
data.putExtra("CREATED_FILE", path);
|
||||
data.putExtra("NAME", ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString());
|
||||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
Log.e(Constants.TAG, "UnsupportedEncodingException", e);
|
||||
|
@ -406,7 +401,6 @@ public class PgpHandler extends Activity {
|
|||
data.setAction(OpenPgpApi.ACTION_ENCRYPT);
|
||||
data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{accountName});
|
||||
data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
||||
Log.i("BABABOU", settings.getString("openpgpg_key_ids", "") + "");
|
||||
|
||||
String name = ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString();
|
||||
String pass = ((EditText) findViewById(R.id.crypto_password_edit)).getText().toString();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
tools:context="com.zeapo.pwdstore.GitClone">
|
||||
tools:context="com.zeapo.pwdstore.GitHandler">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="com.zeapo.pwdstore.GitClone" >
|
||||
tools:context="com.zeapo.pwdstore.GitHandler" >
|
||||
<item android:id="@+id/action_settings"
|
||||
android:title="@string/action_settings"
|
||||
android:orderInCategory="100"
|
||||
|
|
|
@ -7,8 +7,13 @@
|
|||
<!--<item android:id="@+id/menu_add_category"-->
|
||||
<!--android:title="New category"/>-->
|
||||
|
||||
<item android:id="@+id/git_pull"
|
||||
android:title="Pull from remote"/>
|
||||
<item android:id="@+id/git_push"
|
||||
android:title="Push to remote"/>
|
||||
|
||||
<item android:id="@+id/referesh"
|
||||
android:title="Refresh"
|
||||
android:title="Refresh list"
|
||||
android:showAsAction="ifRoom"
|
||||
android:icon="@android:drawable/ic_popup_sync"/>
|
||||
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory android:title="Git">
|
||||
<EditTextPreference android:title="Server"
|
||||
android:key="git_remote_server"/>
|
||||
<EditTextPreference android:title="Username"
|
||||
android:key="git_remote_username"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="Crypto">
|
||||
<org.openintents.openpgp.util.OpenPgpListPreference
|
||||
|
|
Loading…
Reference in a new issue