mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-25 10:42:17 -05:00
* check if entered URI looks like a directory (not a file) and issue warning in SelectStorageLocationActivity
* check if URI is directory and refuse to delete in IOConnection
This commit is contained in:
parent
6c3795ff1a
commit
ed15af3f8f
@ -519,6 +519,11 @@ namespace KeePassLib.Serialization
|
|||||||
{
|
{
|
||||||
RaiseIOAccessPreEvent(ioc, IOAccessType.Delete);
|
RaiseIOAccessPreEvent(ioc, IOAccessType.Delete);
|
||||||
|
|
||||||
|
//in case a user entered a directory instead of a filename, make sure we're never
|
||||||
|
//deleting their whole WebDAV/FTP content
|
||||||
|
if (ioc.Path.EndsWith("/"))
|
||||||
|
throw new IOException("Delete file does not expect directory URIs.");
|
||||||
|
|
||||||
if(ioc.IsLocalFile()) { File.Delete(ioc.Path); return; }
|
if(ioc.IsLocalFile()) { File.Delete(ioc.Path); return; }
|
||||||
|
|
||||||
#if (!KeePassLibSD && !KeePassRT)
|
#if (!KeePassLibSD && !KeePassRT)
|
||||||
|
@ -9,7 +9,10 @@ using KeePassLib.Serialization;
|
|||||||
|
|
||||||
namespace keepass2android.Io
|
namespace keepass2android.Io
|
||||||
{
|
{
|
||||||
//TODOC,TOTEST, TODO: unimplemented methods?
|
/** FileStorage to work with content URIs
|
||||||
|
* Supports both "old" system where data is available only temporarily as
|
||||||
|
* well as the SAF system. Assumes that persistable permissions are "taken" by
|
||||||
|
* the activity which receives OnActivityResult from the system file picker.*/
|
||||||
public class AndroidContentStorage: IFileStorage
|
public class AndroidContentStorage: IFileStorage
|
||||||
{
|
{
|
||||||
private readonly Context _ctx;
|
private readonly Context _ctx;
|
||||||
@ -135,10 +138,12 @@ namespace keepass2android.Io
|
|||||||
private bool TryGetDisplayName(IOConnectionInfo ioc, ref string displayName)
|
private bool TryGetDisplayName(IOConnectionInfo ioc, ref string displayName)
|
||||||
{
|
{
|
||||||
var uri = Android.Net.Uri.Parse(ioc.Path);
|
var uri = Android.Net.Uri.Parse(ioc.Path);
|
||||||
var cursor = _ctx.ContentResolver.Query(uri, null, null, null, null, null);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var cursor = _ctx.ContentResolver.Query(uri, null, null, null, null, null);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
if (cursor != null && cursor.MoveToFirst())
|
if (cursor != null && cursor.MoveToFirst())
|
||||||
{
|
{
|
||||||
displayName = cursor.GetString(cursor.GetColumnIndex(OpenableColumns.DisplayName));
|
displayName = cursor.GetString(cursor.GetColumnIndex(OpenableColumns.DisplayName));
|
||||||
@ -156,6 +161,16 @@ namespace keepass2android.Io
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Kp2aLog.Log(e.ToString());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CreateFilePath(string parent, string newFilename)
|
public string CreateFilePath(string parent, string newFilename)
|
||||||
|
@ -258,21 +258,31 @@ namespace keepass2android
|
|||||||
|
|
||||||
protected abstract void StartFileChooser(string path, int requestCode, bool isForSave);
|
protected abstract void StartFileChooser(string path, int requestCode, bool isForSave);
|
||||||
|
|
||||||
protected bool OnOpenButton(String fileName, int requestCode)
|
protected bool OnOpenButton(string fileName, int requestCode, Action dismissDialog)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
IOConnectionInfo ioc = new IOConnectionInfo
|
IOConnectionInfo ioc = new IOConnectionInfo
|
||||||
{
|
{
|
||||||
Path = fileName
|
Path = fileName
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int lastSlashPos = fileName.LastIndexOf('/');
|
||||||
|
int lastDotPos = fileName.LastIndexOf('.');
|
||||||
|
if (lastSlashPos >= lastDotPos) //no dot after last slash or == in case neither / nor .
|
||||||
|
{
|
||||||
|
ShowFilenameWarning(fileName, () => { IocSelected(ioc, requestCode); dismissDialog(); }, () => { /* don't do anything, leave dialog open, let user try again*/ });
|
||||||
|
//signal that the dialog should be kept open
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IocSelected(ioc, requestCode);
|
IocSelected(ioc, requestCode);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void ShowFilenameWarning(string fileName, Action onUserWantsToContinue, Action onUserWantsToCorrect);
|
||||||
|
|
||||||
|
|
||||||
protected virtual void CopyFile(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc)
|
protected virtual void CopyFile(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc)
|
||||||
{
|
{
|
||||||
|
@ -14,12 +14,13 @@
|
|||||||
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
|
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
|
||||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||||
<TargetFrameworkVersion>v4.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.4</TargetFrameworkVersion>
|
||||||
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
|
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
|
||||||
<AndroidStoreUncompressedFileExtensions />
|
<AndroidStoreUncompressedFileExtensions />
|
||||||
<MandroidI18n />
|
<MandroidI18n />
|
||||||
<JavaMaximumHeapSize />
|
<JavaMaximumHeapSize />
|
||||||
<JavaOptions />
|
<JavaOptions />
|
||||||
|
<AndroidUseLatestPlatformSdk />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@ -101,7 +102,7 @@
|
|||||||
<Name>KeePassLib2Android</Name>
|
<Name>KeePassLib2Android</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\Kp2aBusinessLogic\Kp2aBusinessLogic.csproj">
|
<ProjectReference Include="..\Kp2aBusinessLogic\Kp2aBusinessLogic.csproj">
|
||||||
<Project>{53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}</Project>
|
<Project>{53a9cb7f-6553-4bc0-b56b-9410bb2e59aa}</Project>
|
||||||
<Name>Kp2aBusinessLogic</Name>
|
<Name>Kp2aBusinessLogic</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\KP2AKdbLibraryBinding\KP2AKdbLibraryBinding.csproj">
|
<ProjectReference Include="..\KP2AKdbLibraryBinding\KP2AKdbLibraryBinding.csproj">
|
||||||
|
@ -23,7 +23,7 @@ namespace Kp2aUnitTests
|
|||||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdb1WithKeyfileOnly"));
|
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdb1WithKeyfileOnly"));
|
||||||
|
|
||||||
|
|
||||||
//runner.AddTests(new List<Type> { typeof(TestSelectStorageLocation) });
|
runner.AddTests(new List<Type> { typeof(TestSelectStorageLocation) });
|
||||||
//runner.AddTests(new List<Type> { typeof(TestSynchronizeCachedDatabase)});
|
//runner.AddTests(new List<Type> { typeof(TestSynchronizeCachedDatabase)});
|
||||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadErrorWithCertificateTrustFailure"));
|
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadErrorWithCertificateTrustFailure"));
|
||||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadWithAcceptedCertificateTrustFailure"));
|
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadWithAcceptedCertificateTrustFailure"));
|
||||||
@ -36,7 +36,7 @@ namespace Kp2aUnitTests
|
|||||||
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadAndSave_TestIdenticalFiles_kdb"));
|
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestLoadAndSave_TestIdenticalFiles_kdb"));
|
||||||
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestCreateSaveAndLoad_TestIdenticalFiles_kdb"));
|
//runner.AddTests(typeof(TestSaveDb).GetMethod("TestCreateSaveAndLoad_TestIdenticalFiles_kdb"));
|
||||||
|
|
||||||
runner.AddTests(typeof(TestSaveDb).GetMethod("TestSaveTwice_kdb"));
|
// runner.AddTests(typeof(TestSaveDb).GetMethod("TestSaveTwice_kdb"));
|
||||||
|
|
||||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadAndSaveFromRemote1And1Ftp"));
|
//runner.AddTests(typeof(TestLoadDb).GetMethod("LoadAndSaveFromRemote1And1Ftp"));
|
||||||
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdbpWithPasswordOnly"));
|
//runner.AddTests(typeof(TestLoadDb).GetMethod("TestLoadKdbpWithPasswordOnly"));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
|
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" />
|
||||||
<application></application>
|
<application></application>
|
||||||
</manifest>
|
</manifest>
|
@ -225,6 +225,12 @@ namespace Kp2aUnitTests
|
|||||||
_userAction = new SelectFileAction(isForSave, browseRequestCode, protocolId, this);
|
_userAction = new SelectFileAction(isForSave, browseRequestCode, protocolId, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ShowFilenameWarning(string fileName, Action onUserWantsToContinue, Action onUserWantsToCorrect)
|
||||||
|
{
|
||||||
|
_userAction = new ShowAlertDialogAction("filenameWarning", delegate { onUserWantsToContinue(); },
|
||||||
|
delegate { onUserWantsToCorrect(); });
|
||||||
|
}
|
||||||
|
|
||||||
public void HandleActivityResult(int requestCode, Result resultCode, Intent data)
|
public void HandleActivityResult(int requestCode, Result resultCode, Intent data)
|
||||||
{
|
{
|
||||||
OnActivityResult(requestCode, resultCode, data);
|
OnActivityResult(requestCode, resultCode, data);
|
||||||
@ -281,7 +287,7 @@ namespace Kp2aUnitTests
|
|||||||
|
|
||||||
private void PressOpenButton(string path, int browseRequestCode)
|
private void PressOpenButton(string path, int browseRequestCode)
|
||||||
{
|
{
|
||||||
OnOpenButton(path, browseRequestCode);
|
OnOpenButton(path, browseRequestCode, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -523,6 +529,48 @@ namespace Kp2aUnitTests
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestManualSelectWithDirectoryCancel()
|
||||||
|
{
|
||||||
|
var testee = CreateTestee();
|
||||||
|
var action = (TestControllableSelectStorageLocationActivity.FileStorageSelectionAction)testee._userAction;
|
||||||
|
action.ReturnProtocol("ftp");
|
||||||
|
|
||||||
|
Assert.IsNull(testee._result); //no result yet
|
||||||
|
|
||||||
|
var action2 = (TestControllableSelectStorageLocationActivity.SelectFileAction)testee._userAction;
|
||||||
|
string path = "ftp://crocoll.net/";
|
||||||
|
action2.PerformManualFileSelect(path);
|
||||||
|
|
||||||
|
Assert.IsNull(testee._result);
|
||||||
|
|
||||||
|
var action3 = (TestControllableSelectStorageLocationActivity.ShowAlertDialogAction) testee._userAction;
|
||||||
|
action3.Ok();
|
||||||
|
Assert.IsTrue((bool)testee._result);
|
||||||
|
Assert.AreEqual(testee._resultIoc.Path, path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestManualSelectWithDirectory()
|
||||||
|
{
|
||||||
|
var testee = CreateTestee();
|
||||||
|
var action = (TestControllableSelectStorageLocationActivity.FileStorageSelectionAction)testee._userAction;
|
||||||
|
action.ReturnProtocol("ftp");
|
||||||
|
|
||||||
|
Assert.IsNull(testee._result); //no result yet
|
||||||
|
|
||||||
|
var action2 = (TestControllableSelectStorageLocationActivity.SelectFileAction)testee._userAction;
|
||||||
|
string path = "ftp://crocoll.net/";
|
||||||
|
action2.PerformManualFileSelect(path);
|
||||||
|
|
||||||
|
Assert.IsNull(testee._result);
|
||||||
|
|
||||||
|
var action3 = (TestControllableSelectStorageLocationActivity.ShowAlertDialogAction)testee._userAction;
|
||||||
|
action3.Cancel();
|
||||||
|
|
||||||
|
}
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestCancelManualSelect()
|
public void TestCancelManualSelect()
|
||||||
{
|
{
|
||||||
|
@ -441,7 +441,7 @@ namespace keepass2android
|
|||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OnCreateButton(string filename)
|
private bool OnCreateButton(string filename, Dialog dialog)
|
||||||
{
|
{
|
||||||
// Make sure file name exists
|
// Make sure file name exists
|
||||||
if (filename.Length == 0)
|
if (filename.Length == 0)
|
||||||
|
@ -144,7 +144,7 @@ namespace keepass2android
|
|||||||
get { return 0; }
|
get { return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OnCreateButton(string filename)
|
private bool OnCreateButton(string filename, Dialog dialog)
|
||||||
{
|
{
|
||||||
if (filename.Length == 0)
|
if (filename.Length == 0)
|
||||||
{
|
{
|
||||||
|
@ -530,6 +530,9 @@
|
|||||||
|
|
||||||
<string name="PreviewWarning">Please note! This is a preview release and might come with some flaws! If you experience *anything* unexpected, please let me know (on Codeplex or by email).</string>
|
<string name="PreviewWarning">Please note! This is a preview release and might come with some flaws! If you experience *anything* unexpected, please let me know (on Codeplex or by email).</string>
|
||||||
|
|
||||||
|
<string name="Continue">Continue</string>
|
||||||
|
<string name="NoFilenameWarning">The URI you have entered does not look like a filename. Are you sure this is a valid file?</string>
|
||||||
|
|
||||||
<string name="ChangeLog_0_9_7b">
|
<string name="ChangeLog_0_9_7b">
|
||||||
Version 0.9.7b\n
|
Version 0.9.7b\n
|
||||||
* updated translations\n
|
* updated translations\n
|
||||||
|
@ -100,9 +100,9 @@ namespace keepass2android
|
|||||||
if (defaultPath.StartsWith("sftp://"))
|
if (defaultPath.StartsWith("sftp://"))
|
||||||
Util.ShowSftpDialog(this, filename => OnReceivedSftpData(filename, browseRequestCode, isForSave), ReturnCancel);
|
Util.ShowSftpDialog(this, filename => OnReceivedSftpData(filename, browseRequestCode, isForSave), ReturnCancel);
|
||||||
else
|
else
|
||||||
//todo oncreate nur wenn for save?
|
Util.ShowFilenameDialog(this,
|
||||||
Util.ShowFilenameDialog(this, filename => OnOpenButton(filename, browseRequestCode),
|
!isForSave ? delegate(string filename, Dialog dialog) { return OnOpenButton(filename, browseRequestCode, dialog.Dismiss); } : (Func<string, Dialog, bool>) null,
|
||||||
filename => OnOpenButton(filename, browseRequestCode),
|
isForSave ? delegate(string filename, Dialog dialog) { return OnOpenButton(filename, browseRequestCode, dialog.Dismiss); } : (Func<string, Dialog, bool>) null,
|
||||||
ReturnCancel, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
ReturnCancel, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||||
browseRequestCode);
|
browseRequestCode);
|
||||||
});
|
});
|
||||||
@ -224,7 +224,17 @@ namespace keepass2android
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ShowFilenameWarning(string fileName, Action onUserWantsToContinue, Action onUserWantsToCorrect)
|
||||||
|
{
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.SetPositiveButton(Resource.String.Continue, delegate { onUserWantsToContinue(); } )
|
||||||
|
.SetMessage(Resource.String.NoFilenameWarning)
|
||||||
|
.SetCancelable(false)
|
||||||
|
.SetNegativeButton(Android.Resource.String.Cancel, delegate { onUserWantsToCorrect(); })
|
||||||
|
.Create()
|
||||||
|
.Show();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void OnDismiss(IDialogInterface dialog)
|
public void OnDismiss(IDialogInterface dialog)
|
||||||
|
@ -335,7 +335,7 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowFilenameDialog(Activity activity, FileSelectedHandler onOpen, FileSelectedHandler onCreate, Action onCancel, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
|
public static void ShowFilenameDialog(Activity activity, Func<string, Dialog, bool> onOpen, Func<string, Dialog, bool> onCreate, Action onCancel, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
|
||||||
{
|
{
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.SetView(activity.LayoutInflater.Inflate(Resource.Layout.file_selection_filename, null));
|
builder.SetView(activity.LayoutInflater.Inflate(Resource.Layout.file_selection_filename, null));
|
||||||
@ -362,7 +362,7 @@ namespace keepass2android
|
|||||||
openButton.Click += (sender, args) =>
|
openButton.Click += (sender, args) =>
|
||||||
{
|
{
|
||||||
String fileName = ((EditText) dialog.FindViewById(Resource.Id.file_filename)).Text;
|
String fileName = ((EditText) dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||||
if (onOpen(fileName))
|
if (onOpen(fileName, dialog))
|
||||||
dialog.Dismiss();
|
dialog.Dismiss();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -371,7 +371,7 @@ namespace keepass2android
|
|||||||
createButton.Click += (sender, args) =>
|
createButton.Click += (sender, args) =>
|
||||||
{
|
{
|
||||||
String fileName = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
String fileName = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||||
if (onCreate(fileName))
|
if (onCreate(fileName, dialog))
|
||||||
dialog.Dismiss();
|
dialog.Dismiss();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user