mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-15 05:55:05 -05:00
implement GUI for NetFtpStorage
store user/password for ftp connection in "path" string for compatiblity with file chooser
This commit is contained in:
parent
fe3da55e0d
commit
113d693f7a
@ -87,22 +87,45 @@ namespace keepass2android.Io
|
|||||||
{
|
{
|
||||||
public FtpEncryptionMode EncryptionMode {get; set; }
|
public FtpEncryptionMode EncryptionMode {get; set; }
|
||||||
|
|
||||||
|
public string Username
|
||||||
|
{
|
||||||
|
get;set;
|
||||||
|
}
|
||||||
|
public string Password
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public static ConnectionSettings FromIoc(IOConnectionInfo ioc)
|
public static ConnectionSettings FromIoc(IOConnectionInfo ioc)
|
||||||
{
|
{
|
||||||
string path = ioc.Path;
|
string path = ioc.Path;
|
||||||
int schemeLength = path.IndexOf("://", StringComparison.Ordinal);
|
int schemeLength = path.IndexOf("://", StringComparison.Ordinal);
|
||||||
path = path.Substring(schemeLength + 3);
|
path = path.Substring(schemeLength + 3);
|
||||||
string settings = path.Substring(0, path.IndexOf("/", StringComparison.Ordinal));
|
string settings = path.Substring(0, path.IndexOf(SettingsPostFix, StringComparison.Ordinal));
|
||||||
|
if (!settings.StartsWith(SettingsPrefix))
|
||||||
|
throw new Exception("unexpected settings in path");
|
||||||
|
settings = settings.Substring(SettingsPrefix.Length);
|
||||||
|
var tokens = settings.Split(Separator);
|
||||||
return new ConnectionSettings()
|
return new ConnectionSettings()
|
||||||
{
|
{
|
||||||
EncryptionMode = (FtpEncryptionMode) int.Parse(settings)
|
EncryptionMode = (FtpEncryptionMode) int.Parse(tokens[2]),
|
||||||
|
Username = tokens[0],
|
||||||
|
Password = tokens[1]
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToString()
|
public const string SettingsPrefix = "SET";
|
||||||
|
public const string SettingsPostFix = "%";
|
||||||
|
public const char Separator = ':';
|
||||||
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return ((int) EncryptionMode).ToString();
|
return SettingsPrefix +
|
||||||
|
System.Net.WebUtility.UrlEncode(Username) + Separator +
|
||||||
|
WebUtility.UrlEncode(Password) + Separator +
|
||||||
|
(int) EncryptionMode;
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +143,10 @@ namespace keepass2android.Io
|
|||||||
|
|
||||||
public IEnumerable<string> SupportedProtocols
|
public IEnumerable<string> SupportedProtocols
|
||||||
{
|
{
|
||||||
get { yield return "ftp"; }
|
get
|
||||||
|
{
|
||||||
|
yield return "ftp";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Delete(IOConnectionInfo ioc)
|
public void Delete(IOConnectionInfo ioc)
|
||||||
@ -160,9 +186,11 @@ namespace keepass2android.Io
|
|||||||
|
|
||||||
internal FtpClient GetClient(IOConnectionInfo ioc, bool enableCloneClient = true)
|
internal FtpClient GetClient(IOConnectionInfo ioc, bool enableCloneClient = true)
|
||||||
{
|
{
|
||||||
|
var settings = ConnectionSettings.FromIoc(ioc);
|
||||||
|
|
||||||
FtpClient client = new RetryConnectFtpClient();
|
FtpClient client = new RetryConnectFtpClient();
|
||||||
if ((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
|
if ((settings.Username.Length > 0) || (settings.Password.Length > 0))
|
||||||
client.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
|
client.Credentials = new NetworkCredential(settings.Username, settings.Password);
|
||||||
else
|
else
|
||||||
client.Credentials = new NetworkCredential("anonymous", ""); //TODO TEST
|
client.Credentials = new NetworkCredential("anonymous", ""); //TODO TEST
|
||||||
|
|
||||||
@ -176,7 +204,7 @@ namespace keepass2android.Io
|
|||||||
args.Accept = _app.CertificateValidationCallback(control, args.Certificate, args.Chain, args.PolicyErrors);
|
args.Accept = _app.CertificateValidationCallback(control, args.Certificate, args.Chain, args.PolicyErrors);
|
||||||
};
|
};
|
||||||
|
|
||||||
client.EncryptionMode = ConnectionSettings.FromIoc(ioc).EncryptionMode;
|
client.EncryptionMode = settings.EncryptionMode;
|
||||||
|
|
||||||
client.Connect();
|
client.Connect();
|
||||||
return client;
|
return client;
|
||||||
@ -192,7 +220,7 @@ namespace keepass2android.Io
|
|||||||
int schemeLength = path.IndexOf("://", StringComparison.Ordinal);
|
int schemeLength = path.IndexOf("://", StringComparison.Ordinal);
|
||||||
string scheme = path.Substring(0, schemeLength);
|
string scheme = path.Substring(0, schemeLength);
|
||||||
path = path.Substring(schemeLength + 3);
|
path = path.Substring(schemeLength + 3);
|
||||||
string settings = path.Substring(0, path.IndexOf("/", StringComparison.Ordinal));
|
string settings = path.Substring(0, path.IndexOf(ConnectionSettings.SettingsPostFix, StringComparison.Ordinal));
|
||||||
path = path.Substring(settings.Length + 1);
|
path = path.Substring(settings.Length + 1);
|
||||||
return new Uri(scheme + "://" + path);
|
return new Uri(scheme + "://" + path);
|
||||||
}
|
}
|
||||||
@ -203,10 +231,10 @@ namespace keepass2android.Io
|
|||||||
int schemeLength = basePath.IndexOf("://", StringComparison.Ordinal);
|
int schemeLength = basePath.IndexOf("://", StringComparison.Ordinal);
|
||||||
string scheme = basePath.Substring(0, schemeLength);
|
string scheme = basePath.Substring(0, schemeLength);
|
||||||
basePath = basePath.Substring(schemeLength + 3);
|
basePath = basePath.Substring(schemeLength + 3);
|
||||||
string baseSettings = basePath.Substring(0, basePath.IndexOf("/", StringComparison.Ordinal));
|
string baseSettings = basePath.Substring(0, basePath.IndexOf(ConnectionSettings.SettingsPostFix, StringComparison.Ordinal));
|
||||||
basePath = basePath.Substring(baseSettings.Length+1);
|
basePath = basePath.Substring(baseSettings.Length+1);
|
||||||
string baseHost = basePath.Substring(0, basePath.IndexOf("/", StringComparison.Ordinal));
|
string baseHost = basePath.Substring(0, basePath.IndexOf("/", StringComparison.Ordinal));
|
||||||
return scheme + "://" + baseSettings + "/" + baseHost + uri.AbsolutePath; //TODO does this contain Query?
|
return scheme + "://" + baseSettings + ConnectionSettings.SettingsPostFix + baseHost + uri.AbsolutePath; //TODO does this contain Query?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -261,7 +289,7 @@ namespace keepass2android.Io
|
|||||||
|
|
||||||
public bool RequiresCredentials(IOConnectionInfo ioc)
|
public bool RequiresCredentials(IOConnectionInfo ioc)
|
||||||
{
|
{
|
||||||
return ioc.CredSaveMode != IOCredSaveMode.SaveCred;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
|
public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
|
||||||
@ -340,16 +368,19 @@ namespace keepass2android.Io
|
|||||||
|
|
||||||
var uri = IocPathToUri(ioc.Path);
|
var uri = IocPathToUri(ioc.Path);
|
||||||
string path = uri.PathAndQuery;
|
string path = uri.PathAndQuery;
|
||||||
return new FileDescription()
|
if (!client.FileExists(path) && (!client.DirectoryExists(path)))
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
var fileDesc = new FileDescription()
|
||||||
{
|
{
|
||||||
CanRead = true,
|
CanRead = true,
|
||||||
CanWrite = true,
|
CanWrite = true,
|
||||||
Path = ioc.Path,
|
Path = ioc.Path,
|
||||||
LastModified = client.GetModifiedTime(path),
|
LastModified = client.GetModifiedTime(path),
|
||||||
SizeInBytes = client.GetFileSize(path),
|
SizeInBytes = client.GetFileSize(path),
|
||||||
DisplayName = UrlUtil.GetFileName(path),
|
DisplayName = UrlUtil.GetFileName(path)
|
||||||
IsDirectory = false
|
|
||||||
};
|
};
|
||||||
|
fileDesc.IsDirectory = fileDesc.Path.EndsWith("/");
|
||||||
|
return fileDesc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FtpCommandException ex)
|
catch (FtpCommandException ex)
|
||||||
@ -457,6 +488,34 @@ namespace keepass2android.Io
|
|||||||
throw ConvertException(ex);
|
throw ConvertException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int GetDefaultPort(FtpEncryptionMode encryption)
|
||||||
|
{
|
||||||
|
return new FtpClient() { EncryptionMode = encryption}.Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BuildFullPath(string host, int port, string initialPath, string user, string password, FtpEncryptionMode encryption)
|
||||||
|
{
|
||||||
|
var connectionSettings = new ConnectionSettings()
|
||||||
|
{
|
||||||
|
EncryptionMode = encryption,
|
||||||
|
Username = user,
|
||||||
|
Password = password
|
||||||
|
};
|
||||||
|
|
||||||
|
string scheme = "ftp";
|
||||||
|
|
||||||
|
string fullPath = scheme + "://" + connectionSettings.ToString() + ConnectionSettings.SettingsPostFix + host;
|
||||||
|
if (port != GetDefaultPort(encryption))
|
||||||
|
fullPath += ":" + port;
|
||||||
|
|
||||||
|
if (!initialPath.StartsWith("/"))
|
||||||
|
initialPath = "/" + initialPath;
|
||||||
|
fullPath += initialPath;
|
||||||
|
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TransactedWrite : IWriteTransaction
|
public class TransactedWrite : IWriteTransaction
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.FtpClient;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using Android.App;
|
using Android.App;
|
||||||
@ -62,13 +63,49 @@ namespace keepass2android
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel)
|
||||||
|
{
|
||||||
|
#if !NoNet
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
|
View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.ftpcredentials, null);
|
||||||
|
builder.SetView(dlgContents);
|
||||||
|
builder.SetPositiveButton(Android.Resource.String.Ok,
|
||||||
|
(sender, args) =>
|
||||||
|
{
|
||||||
|
string host = dlgContents.FindViewById<EditText>(Resource.Id.ftp_host).Text;
|
||||||
|
string portText = dlgContents.FindViewById<EditText>(Resource.Id.ftp_port).Text;
|
||||||
|
FtpEncryptionMode encryption =
|
||||||
|
(FtpEncryptionMode) dlgContents.FindViewById<Spinner>(Resource.Id.ftp_encryption).SelectedItemPosition;
|
||||||
|
int port = NetFtpFileStorage.GetDefaultPort(encryption);
|
||||||
|
if (!string.IsNullOrEmpty(portText))
|
||||||
|
int.TryParse(portText, out port);
|
||||||
|
string user = dlgContents.FindViewById<EditText>(Resource.Id.ftp_user).Text;
|
||||||
|
string password = dlgContents.FindViewById<EditText>(Resource.Id.ftp_password).Text;
|
||||||
|
string initialPath = dlgContents.FindViewById<EditText>(Resource.Id.ftp_initial_dir).Text;
|
||||||
|
string ftpPath = new NetFtpFileStorage(_activity, App.Kp2a).BuildFullPath(host, port, initialPath, user,
|
||||||
|
password, encryption);
|
||||||
|
onStartBrowse(ftpPath);
|
||||||
|
});
|
||||||
|
EventHandler<DialogClickEventArgs> evtH = new EventHandler<DialogClickEventArgs>((sender, e) => onCancel());
|
||||||
|
|
||||||
|
builder.SetNegativeButton(Android.Resource.String.Cancel, evtH);
|
||||||
|
builder.SetTitle(activity.GetString(Resource.String.enter_sftp_login_title));
|
||||||
|
Dialog dialog = builder.Create();
|
||||||
|
|
||||||
|
dialog.Show();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void PerformManualFileSelect(string defaultPath)
|
public void PerformManualFileSelect(string defaultPath)
|
||||||
{
|
{
|
||||||
if (defaultPath.StartsWith("sftp://"))
|
if (defaultPath.StartsWith("sftp://"))
|
||||||
ShowSftpDialog(_activity, StartFileChooser, ReturnCancel);
|
ShowSftpDialog(_activity, StartFileChooser, ReturnCancel);
|
||||||
|
else if ((defaultPath.StartsWith("ftp://")) || (defaultPath.StartsWith("ftps://")))
|
||||||
|
ShowFtpDialog(_activity, StartFileChooser, ReturnCancel);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Func<string, Dialog, bool> onOpen = (filename, dialog) => OnOpenButton(filename, dialog);
|
Func<string, Dialog, bool> onOpen = OnOpenButton;
|
||||||
Util.ShowFilenameDialog(_activity,
|
Util.ShowFilenameDialog(_activity,
|
||||||
!_isForSave ? onOpen : null,
|
!_isForSave ? onOpen : null,
|
||||||
_isForSave ? onOpen : null,
|
_isForSave ? onOpen : null,
|
||||||
@ -202,7 +239,6 @@ namespace keepass2android
|
|||||||
public bool StartFileChooser(string defaultPath)
|
public bool StartFileChooser(string defaultPath)
|
||||||
{
|
{
|
||||||
#if !EXCLUDE_FILECHOOSER
|
#if !EXCLUDE_FILECHOOSER
|
||||||
Kp2aLog.Log("FSA: defaultPath=" + defaultPath);
|
|
||||||
string fileProviderAuthority = FileChooserFileProvider.TheAuthority;
|
string fileProviderAuthority = FileChooserFileProvider.TheAuthority;
|
||||||
if (defaultPath.StartsWith("file://"))
|
if (defaultPath.StartsWith("file://"))
|
||||||
{
|
{
|
||||||
|
@ -40,46 +40,46 @@ namespace keepass2android
|
|||||||
|
|
||||||
private readonly FileStorageSelectionActivity _context;
|
private readonly FileStorageSelectionActivity _context;
|
||||||
|
|
||||||
private readonly List<string> _protocolIds = new List<string>();
|
private readonly List<string> _displayedProtocolIds = new List<string>();
|
||||||
|
|
||||||
public FileStorageAdapter(FileStorageSelectionActivity context)
|
public FileStorageAdapter(FileStorageSelectionActivity context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
//show all supported protocols:
|
//show all supported protocols:
|
||||||
foreach (IFileStorage fs in App.Kp2a.FileStorages)
|
foreach (IFileStorage fs in App.Kp2a.FileStorages)
|
||||||
_protocolIds.AddRange(fs.SupportedProtocols);
|
_displayedProtocolIds.AddRange(fs.SupportedProtocols);
|
||||||
|
|
||||||
//special handling for local files:
|
//special handling for local files:
|
||||||
if (!Util.IsKitKatOrLater)
|
if (!Util.IsKitKatOrLater)
|
||||||
{
|
{
|
||||||
//put file:// to the top
|
//put file:// to the top
|
||||||
_protocolIds.Remove("file");
|
_displayedProtocolIds.Remove("file");
|
||||||
_protocolIds.Insert(0, "file");
|
_displayedProtocolIds.Insert(0, "file");
|
||||||
|
|
||||||
//remove "content" (covered by androidget)
|
//remove "content" (covered by androidget)
|
||||||
//On KitKat, content is handled by AndroidContentStorage taking advantage
|
//On KitKat, content is handled by AndroidContentStorage taking advantage
|
||||||
//of persistable permissions and ACTION_OPEN/CREATE_DOCUMENT
|
//of persistable permissions and ACTION_OPEN/CREATE_DOCUMENT
|
||||||
_protocolIds.Remove("content");
|
_displayedProtocolIds.Remove("content");
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_protocolIds.Remove("file");
|
_displayedProtocolIds.Remove("file");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppGet, false))
|
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppGet, false))
|
||||||
_protocolIds.Add("androidget");
|
_displayedProtocolIds.Add("androidget");
|
||||||
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppSend, false))
|
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppSend, false))
|
||||||
_protocolIds.Add("androidsend");
|
_displayedProtocolIds.Add("androidsend");
|
||||||
#if NoNet
|
#if NoNet
|
||||||
_protocolIds.Add("kp2a");
|
_displayedProtocolIds.Add("kp2a");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Object GetItem(int position)
|
public override Object GetItem(int position)
|
||||||
{
|
{
|
||||||
return _protocolIds[position];
|
return _displayedProtocolIds[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long GetItemId(int position)
|
public override long GetItemId(int position)
|
||||||
@ -121,7 +121,7 @@ namespace keepass2android
|
|||||||
btn = (Button)convertView;
|
btn = (Button)convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
var protocolId = _protocolIds[position];
|
var protocolId = _displayedProtocolIds[position];
|
||||||
btn.Tag = protocolId;
|
btn.Tag = protocolId;
|
||||||
|
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
public override int Count
|
public override int Count
|
||||||
{
|
{
|
||||||
get { return _protocolIds.Count; }
|
get { return _displayedProtocolIds.Count; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
src/keepass2android/Resources/layout/ftpcredentials.xml
Normal file
75
src/keepass2android/Resources/layout/ftpcredentials.xml
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="12dip"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ftp_host"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="85.13.147.153"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:inputType="textNoSuggestions"
|
||||||
|
android:hint="@string/hint_sftp_host" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/portsep"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=":" />
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ftp_port"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="4"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:inputType="number"
|
||||||
|
android:text=""
|
||||||
|
android:hint="@string/hint_sftp_port" />
|
||||||
|
</LinearLayout>
|
||||||
|
<Spinner
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:entries="@array/ftp_encryption_modes"
|
||||||
|
android:id="@+id/ftp_encryption" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ftp_user"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="f00c530c"
|
||||||
|
android:hint="@string/hint_username" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ftp_password"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:text="2C4vsSt8MhNEaqv5"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:hint="@string/hint_pass" />
|
||||||
|
|
||||||
|
<TextView android:id="@+id/initial_dir"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="4dip"
|
||||||
|
android:layout_marginTop="4dip"
|
||||||
|
android:text="@string/initial_directory" />
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/ftp_initial_dir"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="/"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -944,8 +944,12 @@ Initial public release
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string name="design_title">Design</string>
|
<string name="design_title">Design</string>
|
||||||
|
<string-array name="ftp_encryption_modes">
|
||||||
<string-array name="cred_remember_modes">
|
<item>No encryption (FTP)</item>
|
||||||
|
<item>Implicit encryption (FTP over TLS, FTPS)</item>
|
||||||
|
<item>Explicit encryption (FTP over TLS, FTPS)</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="cred_remember_modes">
|
||||||
<item>Do not remember username and password</item>
|
<item>Do not remember username and password</item>
|
||||||
<item>Remember username only</item>
|
<item>Remember username only</item>
|
||||||
<item>Remember username and password</item>
|
<item>Remember username and password</item>
|
||||||
|
@ -319,36 +319,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
public delegate bool FileSelectedHandler(string filename);
|
public delegate bool FileSelectedHandler(string filename);
|
||||||
|
|
||||||
public static void ShowSftpDialog(Activity activity, FileSelectedHandler onStartBrowse, Action onCancel)
|
|
||||||
{
|
|
||||||
#if !EXCLUDE_JAVAFILESTORAGE && !NoNet
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
||||||
View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.sftpcredentials, null);
|
|
||||||
builder.SetView(dlgContents);
|
|
||||||
builder.SetPositiveButton(Android.Resource.String.Ok,
|
|
||||||
(sender, args) =>
|
|
||||||
{
|
|
||||||
string host = dlgContents.FindViewById<EditText>(Resource.Id.sftp_host).Text;
|
|
||||||
string portText = dlgContents.FindViewById<EditText>(Resource.Id.sftp_port).Text;
|
|
||||||
int port = Keepass2android.Javafilestorage.SftpStorage.DefaultSftpPort;
|
|
||||||
if (!string.IsNullOrEmpty(portText))
|
|
||||||
int.TryParse(portText, out port);
|
|
||||||
string user = dlgContents.FindViewById<EditText>(Resource.Id.sftp_user).Text;
|
|
||||||
string password = dlgContents.FindViewById<EditText>(Resource.Id.sftp_password).Text;
|
|
||||||
string initialPath = dlgContents.FindViewById<EditText>(Resource.Id.sftp_initial_dir).Text;
|
|
||||||
string sftpPath = new Keepass2android.Javafilestorage.SftpStorage().BuildFullPath(host, port, initialPath, user,
|
|
||||||
password);
|
|
||||||
onStartBrowse(sftpPath);
|
|
||||||
});
|
|
||||||
EventHandler<DialogClickEventArgs> evtH = new EventHandler<DialogClickEventArgs>( (sender, e) => onCancel());
|
|
||||||
|
|
||||||
builder.SetNegativeButton(Android.Resource.String.Cancel, evtH);
|
|
||||||
builder.SetTitle(activity.GetString(Resource.String.enter_sftp_login_title));
|
|
||||||
Dialog dialog = builder.Create();
|
|
||||||
|
|
||||||
dialog.Show();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DismissListener: Java.Lang.Object, IDialogInterfaceOnDismissListener
|
public class DismissListener: Java.Lang.Object, IDialogInterfaceOnDismissListener
|
||||||
{
|
{
|
||||||
|
@ -511,7 +511,7 @@ namespace keepass2android
|
|||||||
new GoogleDriveFileStorage(Application.Context, this),
|
new GoogleDriveFileStorage(Application.Context, this),
|
||||||
new SkyDriveFileStorage(Application.Context, this),
|
new SkyDriveFileStorage(Application.Context, this),
|
||||||
new SftpFileStorage(this),
|
new SftpFileStorage(this),
|
||||||
new NetFtpFileStorage(Application.Context),
|
new NetFtpFileStorage(Application.Context, this),
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
new LocalFileStorage(this)
|
new LocalFileStorage(this)
|
||||||
@ -684,7 +684,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
public void ClearOfflineCache()
|
public void ClearOfflineCache()
|
||||||
{
|
{
|
||||||
new CachingFileStorage(new BuiltInFileStorage(this), Application.Context.CacheDir.Path, this).ClearCache();
|
new CachingFileStorage(new LocalFileStorage(this), Application.Context.CacheDir.Path, this).ClearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IFileStorage GetFileStorage(string protocolId)
|
public IFileStorage GetFileStorage(string protocolId)
|
||||||
@ -700,7 +700,7 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (iocInfo.IsLocalFile())
|
if (iocInfo.IsLocalFile())
|
||||||
return new BuiltInFileStorage(this);
|
return new LocalFileStorage(this);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IFileStorage innerFileStorage = GetCloudFileStorage(iocInfo);
|
IFileStorage innerFileStorage = GetCloudFileStorage(iocInfo);
|
||||||
|
@ -66,7 +66,6 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Kp2aLog.Log("Provider.GetFileEntry " + filename);
|
|
||||||
return ConvertFileDescription(App.Kp2a.GetFileStorage(filename).GetFileDescription(ConvertPathToIoc(filename)));
|
return ConvertFileDescription(App.Kp2a.GetFileStorage(filename).GetFileDescription(ConvertPathToIoc(filename)));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -80,14 +79,12 @@ namespace keepass2android
|
|||||||
protected override void ListFiles(int taskId, string dirName, bool showHiddenFiles, int filterMode, int limit, string positiveRegex,
|
protected override void ListFiles(int taskId, string dirName, bool showHiddenFiles, int filterMode, int limit, string positiveRegex,
|
||||||
string negativeRegex, IList<FileEntry> fileList, bool[] hasMoreFiles)
|
string negativeRegex, IList<FileEntry> fileList, bool[] hasMoreFiles)
|
||||||
{
|
{
|
||||||
Kp2aLog.Log("Provider.ListFiles " + dirName);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dirContents = App.Kp2a.GetFileStorage(dirName).ListContents(ConvertPathToIoc(dirName));
|
var dirContents = App.Kp2a.GetFileStorage(dirName).ListContents(ConvertPathToIoc(dirName));
|
||||||
foreach (FileDescription e in dirContents)
|
foreach (FileDescription e in dirContents)
|
||||||
{
|
{
|
||||||
fileList.Add(ConvertFileDescription(e)
|
fileList.Add(ConvertFileDescription(e));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -678,7 +678,9 @@
|
|||||||
<AndroidResource Include="Resources\layout\QuickUnlock.xml">
|
<AndroidResource Include="Resources\layout\QuickUnlock.xml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
<AndroidResource Include="Resources\layout\url_credentials.xml" />
|
<AndroidResource Include="Resources\layout\url_credentials.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AndroidResource>
|
||||||
<AndroidResource Include="Resources\drawable\section_header.xml" />
|
<AndroidResource Include="Resources\drawable\section_header.xml" />
|
||||||
<AndroidResource Include="Resources\drawable\extra_string_header.xml" />
|
<AndroidResource Include="Resources\drawable\extra_string_header.xml" />
|
||||||
<AndroidResource Include="Resources\layout\entry_edit_section.xml">
|
<AndroidResource Include="Resources\layout\entry_edit_section.xml">
|
||||||
@ -771,6 +773,10 @@
|
|||||||
<Project>{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}</Project>
|
<Project>{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}</Project>
|
||||||
<Name>Kp2aKeyboardBinding</Name>
|
<Name>Kp2aKeyboardBinding</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\netftpandroid\System.Net.FtpClient\System.Net.FtpClient.Android.csproj">
|
||||||
|
<Project>{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}</Project>
|
||||||
|
<Name>System.Net.FtpClient.Android</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\PluginSdkBinding\PluginSdkBinding.csproj">
|
<ProjectReference Include="..\PluginSdkBinding\PluginSdkBinding.csproj">
|
||||||
<Project>{3DA3911E-36DE-465E-8F15-F1991B6437E5}</Project>
|
<Project>{3DA3911E-36DE-465E-8F15-F1991B6437E5}</Project>
|
||||||
<Name>PluginSdkBinding</Name>
|
<Name>PluginSdkBinding</Name>
|
||||||
@ -1683,6 +1689,11 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-mdpi\ic_fp_40px.png" />
|
<AndroidResource Include="Resources\drawable-mdpi\ic_fp_40px.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<AndroidResource Include="Resources\layout\ftpcredentials.xml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</AndroidResource>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||||
<Import Project="..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets')" />
|
<Import Project="..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets')" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
Loading…
Reference in New Issue
Block a user