implemented editing of connection settings for ftp/sftp/webdav, includes changing password. Closes #27
This commit is contained in:
@@ -112,6 +112,5 @@ namespace keepass2android
|
||||
#if !NoNet
|
||||
ICertificateErrorHandler CertificateErrorHandler { get; }
|
||||
#endif
|
||||
bool CanEditIoc(IOConnectionInfo ioc);
|
||||
}
|
||||
}
|
@@ -231,7 +231,7 @@ namespace keepass2android.Io
|
||||
|
||||
|
||||
|
||||
internal Uri IocToUri(IOConnectionInfo ioc)
|
||||
public static Uri IocToUri(IOConnectionInfo ioc)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ioc.UserName))
|
||||
{
|
||||
@@ -575,7 +575,7 @@ namespace keepass2android.Io
|
||||
{
|
||||
|
||||
_client = _fileStorage.GetClient(_ioc, false);
|
||||
_stream = _client.OpenWrite(_fileStorage.IocToUri(_iocTemp).PathAndQuery);
|
||||
_stream = _client.OpenWrite(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery);
|
||||
return _stream;
|
||||
}
|
||||
catch (FtpCommandException ex)
|
||||
@@ -595,8 +595,8 @@ namespace keepass2android.Io
|
||||
//make sure target file does not exist:
|
||||
//try
|
||||
{
|
||||
if (_client.FileExists(_fileStorage.IocToUri(_ioc).PathAndQuery))
|
||||
_client.DeleteFile(_fileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
if (_client.FileExists(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery))
|
||||
_client.DeleteFile(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
|
||||
}
|
||||
//catch (FtpCommandException)
|
||||
@@ -604,8 +604,8 @@ namespace keepass2android.Io
|
||||
//TODO get a new clien? might be stale
|
||||
}
|
||||
|
||||
_client.Rename(_fileStorage.IocToUri(_iocTemp).PathAndQuery,
|
||||
_fileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
_client.Rename(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery,
|
||||
NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
|
||||
}
|
||||
catch (FtpCommandException ex)
|
||||
|
@@ -53,9 +53,10 @@ namespace keepass2android
|
||||
{
|
||||
try
|
||||
{
|
||||
SaveFileData(_ioc, _keyfileOrProvider);
|
||||
|
||||
|
||||
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
||||
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
||||
//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not:
|
||||
MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result;
|
||||
MemoryStream databaseStream;
|
||||
@@ -134,8 +135,7 @@ namespace keepass2android
|
||||
//now let's go:
|
||||
try
|
||||
{
|
||||
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
|
||||
SaveFileData(_ioc, _keyfileOrProvider);
|
||||
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
|
||||
Kp2aLog.Log("LoadDB OK");
|
||||
Finish(true, _format.SuccessMessage);
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package keepass2android.javafilestorage.webdav;
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
/**
|
||||
* Created by Philipp on 22.11.2016.
|
@@ -26,14 +26,14 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
public static final int DEFAULT_SFTP_PORT = 22;
|
||||
JSch jsch;
|
||||
|
||||
class ConnectionInfo
|
||||
|
||||
public class ConnectionInfo
|
||||
{
|
||||
String host;
|
||||
String username;
|
||||
String password;
|
||||
String localPath;
|
||||
int port;
|
||||
public String host;
|
||||
public String username;
|
||||
public String password;
|
||||
public String localPath;
|
||||
public int port;
|
||||
}
|
||||
|
||||
public SftpStorage() {
|
||||
@@ -333,7 +333,7 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
}
|
||||
|
||||
private ConnectionInfo splitStringToConnectionInfo(String filename)
|
||||
public ConnectionInfo splitStringToConnectionInfo(String filename)
|
||||
throws UnsupportedEncodingException {
|
||||
ConnectionInfo ci = new ConnectionInfo();
|
||||
ci.host = extractUserPwdHost(filename);
|
||||
@@ -348,6 +348,7 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
ci.port = Integer.parseInt(ci.host.substring(portSeparatorIndex+1));
|
||||
ci.host = ci.host.substring(0, portSeparatorIndex);
|
||||
}
|
||||
ci.localPath = extractSessionPath(filename);
|
||||
return ci;
|
||||
}
|
||||
|
||||
@@ -384,7 +385,7 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
try
|
||||
{
|
||||
ConnectionInfo ci = splitStringToConnectionInfo(path);
|
||||
return getProtocolPrefix()+ci.username+"@"+ci.host+extractSessionPath(path);
|
||||
return getProtocolPrefix()+ci.username+"@"+ci.host+ci.localPath;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -414,7 +415,7 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String buildFullPath( String host, int port, String localPath, String username, String password) throws UnsupportedEncodingException
|
||||
{
|
||||
if (port != DEFAULT_SFTP_PORT)
|
||||
@@ -423,6 +424,7 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void prepareFileUsage(Context appContext, String path) {
|
||||
//nothing to do
|
||||
|
@@ -36,7 +36,7 @@ import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import keepass2android.javafilestorage.webdav.ConnectionInfo;
|
||||
import keepass2android.javafilestorage.ConnectionInfo;
|
||||
import keepass2android.javafilestorage.webdav.DecoratedHostnameVerifier;
|
||||
import keepass2android.javafilestorage.webdav.DecoratedTrustManager;
|
||||
import keepass2android.javafilestorage.webdav.PropfindXmlParser;
|
||||
@@ -64,7 +64,7 @@ public class WebDavStorage extends JavaFileStorageBase {
|
||||
return scheme + "://" + encode(username)+":"+encode(password)+"@"+url;
|
||||
}
|
||||
|
||||
private ConnectionInfo splitStringToConnectionInfo(String filename)
|
||||
public ConnectionInfo splitStringToConnectionInfo(String filename)
|
||||
throws UnsupportedEncodingException {
|
||||
ConnectionInfo ci = new ConnectionInfo();
|
||||
|
||||
|
@@ -14,6 +14,7 @@ using Android.Views;
|
||||
using Android.Widget;
|
||||
using Java.IO;
|
||||
using keepass2android.Io;
|
||||
using Keepass2android.Javafilestorage;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
@@ -24,8 +25,9 @@ namespace keepass2android
|
||||
private readonly Activity _activity;
|
||||
private readonly bool _isForSave;
|
||||
private readonly int _requestCode;
|
||||
private readonly string _schemeSeparator = "://";
|
||||
|
||||
public string DefaultExtension { get; set; }
|
||||
public string DefaultExtension { get; set; }
|
||||
|
||||
public FileSelectHelper(Activity activity, bool isForSave, int requestCode)
|
||||
{
|
||||
@@ -34,11 +36,23 @@ namespace keepass2android
|
||||
_requestCode = requestCode;
|
||||
}
|
||||
|
||||
private void ShowSftpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel)
|
||||
private void ShowSftpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel, string defaultPath)
|
||||
{
|
||||
#if !EXCLUDE_JAVAFILESTORAGE && !NoNet
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.sftpcredentials, null);
|
||||
|
||||
if (!defaultPath.EndsWith(_schemeSeparator))
|
||||
{
|
||||
var fileStorage = new Keepass2android.Javafilestorage.SftpStorage();
|
||||
SftpStorage.ConnectionInfo ci = fileStorage.SplitStringToConnectionInfo(defaultPath);
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_host).Text = ci.Host;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_port).Text = ci.Port.ToString();
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_user).Text = ci.Username;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_password).Text = ci.Password;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_initial_dir).Text = ci.LocalPath;
|
||||
}
|
||||
|
||||
builder.SetView(dlgContents);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok,
|
||||
(sender, args) =>
|
||||
@@ -70,6 +84,16 @@ namespace keepass2android
|
||||
#if !EXCLUDE_JAVAFILESTORAGE && !NoNet
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.httpcredentials, null);
|
||||
if (!defaultPath.EndsWith(_schemeSeparator))
|
||||
{
|
||||
var webdavStorage = new Keepass2android.Javafilestorage.WebDavStorage(App.Kp2a.CertificateErrorHandler);
|
||||
var connInfo = webdavStorage.SplitStringToConnectionInfo(defaultPath);
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.http_url).Text = connInfo.Url;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.http_user).Text = connInfo.Username;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.http_password).Text = connInfo.Password;
|
||||
|
||||
|
||||
}
|
||||
builder.SetView(dlgContents);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok,
|
||||
(sender, args) =>
|
||||
@@ -79,9 +103,9 @@ namespace keepass2android
|
||||
string user = dlgContents.FindViewById<EditText>(Resource.Id.http_user).Text;
|
||||
string password = dlgContents.FindViewById<EditText>(Resource.Id.http_password).Text;
|
||||
|
||||
string scheme = defaultPath.Substring(0, defaultPath.IndexOf("://", StringComparison.Ordinal));
|
||||
if (host.Contains("://") == false)
|
||||
host = scheme + "://" + host;
|
||||
string scheme = defaultPath.Substring(0, defaultPath.IndexOf(_schemeSeparator, StringComparison.Ordinal));
|
||||
if (host.Contains(_schemeSeparator) == false)
|
||||
host = scheme + _schemeSeparator + host;
|
||||
string httpPath = new Keepass2android.Javafilestorage.WebDavStorage(null).BuildFullPath(host, user,
|
||||
password);
|
||||
onStartBrowse(httpPath);
|
||||
@@ -96,12 +120,35 @@ namespace keepass2android
|
||||
#endif
|
||||
}
|
||||
|
||||
private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel)
|
||||
private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel, string defaultPath)
|
||||
{
|
||||
#if !NoNet
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.ftpcredentials, null);
|
||||
builder.SetView(dlgContents);
|
||||
if (!defaultPath.EndsWith(_schemeSeparator))
|
||||
{
|
||||
var connection = NetFtpFileStorage.ConnectionSettings.FromIoc(IOConnectionInfo.FromPath(defaultPath));
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.ftp_user).Text = connection.Username;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.ftp_password).Text = connection.Password;
|
||||
dlgContents.FindViewById<Spinner>(Resource.Id.ftp_encryption).SetSelection((int)connection.EncryptionMode);
|
||||
|
||||
var uri = NetFtpFileStorage.IocToUri(IOConnectionInfo.FromPath(defaultPath));
|
||||
string pathAndQuery = uri.PathAndQuery;
|
||||
|
||||
var host = uri.Host;
|
||||
var localPath = pathAndQuery;
|
||||
|
||||
|
||||
if (!uri.IsDefaultPort)
|
||||
{
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.ftp_port).Text = uri.Port.ToString();
|
||||
}
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.ftp_host).Text = host;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.ftp_initial_dir).Text = localPath;
|
||||
|
||||
|
||||
}
|
||||
builder.SetView(dlgContents);
|
||||
builder.SetPositiveButton(Android.Resource.String.Ok,
|
||||
(sender, args) =>
|
||||
{
|
||||
@@ -133,9 +180,9 @@ namespace keepass2android
|
||||
public void PerformManualFileSelect(string defaultPath)
|
||||
{
|
||||
if (defaultPath.StartsWith("sftp://"))
|
||||
ShowSftpDialog(_activity, ReturnFileOrStartFileChooser, ReturnCancel);
|
||||
ShowSftpDialog(_activity, ReturnFileOrStartFileChooser, ReturnCancel, defaultPath);
|
||||
else if ((defaultPath.StartsWith("ftp://")) || (defaultPath.StartsWith("ftps://")))
|
||||
ShowFtpDialog(_activity, ReturnFileOrStartFileChooser, ReturnCancel);
|
||||
ShowFtpDialog(_activity, ReturnFileOrStartFileChooser, ReturnCancel, defaultPath);
|
||||
else if ((defaultPath.StartsWith("http://")) || (defaultPath.StartsWith("https://")))
|
||||
ShowHttpDialog(_activity, ReturnFileOrStartFileChooser, ReturnCancel, defaultPath);
|
||||
else if (defaultPath.StartsWith("owncloud://"))
|
||||
@@ -169,9 +216,9 @@ namespace keepass2android
|
||||
string user = dlgContents.FindViewById<EditText>(Resource.Id.http_user).Text;
|
||||
string password = dlgContents.FindViewById<EditText>(Resource.Id.http_password).Text;
|
||||
|
||||
string scheme = defaultPath.Substring(defaultPath.IndexOf("://", StringComparison.Ordinal));
|
||||
if (host.Contains("://") == false)
|
||||
host = scheme + "://" + host;
|
||||
string scheme = defaultPath.Substring(defaultPath.IndexOf(_schemeSeparator, StringComparison.Ordinal));
|
||||
if (host.Contains(_schemeSeparator) == false)
|
||||
host = scheme + _schemeSeparator + host;
|
||||
string httpPath = new Keepass2android.Javafilestorage.WebDavStorage(null).BuildFullPath(WebDavFileStorage.Owncloud2Webdav(host), user,
|
||||
password);
|
||||
onStartBrowse(httpPath);
|
||||
@@ -190,10 +237,10 @@ namespace keepass2android
|
||||
private bool ReturnFileOrStartFileChooser(string filename)
|
||||
{
|
||||
string filenameWithoutProt = filename;
|
||||
if (filenameWithoutProt.Contains("://"))
|
||||
if (filenameWithoutProt.Contains(_schemeSeparator))
|
||||
{
|
||||
filenameWithoutProt =
|
||||
filenameWithoutProt.Substring(filenameWithoutProt.IndexOf("://", StringComparison.Ordinal) + 3);
|
||||
filenameWithoutProt.Substring(filenameWithoutProt.IndexOf(_schemeSeparator, StringComparison.Ordinal) + 3);
|
||||
}
|
||||
|
||||
int lastSlashPos = filenameWithoutProt.LastIndexOf('/');
|
||||
@@ -365,5 +412,13 @@ namespace keepass2android
|
||||
public event EventHandler OnCancel;
|
||||
|
||||
public event EventHandler<IOConnectionInfo> OnOpen;
|
||||
|
||||
public static bool CanEditIoc(IOConnectionInfo ioc)
|
||||
{
|
||||
return ioc.Path.StartsWith("http")
|
||||
|| ioc.Path.StartsWith("ftp")
|
||||
|| ioc.Path.StartsWith("sftp");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,8 +16,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text=""
|
||||
android:layout_weight="1"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:layout_weight="1"
|
||||
android:inputType="textWebEmailAddress"
|
||||
android:hint="@string/hint_sftp_host" />
|
||||
<TextView
|
||||
android:id="@+id/portsep"
|
||||
@@ -62,6 +62,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="4dip"
|
||||
android:layout_marginTop="4dip"
|
||||
android:inputType="textWebEmailAddress"
|
||||
android:text="@string/initial_directory" />
|
||||
<EditText
|
||||
android:id="@+id/ftp_initial_dir"
|
||||
|
@@ -17,7 +17,7 @@
|
||||
android:singleLine="true"
|
||||
android:layout_weight="1"
|
||||
android:text=""
|
||||
android:inputType="textNoSuggestions"
|
||||
android:inputType="textWebEmailAddress"
|
||||
android:hint="@string/hint_http_url" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@@ -16,7 +16,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_weight="1"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:inputType="textWebEmailAddress"
|
||||
android:hint="@string/hint_sftp_host" />
|
||||
<TextView
|
||||
android:id="@+id/portsep"
|
||||
@@ -58,6 +58,7 @@
|
||||
android:id="@+id/sftp_initial_dir"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textWebEmailAddress"
|
||||
android:singleLine="true"
|
||||
android:text="/"
|
||||
/>
|
||||
|
@@ -611,11 +611,7 @@ namespace keepass2android
|
||||
{
|
||||
get { return new CertificateErrorHandlerImpl(this); }
|
||||
}
|
||||
public bool CanEditIoc(IOConnectionInfo ioc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class CertificateErrorHandlerImpl : Java.Lang.Object, Keepass2android.Javafilestorage.ICertificateErrorHandler
|
||||
{
|
||||
|
@@ -72,8 +72,9 @@ namespace keepass2android
|
||||
|
||||
internal AppTask AppTask;
|
||||
private const int RequestCodeSelectIoc = 456;
|
||||
private const int RequestCodeEditIoc = 457;
|
||||
|
||||
public const string NoForwardToPasswordActivity = "NoForwardToPasswordActivity";
|
||||
public const string NoForwardToPasswordActivity = "NoForwardToPasswordActivity";
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
@@ -204,14 +205,16 @@ namespace keepass2android
|
||||
class MyCursorAdapter: CursorAdapter
|
||||
{
|
||||
private LayoutInflater cursorInflater;
|
||||
private readonly FileSelectActivity _activity;
|
||||
private IKp2aApp _app;
|
||||
|
||||
public MyCursorAdapter(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
|
||||
public MyCursorAdapter(Context context, ICursor c, IKp2aApp app) : base(context, c)
|
||||
public MyCursorAdapter(FileSelectActivity activity, ICursor c, IKp2aApp app) : base(activity, c)
|
||||
{
|
||||
_activity = activity;
|
||||
_app = app;
|
||||
}
|
||||
|
||||
@@ -258,13 +261,13 @@ namespace keepass2android
|
||||
|
||||
String filename = (string)textView.Tag;
|
||||
IOConnectionInfo ioc = new IOConnectionInfo { Path = filename };
|
||||
if (_app.CanEditIoc(ioc))
|
||||
if (FileSelectHelper.CanEditIoc(ioc))
|
||||
{
|
||||
popupMenu.Menu.Add(0, edit, 0, context.GetString(Resource.String.edit)).SetIcon(Resource.Drawable.ic_menu_edit_grey);
|
||||
}
|
||||
|
||||
|
||||
popupMenu.MenuItemClick += delegate (object sender2, PopupMenu.MenuItemClickEventArgs args2)
|
||||
popupMenu.MenuItemClick += delegate(object sender2, PopupMenu.MenuItemClickEventArgs args2)
|
||||
{
|
||||
if (args2.Item.ItemId == remove)
|
||||
{
|
||||
@@ -272,6 +275,16 @@ namespace keepass2android
|
||||
|
||||
cursor.Requery();
|
||||
}
|
||||
if (args2.Item.ItemId == edit)
|
||||
{
|
||||
var fsh = new FileSelectHelper(_activity, false, RequestCodeEditIoc);
|
||||
fsh.OnOpen += (o, newConnectionInfo) =>
|
||||
{
|
||||
_activity.EditFileEntry(filename, newConnectionInfo);
|
||||
};
|
||||
fsh.PerformManualFileSelect(filename);
|
||||
|
||||
}
|
||||
};
|
||||
popupMenu.Show();
|
||||
});
|
||||
@@ -279,8 +292,19 @@ namespace keepass2android
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void EditFileEntry(string filename, IOConnectionInfo newConnectionInfo)
|
||||
{
|
||||
_dbHelper.CreateFile(newConnectionInfo, _dbHelper.GetKeyFileForFile(filename));
|
||||
_dbHelper.DeleteFile(filename);
|
||||
|
||||
LaunchPasswordActivityForIoc(newConnectionInfo);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void FillData()
|
||||
{
|
||||
@@ -382,8 +406,15 @@ namespace keepass2android
|
||||
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
||||
LaunchPasswordActivityForIoc(ioc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((resultCode == Result.Ok) && (requestCode == RequestCodeEditIoc))
|
||||
{
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
|
||||
LaunchPasswordActivityForIoc(IOConnectionInfo.FromPath(filename));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
|
Reference in New Issue
Block a user