diff options
Diffstat (limited to 'app/src')
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/GitHandler.java | 127 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/PasswordStore.java | 41 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java | 12 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.java | 11 | ||||
-rw-r--r-- | app/src/main/res/drawable/bottom_line.xml | 14 | ||||
-rw-r--r-- | app/src/main/res/layout/activity_git_clone.xml | 209 | ||||
-rw-r--r-- | app/src/main/res/layout/decrypt_layout.xml | 2 | ||||
-rw-r--r-- | app/src/main/res/menu/pwdstore.xml | 2 | ||||
-rw-r--r-- | app/src/main/res/values/strings.xml | 16 |
9 files changed, 377 insertions, 57 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/GitHandler.java b/app/src/main/java/com/zeapo/pwdstore/GitHandler.java index c487ce0f..651b23d7 100644 --- a/app/src/main/java/com/zeapo/pwdstore/GitHandler.java +++ b/app/src/main/java/com/zeapo/pwdstore/GitHandler.java @@ -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(). diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java index 4fadb65e..a613b021 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.java @@ -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()); diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java index 78902d8a..efeabc3e 100644 --- a/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java +++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PgpHandler.java @@ -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; } diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.java b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.java index 289f9f43..24a1524c 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.java +++ b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.java @@ -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; diff --git a/app/src/main/res/drawable/bottom_line.xml b/app/src/main/res/drawable/bottom_line.xml new file mode 100644 index 00000000..c24a04df --- /dev/null +++ b/app/src/main/res/drawable/bottom_line.xml @@ -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> diff --git a/app/src/main/res/layout/activity_git_clone.xml b/app/src/main/res/layout/activity_git_clone.xml index b427ac8d..a173f6f6 100644 --- a/app/src/main/res/layout/activity_git_clone.xml +++ b/app/src/main/res/layout/activity_git_clone.xml @@ -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_width="match_parent" + 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: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: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: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:id="@+id/connection_mode"></Spinner> + 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" /> - <Button - android:id="@+id/clone_button" - android:text="Clone!" + <Spinner android:layout_width="match_parent" android:layout_height="wrap_content" - android:onClick="cloneRepository"/> - </LinearLayout> + 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"/> -</RelativeLayout> +</LinearLayout> diff --git a/app/src/main/res/layout/decrypt_layout.xml b/app/src/main/res/layout/decrypt_layout.xml index 300e1d49..6169dd19 100644 --- a/app/src/main/res/layout/decrypt_layout.xml +++ b/app/src/main/res/layout/decrypt_layout.xml @@ -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" diff --git a/app/src/main/res/menu/pwdstore.xml b/app/src/main/res/menu/pwdstore.xml index 65bc0272..a3f44f73 100644 --- a/app/src/main/res/menu/pwdstore.xml +++ b/app/src/main/res/menu/pwdstore.xml @@ -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" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 78e25d2b..c35514ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -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> |