Added option to export database

Fixed problem with native key transform
This commit is contained in:
Philipp Crocoll 2014-01-27 22:47:08 -08:00
parent d7109fc630
commit 2d53021f78
19 changed files with 5739 additions and 2177 deletions

View File

@ -20,7 +20,7 @@
<DebugType>full</DebugType>
<Optimize>False</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>

View File

@ -0,0 +1,119 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using KeePassLib;
using KeePassLib.Interfaces;
namespace KeePass.DataExchange
{
public abstract class FileFormatProvider
{
public abstract bool SupportsImport { get; }
public abstract bool SupportsExport { get; }
public abstract string FormatName { get; }
public virtual string DisplayName
{
get { return this.FormatName; }
}
/// <summary>
/// Default file name extension, without leading dot.
/// If there are multiple default/equivalent extensions
/// (like e.g. "html" and "htm"), specify all of them
/// separated by a '|' (e.g. "html|htm").
/// </summary>
public virtual string DefaultExtension
{
get { return string.Empty; }
}
public virtual bool RequiresFile
{
get { return true; }
}
public virtual bool SupportsUuids
{
get { return false; }
}
public virtual bool RequiresKey
{
get { return false; }
}
/// <summary>
/// This property specifies if entries are only appended to the
/// end of the root group. This is true for example if the
/// file format doesn't support groups (i.e. no hierarchy).
/// </summary>
public virtual bool ImportAppendsToRootGroupOnly
{
get { return false; }
}
/// <summary>
/// Called before the <c>Export</c> method is invoked.
/// </summary>
/// <returns>Returns <c>true</c>, if the <c>Export</c> method
/// can be invoked. If it returns <c>false</c>, something has
/// failed and the export process should be aborted.</returns>
public virtual bool TryBeginExport()
{
return true;
}
/// <summary>
/// Import a stream into a database. Throws an exception if an error
/// occurs. Do not call the base class method when overriding it.
/// </summary>
/// <param name="pwStorage">Data storage into which the data will be imported.</param>
/// <param name="sInput">Input stream to read the data from.</param>
/// <param name="slLogger">Status logger. May be <c>null</c>.</param>
public abstract void Import(PwDatabase pwStorage, Stream sInput,
IStatusLogger slLogger);
/// <summary>
/// Export data into a stream. Throws an exception if an error
/// occurs (like writing to stream fails, etc.). Returns <c>true</c>,
/// if the export was successful.
/// </summary>
/// <param name="pwExportInfo">Contains the data source and detailed
/// information about which entries should be exported.</param>
/// <param name="sOutput">Output stream to write the data to.</param>
/// <param name="slLogger">Status logger. May be <c>null</c>.</param>
/// <returns>Returns <c>false</c>, if the user has aborted the export
/// process (like clicking Cancel in an additional export settings
/// dialog).</returns>
public virtual bool Export(PwExportInfo pwExportInfo, Stream sOutput,
IStatusLogger slLogger)
{
throw new NotSupportedException();
}
}
}

View File

