Authentication works correctly for clone, some cleaning is still required
This commit is contained in:
parent
bbf0175d69
commit
6532252f31
6 changed files with 244 additions and 136 deletions
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
|
@ -24,78 +24,118 @@ import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.jcraft.jsch.JSch;
|
||||||
|
import com.jcraft.jsch.JSchException;
|
||||||
|
import com.jcraft.jsch.Session;
|
||||||
|
import com.jcraft.jsch.UserInfo;
|
||||||
import com.zeapo.pwdstore.R;
|
import com.zeapo.pwdstore.R;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.api.CloneCommand;
|
||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||||
import org.eclipse.jgit.diff.Edit;
|
import org.eclipse.jgit.diff.Edit;
|
||||||
|
import org.eclipse.jgit.errors.NoRemoteRepositoryException;
|
||||||
|
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
|
||||||
|
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||||
|
import org.eclipse.jgit.transport.CredentialItem;
|
||||||
|
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||||
|
import org.eclipse.jgit.transport.CredentialsProviderUserInfo;
|
||||||
|
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||||
|
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||||
|
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||||
|
import org.eclipse.jgit.transport.URIish;
|
||||||
|
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||||
|
import org.eclipse.jgit.util.FS;
|
||||||
|
import org.eclipse.jgit.util.StringUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
|
||||||
public class GitClone extends Activity implements AdapterView.OnItemSelectedListener {
|
public class GitClone extends Activity {
|
||||||
|
|
||||||
|
|
||||||
/* The clone process has to be on a different thread than the main one */
|
|
||||||
private class CloneTask extends AsyncTask<File, Integer, Long> {
|
|
||||||
private ProgressDialog dialog;
|
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
public CloneTask(Activity activity) {
|
private String protocol;
|
||||||
this.activity = activity;
|
private String connectionMode;
|
||||||
context = activity;
|
|
||||||
dialog = new ProgressDialog(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onPreExecute() {
|
private File localDir;
|
||||||
this.dialog.setMessage("Cloning...");
|
private String hostname;
|
||||||
this.dialog.setCancelable(false);
|
|
||||||
this.dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onPostExecute(Long result) {
|
|
||||||
this.dialog.dismiss();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Long doInBackground(File... remote) {
|
|
||||||
int count = remote.length;
|
|
||||||
long totalSize = 0;
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
try {
|
|
||||||
Git.cloneRepository().
|
|
||||||
setCloneAllBranches(true).
|
|
||||||
setDirectory(remote[i]).
|
|
||||||
setURI(((TextView) findViewById(R.id.clone_uri)).getText().toString())
|
|
||||||
.call();
|
|
||||||
totalSize++;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
totalSize++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return totalSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_git_clone);
|
setContentView(R.layout.activity_git_clone);
|
||||||
|
|
||||||
// init the spinner
|
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() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
|
protocol = ((Spinner)findViewById(R.id.clone_protocol)).getSelectedItem().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// init the spinner for connection modes
|
||||||
Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode);
|
Spinner connection_mode_spinner = (Spinner) findViewById(R.id.connection_mode);
|
||||||
ArrayAdapter<CharSequence> connection_mode_adapter = ArrayAdapter.createFromResource(this,
|
ArrayAdapter<CharSequence> connection_mode_adapter = ArrayAdapter.createFromResource(this,
|
||||||
R.array.connection_modes, android.R.layout.simple_spinner_item);
|
R.array.connection_modes, android.R.layout.simple_spinner_item);
|
||||||
connection_mode_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
connection_mode_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
connection_mode_spinner.setAdapter(connection_mode_adapter);
|
connection_mode_spinner.setAdapter(connection_mode_adapter);
|
||||||
connection_mode_spinner.setOnItemSelectedListener(this);
|
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
|
||||||
|
@ -117,54 +157,140 @@ public class GitClone extends Activity implements AdapterView.OnItemSelectedList
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cloneRepository(View view) {
|
/* The clone process has to be on a different thread than the main one */
|
||||||
|
private class CloneTask extends AsyncTask<CloneCommand, Integer, Long> {
|
||||||
|
private ProgressDialog dialog;
|
||||||
|
|
||||||
final File localDir = new File(getApplicationContext().getCacheDir().getAbsoluteFile() + "/store");
|
public CloneTask(Activity activity) {
|
||||||
|
context = activity;
|
||||||
|
dialog = new ProgressDialog(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPreExecute() {
|
||||||
|
this.dialog.setMessage("Cloning...");
|
||||||
|
this.dialog.setCancelable(false);
|
||||||
|
this.dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Long result) {
|
||||||
|
if (result < 0) {
|
||||||
|
new AlertDialog.Builder(activity).
|
||||||
|
setTitle("Invalid remote repository path").
|
||||||
|
setMessage("Please check that the repository path is correct.\nDid you forget to specify the path after the hostname?").
|
||||||
|
setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
this.dialog.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Long doInBackground(CloneCommand... cmd) {
|
||||||
|
int count = cmd.length;
|
||||||
|
long totalSize = 0;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
try {
|
||||||
|
cmd[i].call();
|
||||||
|
} catch (InvalidRemoteException e) {
|
||||||
|
return new Long(-1);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
totalSize++;
|
||||||
|
}
|
||||||
|
return totalSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class GitConfigSessionFactory extends JschConfigSessionFactory {
|
||||||
|
|
||||||
|
public void configure(OpenSshConfig.Host hc, Session session) {
|
||||||
|
session.setConfig("StrictHostKeyChecking", "no");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JSch
|
||||||
|
getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException {
|
||||||
|
JSch jsch = super.getJSch(hc, fs);
|
||||||
|
jsch.removeAllIdentity();
|
||||||
|
return jsch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void cloneRepository(View view) {
|
||||||
|
localDir = new File(getApplicationContext().getCacheDir().getAbsoluteFile() + "/store");
|
||||||
|
|
||||||
|
hostname = ((TextView) findViewById(R.id.clone_uri)).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);
|
||||||
|
|
||||||
|
// now cheat a little and prepend the real protocol
|
||||||
|
// jGit does not accept a ssh:// but requires https://
|
||||||
|
if (!protocol.equals("ssh://")) hostname = new String(protocol + hostname);
|
||||||
|
|
||||||
if (localDir.exists()) {
|
if (localDir.exists()) {
|
||||||
AlertDialog.Builder builder1 = new AlertDialog.Builder(this);
|
new AlertDialog.Builder(this).
|
||||||
builder1.setMessage(R.string.dialog_delete_msg);
|
setTitle(R.string.dialog_delete_title).
|
||||||
builder1.setCancelable(true);
|
setMessage(R.string.dialog_delete_msg).
|
||||||
builder1.setPositiveButton(R.string.dialog_delete,
|
setCancelable(false).
|
||||||
|
setPositiveButton(R.string.dialog_delete,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
try {
|
try {
|
||||||
FileUtils.deleteDirectory(localDir);
|
FileUtils.deleteDirectory(localDir);
|
||||||
|
authenticateThenClone(localDir);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
//TODO Handle the exception correctly
|
//TODO Handle the exception correctly if we are unable to delete the directory...
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
//This is what happens when jgit fails :(
|
||||||
|
//TODO Handle the diffent cases of exceptions
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
).
|
||||||
builder1.setNegativeButton(R.string.dialog_do_not_delete,
|
setNegativeButton(R.string.dialog_do_not_delete,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
).
|
||||||
|
show();
|
||||||
AlertDialog alert11 = builder1.create();
|
} else {
|
||||||
alert11.show();
|
try {
|
||||||
|
authenticateThenClone(localDir);
|
||||||
|
} catch (Exception e) {
|
||||||
|
//This is what happens when jgit fails :(
|
||||||
|
//TODO Handle the diffent cases of exceptions
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void authenticateThenClone(final File localDir) {
|
||||||
String connectionMode = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString();
|
String connectionMode = ((Spinner) findViewById(R.id.connection_mode)).getSelectedItem().toString();
|
||||||
|
|
||||||
if (connectionMode.equalsIgnoreCase("ssh-key")) {
|
if (connectionMode.equalsIgnoreCase("ssh-key")) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Set an EditText view to get user input
|
// Set an EditText view to get user input
|
||||||
final LinearLayout layout = new LinearLayout(this);
|
final LinearLayout layout = new LinearLayout(activity);
|
||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
layout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
final EditText username = new EditText(this);
|
final EditText username = new EditText(activity);
|
||||||
username.setHint("Username");
|
username.setHint("Username");
|
||||||
username.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
|
username.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
|
||||||
|
|
||||||
final EditText password = new EditText(this);
|
final EditText password = new EditText(activity);
|
||||||
password.setHint("Password");
|
password.setHint("Password");
|
||||||
password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
|
password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT);
|
||||||
password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||||
|
@ -172,15 +298,22 @@ public class GitClone extends Activity implements AdapterView.OnItemSelectedList
|
||||||
layout.addView(username);
|
layout.addView(username);
|
||||||
layout.addView(password);
|
layout.addView(password);
|
||||||
|
|
||||||
|
new AlertDialog.Builder(activity)
|
||||||
new AlertDialog.Builder(this)
|
|
||||||
.setTitle("Authenticate")
|
.setTitle("Authenticate")
|
||||||
.setMessage("Please provide your usename and password for this repository")
|
.setMessage("Please provide your usename and password for this repository")
|
||||||
.setView(layout)
|
.setView(layout)
|
||||||
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
|
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
//TODO use Jsch to set the authentication method
|
|
||||||
|
|
||||||
|
SshSessionFactory.setInstance(new GitConfigSessionFactory());
|
||||||
|
|
||||||
|
CloneCommand cmd = Git.cloneRepository().
|
||||||
|
setCredentialsProvider(new UsernamePasswordCredentialsProvider("git", "nicomint")).
|
||||||
|
setCloneAllBranches(true).
|
||||||
|
setDirectory(localDir).
|
||||||
|
setURI(hostname);
|
||||||
|
|
||||||
|
new CloneTask(activity).execute(cmd);
|
||||||
}
|
}
|
||||||
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
@ -188,38 +321,8 @@ public class GitClone extends Activity implements AdapterView.OnItemSelectedList
|
||||||
}
|
}
|
||||||
}).show();
|
}).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
new CloneTask(this).execute(localDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void selectConnectionMode(View view) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* when the connection mode is selected */
|
|
||||||
@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(this)
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,21 +13,25 @@
|
||||||
android:layoutDirection="ltr"
|
android:layoutDirection="ltr"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/clone_protocol"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"></Spinner>
|
||||||
<EditText
|
<EditText
|
||||||
android:hint="Repository"
|
android:hint="Repository URI"
|
||||||
android:id="@+id/clone_uri"
|
android:id="@+id/clone_uri"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/connection_mode"></Spinner>
|
android:id="@+id/connection_mode"></Spinner>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/config_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"></LinearLayout>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/clone_button"
|
android:id="@+id/clone_button"
|
||||||
android:text="Clone!"
|
android:text="Clone!"
|
||||||
|
|
|
@ -8,10 +8,4 @@
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
tools:context=".pwdstore">
|
tools:context=".pwdstore">
|
||||||
|
|
||||||
<Button
|
|
||||||
android:text="@string/clone"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:onClick="getClone"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<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=".pwdstore" >
|
tools:context=".pwdstore" >
|
||||||
<item android:id="@+id/action_settings"
|
<item android:id="@+id/clone_setting"
|
||||||
android:title="@string/action_settings"
|
android:title="@string/clone_setting"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="100"
|
||||||
android:showAsAction="never" />
|
android:showAsAction="ifRoom"
|
||||||
|
android:onClick="getClone"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
<string name="app_name">PwdStore</string>
|
<string name="app_name">PwdStore</string>
|
||||||
<string name="clone">Clone!</string>
|
<string name="clone">Clone!</string>
|
||||||
<string name="action_settings">Settings</string>
|
<string name="clone_setting">Clone</string>
|
||||||
<string name="hello_world">Hello world!</string>
|
<string name="hello_world">Hello world!</string>
|
||||||
|
|
||||||
<string name="dialog_delete_title">Remove dir</string>
|
<string name="dialog_delete_title">Directory already exist</string>
|
||||||
<string name="dialog_delete_msg">Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory?</string>
|
<string name="dialog_delete_msg">Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory?</string>
|
||||||
<string name="dialog_delete">Delete directory</string>
|
<string name="dialog_delete">Delete directory</string>
|
||||||
<string name="dialog_do_not_delete">Cancel</string>
|
<string name="dialog_do_not_delete">Cancel</string>
|
||||||
|
@ -16,4 +16,10 @@
|
||||||
<item>ssh-key</item>
|
<item>ssh-key</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="clone_protocols">
|
||||||
|
<item>ssh://</item>
|
||||||
|
<item>https://</item>
|
||||||
|
<item>http://</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue