implemented editing of connection settings for ftp/sftp/webdav, includes changing password. Closes #27

This commit is contained in:
Philipp Crocoll
2018-04-06 06:06:03 +02:00
parent de18aefd7b
commit cdbb492f2c
12 changed files with 137 additions and 52 deletions

View File

@@ -112,6 +112,5 @@ namespace keepass2android
#if !NoNet
ICertificateErrorHandler CertificateErrorHandler { get; }
#endif
bool CanEditIoc(IOConnectionInfo ioc);
}
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -1,4 +1,4 @@
package keepass2android.javafilestorage.webdav;
package keepass2android.javafilestorage;
/**
* Created by Philipp on 22.11.2016.

View File

@@ -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

View File

@@ -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();

View File

@@ -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");
}
}
}

View File

@@ -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"

View File

@@ -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>

View File

@@ -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="/"
/>

View File

@@ -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
{

View File

@@ -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()
{