@ -0,0 +1,183 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System.Diagnostics;
using System.IO;
using KeePassLib;
using KeePassLib.Delegates;
using KeePassLib.Interfaces;
using KeePassLib.Utility;
namespace KeePass.DataExchange.Formats
{
public sealed class KeePassCsv1x : FileFormatProvider
{
public override bool SupportsImport { get { return false; } }
public override bool SupportsExport { get { return true; } }
public override string FormatName { get { return "KeePass CSV (1.x)"; } }
public override string DefaultExtension { get { return "csv"; } }
// public override bool ImportAppendsToRootGroupOnly { get { return true; } }
/* public override void Import(PwDatabase pwStorage, Stream sInput,
IStatusLogger slLogger)
{
StreamReader sr = new StreamReader(sInput, Encoding.UTF8);
string strFileContents = sr.ReadToEnd();
sr.Close();
CharStream csSource = new CharStream(strFileContents);
while(true)
{
if(ReadEntry(pwStorage, csSource) == false)
break;
}
}
private static bool ReadEntry(PwDatabase pwStorage, CharStream csSource)
{
PwEntry pe = new PwEntry(true, true);
string strTitle = ReadCsvField(csSource);
if(strTitle == null) return false; // No entry available
string strUser = ReadCsvField(csSource);
if(strUser == null) throw new InvalidDataException();
string strPassword = ReadCsvField(csSource);
if(strPassword == null) throw new InvalidDataException();
string strUrl = ReadCsvField(csSource);
if(strUrl == null) throw new InvalidDataException();
string strNotes = ReadCsvField(csSource);
if(strNotes == null) throw new InvalidDataException();
if((strTitle == "Account") && (strUser == "Login Name") &&
(strPassword == "Password") && (strUrl == "Web Site") &&
(strNotes == "Comments"))
{
return true; // Ignore header entry
}
pe.Strings.Set(PwDefs.TitleField, new ProtectedString(
pwStorage.MemoryProtection.ProtectTitle, strTitle));
pe.Strings.Set(PwDefs.UserNameField, new ProtectedString(
pwStorage.MemoryProtection.ProtectUserName, strUser));
pe.Strings.Set(PwDefs.PasswordField, new ProtectedString(
pwStorage.MemoryProtection.ProtectPassword, strPassword));
pe.Strings.Set(PwDefs.UrlField, new ProtectedString(
pwStorage.MemoryProtection.ProtectUrl, strUrl));
pe.Strings.Set(PwDefs.NotesField, new ProtectedString(
pwStorage.MemoryProtection.ProtectNotes, strNotes));
pwStorage.RootGroup.AddEntry(pe, true);
return true;
}
private static string ReadCsvField(CharStream csSource)
{
StringBuilder sb = new StringBuilder();
bool bInField = false;
while(true)
{
char ch = csSource.ReadChar();
if(ch == char.MinValue)
return null;
if((ch == '\"') && !bInField)
bInField = true;
else if((ch == '\"') && bInField)
break;
else if(ch == '\\')
{
char chSub = csSource.ReadChar();
if(chSub == char.MinValue)
throw new InvalidDataException();
sb.Append(chSub);
}
else if(bInField)
sb.Append(ch);
}
return sb.ToString();
} */
public override void Import(PwDatabase pwStorage, Stream sInput, IStatusLogger slLogger)
{
throw new System.NotImplementedException();
}
public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
IStatusLogger slLogger)
{
PwGroup pg = (pwExportInfo.DataGroup ?? ((pwExportInfo.ContextDatabase !=
null) ? pwExportInfo.ContextDatabase.RootGroup : null));
StreamWriter sw = new StreamWriter(sOutput, StrUtil.Utf8);
sw.Write("\"Account\",\"Login Name\",\"Password\",\"Web Site\",\"Comments\"\r\n");
EntryHandler eh = delegate(PwEntry pe)
{
WriteCsvEntry(sw, pe);
return true;
};
if(pg != null) pg.TraverseTree(TraversalMethod.PreOrder, null, eh);
sw.Close();
return true;
}
private static void WriteCsvEntry(StreamWriter sw, PwEntry pe)
{
if(sw == null) { Debug.Assert(false); return; }
if(pe == null) { Debug.Assert(false); return; }
const string strSep = "\",\"";
sw.Write("\"");
WriteCsvString(sw, pe.Strings.ReadSafe(PwDefs.TitleField), strSep);
WriteCsvString(sw, pe.Strings.ReadSafe(PwDefs.UserNameField), strSep);
WriteCsvString(sw, pe.Strings.ReadSafe(PwDefs.PasswordField), strSep);
WriteCsvString(sw, pe.Strings.ReadSafe(PwDefs.UrlField), strSep);
WriteCsvString(sw, pe.Strings.ReadSafe(PwDefs.NotesField), "\"\r\n");
}
private static void WriteCsvString(StreamWriter sw, string strText,
string strAppend)
{
string str = strText;
if(!string.IsNullOrEmpty(str))
{
str = str.Replace("\\", "\\\\");
str = str.Replace("\"", "\\\"");
sw.Write(str);
}
if(!string.IsNullOrEmpty(strAppend)) sw.Write(strAppend);
}
}
}

