more refactoring and ability to pull from server

This commit is contained in:
Zeapo 2014-08-08 18:46:35 +01:00
parent 9db42440fb
commit 42f1abfa76
9 changed files with 217 additions and 102 deletions

View file

@ -17,7 +17,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".GitClone" android:name=".GitHandler"
android:label="@string/title_activity_git_clone" android:label="@string/title_activity_git_clone"
android:parentActivityName=".PasswordStore"> android:parentActivityName=".PasswordStore">
<meta-data <meta-data

View 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();
}
}
}

View file

@ -22,6 +22,7 @@ import android.widget.TextView;
import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException; import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session; import com.jcraft.jsch.Session;
import com.zeapo.pwdstore.utils.PasswordRepository;
import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git; 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.InvalidRemoteException;
import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.TransportException; 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.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig; 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.SshSessionFactory;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import java.io.File; import java.io.File;
import java.io.IOException; 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 // TODO move the messages to strings.xml
public class GitClone extends Activity { public class GitHandler extends Activity {
private Activity activity; private Activity activity;
private Context context; private Context context;
@ -66,81 +54,95 @@ public class GitClone extends Activity {
private String hostname; private String hostname;
private String username; 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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_git_clone);
context = getApplicationContext(); context = getApplicationContext();
activity = this; activity = this;
// init the spinner for protocols switch (getIntent().getExtras().getInt("Operation")) {
Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol); case REQUEST_CLONE:
ArrayAdapter<CharSequence> protocol_adapter = ArrayAdapter.createFromResource(this, setContentView(R.layout.activity_git_clone);
R.array.clone_protocols, android.R.layout.simple_spinner_item);
protocol_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // init the spinner for protocols
protcol_spinner.setAdapter(protocol_adapter); Spinner protcol_spinner = (Spinner) findViewById(R.id.clone_protocol);
protcol_spinner.setOnItemSelectedListener( ArrayAdapter<CharSequence> protocol_adapter = ArrayAdapter.createFromResource(this,
new AdapterView.OnItemSelectedListener() { 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 @Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
protocol = ((Spinner)findViewById(R.id.clone_protocol)).getSelectedItem().toString(); String selection = ((Spinner) findViewById(R.id.connection_mode)).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) {
} if (selection.equalsIgnoreCase("ssh-key")) {
}).show(); 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 @Override
public void onNothingSelected(AdapterView<?> adapterView) { 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 @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();
}
} }

View file

@ -1,26 +1,35 @@
package com.zeapo.pwdstore; package com.zeapo.pwdstore;
import android.app.ActionBar;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentManager; import android.app.FragmentManager;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.content.Context; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.widget.EditText;
import android.widget.PopupWindow; 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.crypto.PgpHandler;
import com.zeapo.pwdstore.utils.PasswordItem; 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.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.File;
import java.io.IOException; import java.io.IOException;
@ -85,9 +94,19 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
createPassword(getCurrentFocus()); createPassword(getCurrentFocus());
break; break;
case R.id.menu_add_category: // case R.id.menu_add_category:
// break;
case R.id.git_push:
break; 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: case R.id.referesh:
refreshListAdapter(); refreshListAdapter();
return true; return true;
@ -100,7 +119,8 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
} }
public void getClone(View view){ 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); startActivity(intent);
} }
@ -183,7 +203,7 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
intent.putExtra("NAME", item.toString()); intent.putExtra("NAME", item.toString());
intent.putExtra("FILE_PATH", item.getFile().getAbsolutePath()); intent.putExtra("FILE_PATH", item.getFile().getAbsolutePath());
intent.putExtra("Operation", "DECRYPT"); intent.putExtra("Operation", "DECRYPT");
startActivityForResult(intent, 0); startActivityForResult(intent, PgpHandler.REQUEST_CODE_DECRYPT_AND_VERIFY);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); 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("PGP-ID", FileUtils.readFileToString(PasswordRepository.getFile("/.gpg-id")));
intent.putExtra("FILE_PATH", this.currentDir.getAbsolutePath()); intent.putExtra("FILE_PATH", this.currentDir.getAbsolutePath());
intent.putExtra("Operation", "ENCRYPT"); intent.putExtra("Operation", "ENCRYPT");
// TODO Define different operations here startActivityForResult(intent, PgpHandler.REQUEST_CODE_ENCRYPT);
startActivityForResult(intent, 0);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -231,10 +250,17 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
refreshListAdapter(); refreshListAdapter();
// do not froget to commit the file switch (requestCode) {
if (requestCode == PgpHandler.REQUEST_CODE_ENCRYPT) { 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;
} }
} }
} }
} }

View file

@ -294,20 +294,15 @@ public class PgpHandler extends Activity {
// encrypt // encrypt
if (requestCode == REQUEST_CODE_ENCRYPT && os != null) { if (requestCode == REQUEST_CODE_ENCRYPT && os != null) {
try { try {
Log.d(OpenPgpApi.TAG, "result: " + os.toByteArray().length String path = getIntent().getExtras().getString("FILE_PATH")
+ " str=" + os.toString("UTF-8")); + "/" + ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString()
+ ".gpg";
if (returnToCiphertextField) { OutputStream outputStream = FileUtils.openOutputStream(new File(path));
String path = getIntent().getExtras().getString("FILE_PATH") outputStream.write(os.toByteArray());
+ "/" + ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString() Intent data = new Intent();
+ ".gpg"; data.putExtra("CREATED_FILE", path);
OutputStream outputStream = FileUtils.openOutputStream(new File(path)); data.putExtra("NAME", ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString());
outputStream.write(os.toByteArray()); setResult(RESULT_OK, data);
} else {
showToast(os.toString());
}
setResult(RESULT_OK);
finish(); finish();
} catch (Exception e) { } catch (Exception e) {
Log.e(Constants.TAG, "UnsupportedEncodingException", e); Log.e(Constants.TAG, "UnsupportedEncodingException", e);
@ -406,7 +401,6 @@ public class PgpHandler extends Activity {
data.setAction(OpenPgpApi.ACTION_ENCRYPT); data.setAction(OpenPgpApi.ACTION_ENCRYPT);
data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{accountName}); data.putExtra(OpenPgpApi.EXTRA_USER_IDS, new String[]{accountName});
data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); 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 name = ((EditText) findViewById(R.id.crypto_password_file_edit)).getText().toString();
String pass = ((EditText) findViewById(R.id.crypto_password_edit)).getText().toString(); String pass = ((EditText) findViewById(R.id.crypto_password_edit)).getText().toString();

View file

@ -6,7 +6,7 @@
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.zeapo.pwdstore.GitClone"> tools:context="com.zeapo.pwdstore.GitHandler">
<LinearLayout <LinearLayout
android:orientation="vertical" android:orientation="vertical"

View file

@ -1,6 +1,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" 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" <item android:id="@+id/action_settings"
android:title="@string/action_settings" android:title="@string/action_settings"
android:orderInCategory="100" android:orderInCategory="100"

View file

@ -7,8 +7,13 @@
<!--<item android:id="@+id/menu_add_category"--> <!--<item android:id="@+id/menu_add_category"-->
<!--android:title="New 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" <item android:id="@+id/referesh"
android:title="Refresh" android:title="Refresh list"
android:showAsAction="ifRoom" android:showAsAction="ifRoom"
android:icon="@android:drawable/ic_popup_sync"/> android:icon="@android:drawable/ic_popup_sync"/>

View file

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <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"> <PreferenceCategory android:title="Crypto">
<org.openintents.openpgp.util.OpenPgpListPreference <org.openintents.openpgp.util.OpenPgpListPreference