merged changes made in master

This commit is contained in:
knuthy 2014-10-02 08:26:26 +02:00
commit 57948768c0
11 changed files with 379 additions and 59 deletions

Binary file not shown.

View file

@ -9,8 +9,8 @@ android {
applicationId "com.zeapo.pwdstore"
minSdkVersion 15
targetSdkVersion 19
versionCode 13
versionName "1.1-b6"
versionCode 15
versionName "1.1-b8"
}
buildTypes {
release {

View file

@ -9,6 +9,8 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@ -32,6 +34,7 @@ import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
@ -46,6 +49,10 @@ import org.eclipse.jgit.util.FS;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
// TODO move the messages to strings.xml
@ -60,6 +67,7 @@ public class GitHandler extends Activity {
private File localDir;
private String hostname;
private String username;
private String port;
private SharedPreferences settings;
@ -80,7 +88,7 @@ public class GitHandler extends Activity {
settings = PreferenceManager.getDefaultSharedPreferences(this.context);
protocol = settings.getString("git_remote_protocol", "ssh://");
connectionMode = settings.getString("git_remote_auth", "username/password");
connectionMode = settings.getString("git_remote_auth", "ssh-key");
switch (getIntent().getExtras().getInt("Operation")) {
case REQUEST_CLONE:
@ -139,6 +147,40 @@ public class GitHandler extends Activity {
}
});
// init the server information
EditText server_url = ((EditText) findViewById(R.id.server_url));
EditText server_port = ((EditText) findViewById(R.id.server_port));
EditText server_path = ((EditText) findViewById(R.id.server_path));
EditText server_user = ((EditText) findViewById(R.id.server_user));
final EditText server_uri = ((EditText)findViewById(R.id.clone_uri));
View.OnKeyListener updateListener = new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
updateURI();
return false;
}
};
server_url.setText(settings.getString("git_remote_server", ""));
server_port.setText(settings.getString("git_remote_server_port", ""));
server_user.setText(settings.getString("git_remote_username", ""));
server_path.setText(settings.getString("git_remote_location", ""));
server_url.setOnKeyListener(updateListener);
server_port.setOnKeyListener(updateListener);
server_user.setOnKeyListener(updateListener);
server_path.setOnKeyListener(updateListener);
server_uri.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
splitURI();
return false;
}
});
break;
case REQUEST_PULL:
authenticateAndRun("pullOperation");
@ -152,23 +194,78 @@ public class GitHandler extends Activity {
}
@Override
public void onResume() {
super.onResume();
/** Fills in the server_uri field with the information coming from other fields */
private void updateURI() {
EditText uri = (EditText) findViewById(R.id.clone_uri);
EditText server_url = ((EditText) findViewById(R.id.server_url));
EditText server_port = ((EditText) findViewById(R.id.server_port));
EditText server_path = ((EditText) findViewById(R.id.server_path));
EditText server_user = ((EditText) findViewById(R.id.server_user));
if (uri != null) {
String hostname =
settings.getString("git_remote_username", "")
server_user.getText()
+ "@" +
settings.getString("git_remote_server", "").trim()
+ ":" +
settings.getString("git_remote_location", "");
server_url.getText().toString().trim()
+ ":";
if (server_port.getText().toString().equals("22")) {
hostname += server_path.getText().toString();
((TextView) findViewById(R.id.warn_url)).setVisibility(View.GONE);
} else {
TextView warn_url = (TextView) findViewById(R.id.warn_url);
if (!server_path.getText().toString().matches("/.*") && !server_port.getText().toString().isEmpty()) {
warn_url.setText(R.string.warn_malformed_url_port);
warn_url.setVisibility(View.VISIBLE);
} else {
warn_url.setVisibility(View.GONE);
}
hostname += server_port.getText().toString() + server_path.getText().toString();
}
if (!hostname.equals("@:")) uri.setText(hostname);
}
}
/** Splits the information in server_uri into the other fields */
private void splitURI() {
EditText server_uri = (EditText) findViewById(R.id.clone_uri);
EditText server_url = ((EditText) findViewById(R.id.server_url));
EditText server_port = ((EditText) findViewById(R.id.server_port));
EditText server_path = ((EditText) findViewById(R.id.server_path));
EditText server_user = ((EditText) findViewById(R.id.server_user));
String uri = server_uri.getText().toString();
Pattern pattern = Pattern.compile("(.+)@([\\w\\d\\.]+):([\\d]+)*(.*)");
Matcher matcher = pattern.matcher(uri);
if (matcher.find()) {
int count = matcher.groupCount();
Log.i("GIT", ">> " + count);
if (count > 1) {
server_user.setText(matcher.group(1));
server_url.setText(matcher.group(2));
}
if (count == 4) {
server_port.setText(matcher.group(3));
server_path.setText(matcher.group(4));
TextView warn_url = (TextView) findViewById(R.id.warn_url);
if (!server_path.getText().toString().matches("/.*") && !server_port.getText().toString().isEmpty()) {
warn_url.setText(R.string.warn_malformed_url_port);
warn_url.setVisibility(View.VISIBLE);
} else {
warn_url.setVisibility(View.GONE);
}
}
}
}
@Override
public void onResume() {
super.onResume();
updateURI();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
@ -268,7 +365,8 @@ public class GitHandler extends Activity {
public void cloneRepository(View view) {
localDir = new File(getApplicationContext().getFilesDir().getAbsoluteFile() + "/store");
hostname = ((TextView) findViewById(R.id.clone_uri)).getText().toString();
hostname = ((EditText) findViewById(R.id.clone_uri)).getText().toString();
port = ((EditText) findViewById(R.id.server_port)).getText().toString();
// don't ask the user, take off the protocol that he puts in
hostname = hostname.replaceFirst("^.+://", "");
((TextView) findViewById(R.id.clone_uri)).setText(hostname);
@ -278,6 +376,13 @@ public class GitHandler extends Activity {
if (!protocol.equals("ssh://")) {
hostname = protocol + hostname;
} else {
// if the port is explicitly given, jgit requires the ssh://
if (!port.isEmpty())
hostname = protocol + hostname;
Log.i("GIT", "> " + port);
// did he forget the username?
if (!hostname.matches("^.+@.+")) {
new AlertDialog.Builder(this).
@ -343,11 +448,13 @@ public class GitHandler extends Activity {
// remember the settings
SharedPreferences.Editor editor = settings.edit();
// TODO this is not pretty, use the information obtained earlier
editor.putString("git_remote_server", hostname.split("@")[1].split(":")[0]);
editor.putString("git_remote_location", hostname.split("@")[1].split(":")[1]);
editor.putString("git_remote_username", hostname.split("@")[0]);
editor.putString("git_remote_protocol", protocol);
editor.putString("git_remote_auth", connectionMode);
editor.putString("git_remote_port", port);
editor.commit();
CloneCommand cmd = Git.cloneRepository().

View file

@ -10,19 +10,11 @@ import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ExpandableListView;
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;
@ -30,12 +22,6 @@ import com.zeapo.pwdstore.utils.PasswordRepository;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.revwalk.RevCommit;
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;
@ -91,6 +77,14 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
int id = item.getItemId();
Intent intent;
AlertDialog.Builder initBefore = new AlertDialog.Builder(this)
.setMessage("Please clone or create a new repository below before trying to add a password or any synchronization operation.")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
switch (id) {
case R.id.user_pref:
try {
@ -104,6 +98,11 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
return true;
case R.id.menu_add_password:
if (!PasswordRepository.isInitialized()) {
initBefore.show();
break;
}
createPassword(getCurrentFocus());
break;
@ -111,6 +110,11 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
// break;
case R.id.git_push:
if (!PasswordRepository.isInitialized()) {
initBefore.show();
break;
}
intent = new Intent(this, GitHandler.class);
intent.putExtra("Operation", GitHandler.REQUEST_PUSH);
startActivityForResult(intent, GitHandler.REQUEST_PUSH);
@ -118,6 +122,11 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
return true;
case R.id.git_pull:
if (!PasswordRepository.isInitialized()) {
initBefore.show();
break;
}
intent = new Intent(this, GitHandler.class);
intent.putExtra("Operation", GitHandler.REQUEST_PULL);
startActivityForResult(intent, GitHandler.REQUEST_PULL);
@ -241,12 +250,14 @@ public class PasswordStore extends Activity implements ToCloneOrNot.OnFragmentI
case 0:
if(!localDir.equals(PasswordRepository.getWorkTree()))
break;
PasswordRepository.setInitialized(false);
ToCloneOrNot cloneFrag = new ToCloneOrNot();
fragmentTransaction.replace(R.id.main_layout, cloneFrag, "ToCloneOrNot");
fragmentTransaction.commit();
break;
default:
PasswordRepository.setInitialized(true);
PasswordFragment passFrag = new PasswordFragment();
Bundle args = new Bundle();
args.putString("Path", localDir.getAbsolutePath());

View file

@ -147,6 +147,9 @@ public class PgpHandler extends Activity implements OpenPgpServiceConnection.OnB
case R.id.copy_password:
ClipData clip = ClipData.newPlainText("pgp_handler_result_pm", ((TextView) findViewById(R.id.crypto_password_show)).getText());
clipboard.setPrimaryClip(clip);
showToast("Password copied to clipboard, you have "
+ Integer.parseInt(settings.getString("general_show_time", "45"))
+ " seconds to paste it somewhere.");
}
return super.onOptionsItemSelected(item);
}
@ -387,10 +390,19 @@ public class PgpHandler extends Activity implements OpenPgpServiceConnection.OnB
break;
}
case OpenPgpApi.RESULT_CODE_ERROR: {
// TODO show what kind of error it is
/* For example:
* No suitable key found -> no key in OpenKeyChain
*
* Check in open-pgp-lib how their definitions and error code
*/
showToast("ERROR");
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
handleError(error);
// close the dialog
bindingDialog.dismiss();
break;
}

View file

@ -26,6 +26,7 @@ import static java.util.Collections.sort;
public class PasswordRepository {
private static Repository repository;
private static boolean initialized = false;
protected PasswordRepository(){ }
@ -37,7 +38,6 @@ public class PasswordRepository {
.readEnvironment()
.findGitDir()
.build();
} catch (Exception e) {
e.printStackTrace();
return null;
@ -46,6 +46,14 @@ public class PasswordRepository {
return repository;
}
public static boolean isInitialized() {
return initialized;
}
public static void setInitialized(boolean v) {
initialized = v;
}
public static void createRepository(File localDir) {
localDir.delete();
@ -66,6 +74,7 @@ public class PasswordRepository {
.setName("master")
.call();
initialized = true;
} catch (Exception e) {
e.printStackTrace();
return;

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/holo_orange_dark"/>
</shape>
</item>
<item android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
</shape>
</item>
</layer-list>

View file

@ -1,46 +1,199 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.zeapo.pwdstore.GitHandler">
tools:context="com.zeapo.pwdstore.GitHandler"
android:orientation="vertical">
<LinearLayout
android:orientation="vertical"
android:layoutDirection="ltr"
<TextView
android:layout_width="fill_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_height="wrap_content"
android:text="@string/server_name"
android:textStyle="bold"
style="@android:style/TextAppearance.Large"
android:gravity="left"
android:paddingBottom="6dp"
android:textColor="@android:color/holo_orange_dark"
android:background="@drawable/bottom_line"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_protocol"
android:id="@+id/label_server_protocol"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Spinner
android:id="@+id/clone_protocol"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="@+id/clone_protocol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Spinner>
<EditText
android:hint="Repository URI"
android:id="@+id/clone_uri"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textWebEmailAddress"/>
</LinearLayout>
android:layout_toEndOf="@+id/label_server_protocol"
android:layout_toRightOf="@+id/label_server_protocol" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_user"
android:id="@+id/label_server_user"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/server_user_hint"
android:id="@+id/server_user"
android:layout_toEndOf="@+id/label_server_user"
android:layout_toRightOf="@+id/label_server_user"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_url"
android:id="@+id/label_server_url"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/server_url_hint"
android:id="@+id/server_url"
android:layout_toEndOf="@+id/label_server_url"
android:layout_toRightOf="@+id/label_server_url"
android:layout_toLeftOf="@+id/label_server_port"
android:layout_toStartOf="@+id/label_server_port" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":"
android:id="@+id/label_server_port"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/server_port"
android:layout_toStartOf="@+id/server_port" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/server_port_hint"
android:id="@+id/server_port"
android:layout_alignParentRight="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_path"
android:id="@+id/label_server_path"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/server_path_hint"
android:id="@+id/server_path"
android:layout_toEndOf="@+id/label_server_path"
android:layout_toRightOf="@+id/label_server_path"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/server_resulting_url"
android:textStyle="bold"
style="@android:style/TextAppearance.Large"
android:gravity="left"
android:paddingBottom="6dp"
android:textColor="@android:color/holo_orange_dark"
android:background="@drawable/bottom_line"/>
<EditText
android:hint="Repository URI"
android:id="@+id/clone_uri"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textWebEmailAddress"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/red_rectangle"
android:textColor="@android:color/white"
android:visibility="gone"
android:id="@+id/warn_url"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connection_mode"
android:id="@+id/label_connection_mode"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/connection_mode"></Spinner>
android:id="@+id/connection_mode"
android:layout_toEndOf="@+id/label_connection_mode"
android:layout_toRightOf="@+id/label_connection_mode" />
</RelativeLayout>
<Button
android:id="@+id/clone_button"
android:text="Clone!"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="cloneRepository"/>
</LinearLayout>
<Button
android:id="@+id/clone_button"
android:text="Clone!"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="cloneRepository"/>
</RelativeLayout>
</LinearLayout>

View file

@ -77,7 +77,7 @@
<ProgressBar
android:id="@+id/pbLoading"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_height="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
style="?android:attr/progressBarStyleHorizontal"

View file

@ -17,7 +17,7 @@
<item android:id="@+id/referesh"
android:title="Refresh list"
android:showAsAction="ifRoom"
android:showAsAction="never"
android:icon="@drawable/ico_sync"/>
<item android:id="@+id/user_pref"

View file

@ -18,7 +18,21 @@
<string name="clone_fragment_text">Welcome to Password Store\n\n In this screen you can either create a new repository or clone your git repository onto your device.</string>
<string name="clone">Clone existing</string>
<string name="initialize">Create new</string>
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="server_name">Server</string>
<string name="server_protocol">Protocol</string>
<string name="server_url">Server URL</string>
<string name="server_url_hint">server.com</string>
<string name="server_port_hint">22</string>
<string name="server_path">Repo path</string>
<string name="server_path_hint">/path/to/pass</string>
<string name="server_user">Username</string>
<string name="server_user_hint">git_username</string>
<string name="server_resulting_url">Resulting URL</string>
<string name="connection_mode">Authentication Mode</string>
<string name="warn_malformed_url_port">When using custom ports, provide an absolute path (starts with "/")</string>
<!-- PGP Handler -->
<string name="title_activity_pgp_handler">PgpHandler</string>