View File

@ -0,0 +1,60 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using KeePassLib;
using KeePassLib.Interfaces;
using KeePassLib.Serialization;
namespace KeePass.DataExchange.Formats
{
public sealed class KeePassKdb2x : FileFormatProvider
{
public override bool SupportsImport { get { return true; } }
public override bool SupportsExport { get { return true; } }
public override string FormatName { get { return "KeePass KDBX (2.x)"; } }
public override string DefaultExtension { get { return "kdbx"; } }
public override bool SupportsUuids { get { return true; } }
public override bool RequiresKey { get { return true; } }
public override void Import(PwDatabase pwStorage, Stream sInput,
IStatusLogger slLogger)
{
KdbxFile kdbx = new KdbxFile(pwStorage);
kdbx.Load(sInput, KdbxFormat.Default, slLogger);
}
public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
IStatusLogger slLogger)
{
KdbxFile kdbx = new KdbxFile(pwExportInfo.ContextDatabase);
kdbx.Save(sOutput, pwExportInfo.DataGroup, KdbxFormat.Default, slLogger);
return true;
}
}
}

View File

@ -0,0 +1,72 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using KeePassLib;
using KeePassLib.Collections;
using KeePassLib.Interfaces;
using KeePassLib.Serialization;
namespace KeePass.DataExchange.Formats
{
public sealed class KeePassXml2x : FileFormatProvider
{
public override bool SupportsImport { get { return true; } }
public override bool SupportsExport { get { return true; } }
public override string FormatName { get { return "KeePass XML (2.x)"; } }
public override string DefaultExtension { get { return "xml"; } }
public override bool SupportsUuids { get { return true; } }
public override void Import(PwDatabase pwStorage, Stream sInput,
IStatusLogger slLogger)
{
KdbxFile kdbx = new KdbxFile(pwStorage);
kdbx.Load(sInput, KdbxFormat.PlainXml, slLogger);
}
public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
IStatusLogger slLogger)
{
PwDatabase pd = (pwExportInfo.ContextDatabase ?? new PwDatabase());
PwObjectList<PwDeletedObject> vDel = null;
if(pwExportInfo.ExportDeletedObjects == false)
{
vDel = pd.DeletedObjects.CloneShallow();
pd.DeletedObjects.Clear();
}
KdbxFile kdb = new KdbxFile(pd);
kdb.Save(sOutput, pwExportInfo.DataGroup, KdbxFormat.PlainXml, slLogger);
// Restore deleted objects list
if(vDel != null) pd.DeletedObjects.Add(vDel);
return true;
}
}
}

View File

@ -0,0 +1,82 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using KeePassLib;
namespace KeePass.DataExchange
{
public sealed class PwExportInfo
{
private PwGroup m_pg;
/// <summary>
/// This group contains all entries and subgroups that should
/// be exported. Is never <c>null</c>.
/// </summary>
public PwGroup DataGroup
{
get { return m_pg; }
}
private PwDatabase m_pd;
/// <summary>
/// Optional context database reference. May be <c>null</c>.
/// </summary>
public PwDatabase ContextDatabase
{
get { return m_pd; }
}
private bool m_bExpDel = true;
/// <summary>
/// Indicates whether deleted objects should be exported, if
/// the data format supports it.
/// </summary>
public bool ExportDeletedObjects
{
get { return m_bExpDel; }
}
public PwExportInfo(PwGroup pgDataSource, PwDatabase pwContextInfo)
{
ConstructEx(pgDataSource, pwContextInfo, null);
}
public PwExportInfo(PwGroup pgDataSource, PwDatabase pwContextInfo,
bool bExportDeleted)
{
ConstructEx(pgDataSource, pwContextInfo, bExportDeleted);
}
private void ConstructEx(PwGroup pgDataSource, PwDatabase pwContextInfo,
bool? bExportDeleted)
{
if(pgDataSource == null) throw new ArgumentNullException("pgDataSource");
// pwContextInfo may be null.
m_pg = pgDataSource;
m_pd = pwContextInfo;
if(bExportDeleted.HasValue) m_bExpDel = bExportDeleted.Value;
}
}
}

View File

@ -20,7 +20,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
@ -59,6 +59,11 @@
<Compile Include="database\KdbDatabaseLoader.cs" />
<Compile Include="database\KdbxDatabaseLoader.cs" />
<Compile Include="database\SynchronizeCachedDatabase.cs" />
<Compile Include="DataExchange\FileFormatProvider.cs" />
<Compile Include="DataExchange\Formats\KeePassCsv1x.cs" />
<Compile Include="DataExchange\Formats\KeePassKdb2x.cs" />
<Compile Include="DataExchange\Formats\KeePassXml2x.cs" />
<Compile Include="DataExchange\PwExportInfo.cs" />
<Compile Include="Io\BuiltInFileStorage.cs" />
<Compile Include="Io\CachingFileStorage.cs" />
<Compile Include="Io\DropboxFileStorage.cs" />

View File

@ -47,6 +47,7 @@ namespace keepass2android
ErrorOcurred,
SynchronizingOtpAuxFile,
SavingOtpAuxFile,
CertificateFailure
CertificateFailure,
exporting_database
}
}

View File

@ -717,14 +717,7 @@ public class KP2AKeyboard extends InputMethodService
ExtractedTextRequest etr = new ExtractedTextRequest();
etr.token = 0; // anything is fine here
ExtractedText et = ic.getExtractedText(etr, 0);
if (et == null)
{
Log.d("KP2AK", "et == null");
}
else
{
Log.d("KP2AK", "et != null "+et.text);
}
boolean hasTextInField = (et != null) && (!TextUtils.isEmpty(et.text));
if (!hasTextInField) //only auto-fill if target field is empty
{

View File

@ -534,34 +534,6 @@ namespace keepass2android
}
private class CreateNewFilename: RunnableOnFinish
{
private readonly string _filename;
public CreateNewFilename(OnFinish finish, string filename)
: base(finish)
{
_filename = filename;
}
public override void Run()
{
try
{
int lastIndexOfSlash = _filename.LastIndexOf("/", StringComparison.Ordinal);
string parent = _filename.Substring(0, lastIndexOfSlash);
string newFilename = _filename.Substring(lastIndexOfSlash + 1);
string resultingFilename = App.Kp2a.GetFileStorage(new IOConnectionInfo { Path = parent }).CreateFilePath(parent, newFilename);
Finish(true, resultingFilename);
}
catch (Exception e)
{
Finish(false, e.Message);
}
}
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using KeePassLib.Serialization;
namespace keepass2android
{
class CreateNewFilename : RunnableOnFinish
{
private readonly string _filename;
public CreateNewFilename(OnFinish finish, string filename)
: base(finish)
{
_filename = filename;
}
public override void Run()
{
try
{
int lastIndexOfSlash = _filename.LastIndexOf("/", StringComparison.Ordinal);
string parent = _filename.Substring(0, lastIndexOfSlash);
string newFilename = _filename.Substring(lastIndexOfSlash + 1);
string resultingFilename = App.Kp2a.GetFileStorage(new IOConnectionInfo { Path = parent }).CreateFilePath(parent, newFilename);
Finish(true, resultingFilename);
}
catch (Exception e)
{
Finish(false, e.Message);
}
}
}
}

View File

@ -0,0 +1,258 @@
using System;
using System.IO;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Util;
using Android.Widget;
using KeePass.DataExchange;
using KeePass.DataExchange.Formats;
using KeePassLib.Interfaces;
using KeePassLib.Serialization;
using keepass2android.Io;
namespace keepass2android
{
[Activity(Label = "@string/app_name",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
Theme = "@style/Base")]
[IntentFilter(new[] {"keepass2android.ExportDatabaseActivity"}, Categories = new[] {Intent.CategoryDefault})]
public class ExportDatabaseActivity : LockCloseActivity
{
FileFormatProvider[] _ffp = new FileFormatProvider[]
{
new KeePassKdb2x(),
new KeePassXml2x(),
new KeePassCsv1x()
};
private int _fileFormatIndex;
protected override void OnCreate(Android.OS.Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetTitle(Resource.String.export_fileformats_title);
builder.SetSingleChoiceItems(Resource.Array.export_fileformat_options, _fileFormatIndex,
delegate(object sender, DialogClickEventArgs args) { _fileFormatIndex = args.Which; });
builder.SetPositiveButton(Resource.String.ok, delegate
{
Intent intent = new Intent(this, typeof(FileStorageSelectionActivity));
//intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, true);
StartActivityForResult(intent, 0);
});
builder.SetNegativeButton(Resource.String.cancel, delegate {
Finish();
});
builder.Show();
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (resultCode == KeePass.ExitFileStorageSelectionOk)
{
string protocolId = data.GetStringExtra("protocolId");
App.Kp2a.GetFileStorage(protocolId).StartSelectFile(new FileStorageSetupInitiatorActivity(this,
OnActivityResult,
defaultPath =>
{
if (defaultPath.StartsWith("sftp://"))
Util.ShowSftpDialog(this, OnReceiveSftpData);
else
Util.ShowFilenameDialog(this, OnCreateButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
Intents.RequestCodeFileBrowseForOpen);
}
), true, RequestCodeDbFilename, protocolId);
return;
}
if (resultCode == Result.Ok)
{
if (requestCode == RequestCodeDbFilename)
{
string filename = Util.IntentToFilename(data, this);
bool fileExists = data.GetBooleanExtra("group.pals.android.lib.ui.filechooser.FileChooserActivity.result_file_exists", true);
if (fileExists)
{
ExportTo(new IOConnectionInfo { Path = ConvertFilenameToIocPath(filename) });
}
else
{
var task = new CreateNewFilename(new ActionOnFinish((success, messageOrFilename) =>
{
if (!success)
{
Toast.MakeText(this, messageOrFilename, ToastLength.Long).Show();
return;
}
ExportTo(new IOConnectionInfo { Path = ConvertFilenameToIocPath(messageOrFilename) });
}), filename);
new ProgressTask(App.Kp2a, this, task).Run();
}
return;
}
}
if (resultCode == (Result)FileStorageResults.FileUsagePrepared)
{
var ioc = new IOConnectionInfo();
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
ExportTo(ioc);
return;
}
if (resultCode == (Result)FileStorageResults.FileChooserPrepared)
{
IOConnectionInfo ioc = new IOConnectionInfo();
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
StartFileChooser(ioc.Path, RequestCodeDbFilename, true);
return;
}
Finish();
}
private void ExportTo(IOConnectionInfo ioc)
{
var exportDb = new ExportDb(App.Kp2a, new ActionOnFinish(delegate(bool success, string message)
{
if (!success)
Toast.MakeText(this, message, ToastLength.Long).Show();
else
Toast.MakeText(this, GetString(Resource.String.export_database_successful), ToastLength.Long).Show();
Finish();
}
), _ffp[_fileFormatIndex], ioc);
ProgressTask pt = new ProgressTask(App.Kp2a, this, exportDb);
pt.Run();
}
protected int RequestCodeDbFilename
{
get { return 0; }
}
private bool OnCreateButton(string filename)
{
if (filename.Length == 0)
{
Toast.MakeText(this,
Resource.String.error_filename_required,
ToastLength.Long).Show();
return false;
}
IOConnectionInfo ioc = new IOConnectionInfo { Path = filename };
try
{
App.Kp2a.GetFileStorage(ioc);
}
catch (NoFileStorageFoundException)
{
Toast.MakeText(this,
"Unexpected scheme in " + filename,
ToastLength.Long).Show();
return false;
}
ExportTo(new IOConnectionInfo() { Path = filename });
return true;
}
private bool OnReceiveSftpData(string filename)
{
StartFileChooser(filename, RequestCodeDbFilename, true);
return true;
}
private static string ConvertFilenameToIocPath(string filename)
{
if ((filename != null) && (filename.StartsWith("file://")))
{
filename = filename.Substring(7);
filename = Java.Net.URLDecoder.Decode(filename);
}
return filename;
}
private void StartFileChooser(string defaultPath, int requestCode, bool forSave)
{
#if !EXCLUDE_FILECHOOSER
Kp2aLog.Log("FSA: defaultPath=" + defaultPath);
string fileProviderAuthority = FileChooserFileProvider.TheAuthority;
if (defaultPath.StartsWith("file://"))
{
fileProviderAuthority = "keepass2android."+AppNames.PackagePart+".android-filechooser.localfile";
}
Intent i = Keepass2android.Kp2afilechooser.Kp2aFileChooserBridge.GetLaunchFileChooserIntent(this, fileProviderAuthority,
defaultPath);
if (forSave)
{
i.PutExtra("group.pals.android.lib.ui.filechooser.FileChooserActivity.save_dialog", true);
i.PutExtra("group.pals.android.lib.ui.filechooser.FileChooserActivity.default_file_ext", _ffp[_fileFormatIndex].DefaultExtension);
}
StartActivityForResult(i, requestCode);
#endif
}
public class ExportDb : RunnableOnFinish
{
private readonly IKp2aApp _app;
private readonly FileFormatProvider _fileFormat;
private IOConnectionInfo _targetIoc;
public ExportDb(IKp2aApp app, OnFinish onFinish, FileFormatProvider fileFormat, IOConnectionInfo targetIoc) : base(onFinish)
{
_app = app;
this._fileFormat = fileFormat;
_targetIoc = targetIoc;
}
public override void Run()
{
StatusLogger.UpdateMessage(UiStringKey.exporting_database);
var pd = _app.GetDb().KpDatabase;
PwExportInfo pwInfo = new PwExportInfo(pd.RootGroup, pd, true);
try
{
using (var writeTransaction =_app.GetFileStorage(_targetIoc).OpenWriteTransaction(_targetIoc, _app.GetDb().KpDatabase.UseFileTransactions))
{
Stream sOut = writeTransaction.OpenFile();
_fileFormat.Export(pwInfo, sOut, new NullStatusLogger());
if (sOut != null) sOut.Close();
writeTransaction.CommitWrite();
}
Finish(true);
}
catch (Exception ex)
{
Finish(false, ex.Message);
}
}
}
}
}

View File

@ -31,7 +31,7 @@ namespace keepass2android
//which may be used "outside" the database (e.g. GeneratePassword for creating a master password)
protected const string NoLockCheck = "NO_LOCK_CHECK";
private IOConnectionInfo _ioc;
protected IOConnectionInfo _ioc;
private BroadcastReceiver _intentReceiver;
protected override void OnCreate(Bundle savedInstanceState)

View File

@ -48,11 +48,10 @@ using String = System.String;
namespace keepass2android
{
[Activity (Label = "@string/app_name",
ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden,
LaunchMode = LaunchMode.SingleInstance,
Theme="@style/Base")]
[Activity(Label = "@string/app_name",
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
LaunchMode = LaunchMode.SingleInstance,
Theme = "@style/Base")]
public class PasswordActivity : LockingActivity {
enum KeyProviders
@ -1173,7 +1172,5 @@ namespace keepass2android
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -116,7 +116,8 @@
<item>3600000</item>
<item>-1</item>
</string-array>
<string name="list_size_default">20</string>
<string name="list_size_default">20</string>
<string-array name="list_size_values">
<item>15</item>
<item>20</item>

View File

@ -32,6 +32,7 @@
<string name="QuickUnlock_prefs">QuickUnlock</string>
<string name="FileHandling_prefs">File handling</string>
<string name="keyboard_prefs">Keyboard</string>
<string name="export_prefs">Export database...</string>
<string name="brackets">Brackets</string>
<string name="cancel">Cancel</string>
<string name="ClearClipboard">Clipboard cleared.</string>
@ -160,7 +161,10 @@
<string name="database_name">Database name</string>
<string name="default_username">Default user name for new entries</string>
<string name="saving_database">Saving database…</string>
<string name="space">Space</string>
<string name="exporting_database">Exporting database…</string>
<string name="export_database_successful">Database exported successfully!</string>
<string name="space">Space</string>
<string name="search_label">Search</string>
<string name="show_password">Show password</string>
<string name="sort_name">Sort by name</string>
@ -398,6 +402,8 @@
<string name="CertificateWarning">Warning: Server certificate validation failed: %1$s. Install appropriate root certificate on your device or see settings!</string>
<string name="CertificateFailure">Error: Server certificate validation failed! Install appropriate root certificate on your device or see settings!</string>
<string name="export_fileformats_title">Select file format</string>
<string name="ChangeLog_title">Change log</string>
@ -520,6 +526,11 @@ Initial public release
<item>1 hour</item>
<item>Never</item>
</string-array>
<string-array name="export_fileformat_options">
<item>Keepass 2 database (.kdbx)</item>
<item>Keepass 2 XML (unencrypted) (.xml)</item>
<item>Keepass CSV (unencrypted) (.csv)</item>
</string-array>
<string-array name="list_size_options">
<item>Small</item>
<item>Medium</item>

View File

@ -44,6 +44,14 @@
android:persistent="false"
android:key="@string/default_username_key"/>
<PreferenceScreen
android:key="export_prefs"
android:title="@string/export_prefs"
>
<intent android:action="keepass2android.ExportDatabaseActivity"/>
</PreferenceScreen>
</PreferenceScreen>
<PreferenceScreen
@ -258,7 +266,7 @@
>
<intent android:action="keepass2android.softkeyboard.LatinIMESettings"/>
</PreferenceScreen>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -30,7 +30,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>
@ -92,6 +92,8 @@
<Compile Include="app\NoFileStorageFoundException.cs" />
<Compile Include="app\OtpAuxCacheSupervisor.cs" />
<Compile Include="CreateDatabaseActivity.cs" />
<Compile Include="CreateNewFilename.cs" />
<Compile Include="ExportDatabaseActivity.cs" />
<Compile Include="fileselect\FileChooserFileProvider.cs" />
<Compile Include="fileselect\FileStorageSetupActivity.cs" />
<Compile Include="fileselect\FileStorageSetupInitiatorActivity.cs" />
@ -170,6 +172,12 @@
<AndroidAsset Include="Assets\fontawesome-webfont.ttf" />
<AndroidAsset Include="Assets\DejaVuSansMono.ttf" />
<AndroidAsset Include="Assets\LICENSE_dejavu" />
<AndroidNativeLibrary Include="..\java\KP2AKdbLibrary\libs\armeabi-v7a\libfinal-key.so">
<Link>libs\armeabi-v7a\libfinal-key.so</Link>
</AndroidNativeLibrary>
<AndroidNativeLibrary Include="..\java\KP2AKdbLibrary\libs\armeabi\libfinal-key.so">
<Link>libs\armeabi\libfinal-key.so</Link>
</AndroidNativeLibrary>
<None Include="Resources\AboutResources.txt" />
<None Include="Resources\drawable\Thumbs.db">
<Visible>False</Visible>
@ -665,10 +673,6 @@
<Project>{23233a28-d74f-4bf8-b4d8-834060840bd7}</Project>
<Name>AppCompatV7Binding</Name>
</ProjectReference>
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
<Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
<Name>JavaFileStorageBindings</Name>
</ProjectReference>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project>
<Name>KeePassLib2Android</Name>