public bool DidOpenFileChange() { if (Loaded == false) { return(false); } return(_app.GetFileStorage(Ioc).CheckForFileChangeFast(Ioc, LastFileVersion)); }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.exporting_database); try { var fileStorage = _app.GetFileStorage(_targetIoc); if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = false; } CompositeKey masterKey = App.Kp2a.CurrentDb.KpDatabase.MasterKey; var sourceIoc = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc; IoUtil.Copy(_targetIoc, sourceIoc, App.Kp2a); if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode; } Finish(true); } catch (Exception ex) { Finish(false, ex.Message); } }
public void TestCreateSaveAndLoad_TestIdenticalFiles_kdb() { string filename = DefaultDirectory + "createsaveandload.kdb"; IKp2aApp app = SetupAppWithDatabase(filename); string kdbxXml = DatabaseToXml(app); //save it and reload it Android.Util.Log.Debug("KP2A", "-- Save DB -- "); SaveDatabase(app); Android.Util.Log.Debug("KP2A", "-- Load DB -- "); PwDatabase pwImp = new PwDatabase(); PwDatabase pwDatabase = app.GetDb().KpDatabase; pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey); pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep(); pwImp.MasterKey = pwDatabase.MasterKey; IOConnectionInfo ioc = new IOConnectionInfo() { Path = filename }; using (Stream s = app.GetFileStorage(ioc).OpenFileForRead(ioc)) { app.GetDb().DatabaseFormat.PopulateDatabaseFromStream(pwImp, s, null); } string kdbxReloadedXml = DatabaseToXml(app); RemoveKdbLines(ref kdbxReloadedXml); RemoveKdbLines(ref kdbxXml); Assert.AreEqual(kdbxXml, kdbxReloadedXml); }
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); } }
public override void Run() { try { var fileStorage = _app.GetFileStorage(_targetIoc); if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = false; } using (var writeTransaction = fileStorage.OpenWriteTransaction(_targetIoc, _app.GetDb().KpDatabase.UseFileTransactions)) { Stream sOut = writeTransaction.OpenFile(); byte[] byteArray = _data.ReadData(); sOut.Write(byteArray, 0, byteArray.Length); sOut.Close(); writeTransaction.CommitWrite(); } if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode; } Finish(true); } catch (Exception ex) { Finish(false, ex.Message); } }
//creates a local ioc where the sourceIoc can be stored to public static IOConnectionInfo GetInternalIoc(IOConnectionInfo sourceIoc, Context ctx, IKp2aApp app) { Java.IO.File internalDirectory = IoUtil.GetInternalDirectory(ctx); var filestorage = app.GetFileStorage(sourceIoc); string targetPath = filestorage.GetFilenameWithoutPathAndExt(sourceIoc); targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray()); if (targetPath == "") { targetPath = "internal"; } if (new File(internalDirectory, targetPath).Exists()) { int c = 1; var ext = UrlUtil.GetExtension(targetPath); var filenameWithoutExt = UrlUtil.StripExtension(targetPath); do { c++; targetPath = filenameWithoutExt + c; if (!String.IsNullOrEmpty(ext)) { targetPath += "." + ext; } } while (new File(internalDirectory, targetPath).Exists()); } return(IOConnectionInfo.FromPath(new File(internalDirectory, targetPath).CanonicalPath)); }
public static void Copy(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc, IKp2aApp app) { IFileStorage sourceStorage = app.GetFileStorage(sourceIoc, false); //don't cache source. file won't be used ever again IFileStorage targetStorage = app.GetFileStorage(targetIoc); using ( var writeTransaction = targetStorage.OpenWriteTransaction(targetIoc, app.GetBooleanPreference( PreferenceKey.UseFileTransactions))) { using (var writeStream = writeTransaction.OpenFile()) { sourceStorage.OpenFileForRead(sourceIoc).CopyTo(writeStream); } writeTransaction.CommitWrite(); } }
public static void Copy(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc, IKp2aApp app) { IFileStorage sourceStorage = app.GetFileStorage(sourceIoc, false); //don't cache source. file won't be used ever again IFileStorage targetStorage = app.GetFileStorage(targetIoc); using ( var writeTransaction = targetStorage.OpenWriteTransaction(targetIoc, app.GetBooleanPreference( PreferenceKey.UseFileTransactions))) { using (var writeStream = writeTransaction.OpenFile()) { sourceStorage.OpenFileForRead(sourceIoc).CopyTo(writeStream); } writeTransaction.CommitWrite(); } }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.progress_create); Database db = _app.CreateNewDatabase(_makeCurrent); db.KpDatabase = new KeePassLib.PwDatabase(); if (_key == null) { _key = new CompositeKey(); //use a temporary key which should be changed after creation } db.KpDatabase.New(_ioc, _key, _app.GetFileStorage(_ioc).GetFilenameWithoutPathAndExt(_ioc)); db.KpDatabase.KdfParameters = (new AesKdf()).GetDefaultParameters(); db.KpDatabase.Name = "Keepass2Android Password Database"; //re-set the name of the root group because the PwDatabase uses UrlUtil which is not appropriate for all file storages: db.KpDatabase.RootGroup.Name = _app.GetFileStorage(_ioc).GetFilenameWithoutPathAndExt(_ioc); // Set Database state db.Root = db.KpDatabase.RootGroup; db.SearchHelper = new SearchDbHelper(_app); // Add a couple default groups AddGroup internet = AddGroup.GetInstance(_ctx, _app, "Internet", 1, null, db.KpDatabase.RootGroup, null, true); internet.Run(); AddGroup email = AddGroup.GetInstance(_ctx, _app, "eMail", 19, null, db.KpDatabase.RootGroup, null, true); email.Run(); List <PwEntry> addedEntries; AddTemplateEntries addTemplates = new AddTemplateEntries(_ctx, _app, null); addTemplates.AddTemplates(out addedEntries); // Commit changes SaveDb save = new SaveDb(_ctx, _app, db, OnFinishToRun, _dontSave); save.SetStatusLogger(StatusLogger); _onFinishToRun = null; save.Run(); db.UpdateGlobals(); }
private void PrimaryIocSelected(IOConnectionInfo ioc) { var filestorage = _app.GetFileStorage(ioc, false); if (!filestorage.IsPermanentLocation(ioc)) { string message = _app.GetResourceString(UiStringKey.FileIsTemporarilyAvailable) + " " + _app.GetResourceString(UiStringKey.CopyFileRequired) + " " + _app.GetResourceString(UiStringKey.ClickOkToSelectLocation); EventHandler <DialogClickEventArgs> onOk = (sender, args) => { MoveToWritableLocation(ioc); }; EventHandler <DialogClickEventArgs> onCancel = (sender, args) => { ReturnCancel(); }; ShowAlertDialog(message, onOk, onCancel); return; } if ((RequestedWritableRequirements != WritableRequirements.ReadOnly) && (filestorage.IsReadOnly(ioc))) { string readOnlyExplanation = _app.GetResourceString(UiStringKey.FileIsReadOnly); BuiltInFileStorage builtInFileStorage = filestorage as BuiltInFileStorage; if (builtInFileStorage != null) { if (builtInFileStorage.IsReadOnlyBecauseKitkatRestrictions(ioc)) { readOnlyExplanation = _app.GetResourceString(UiStringKey.FileIsReadOnlyOnKitkat); } } EventHandler <DialogClickEventArgs> onOk = (sender, args) => { MoveToWritableLocation(ioc); }; EventHandler <DialogClickEventArgs> onCancel = (sender, args) => { if (RequestedWritableRequirements == WritableRequirements.WriteDemanded) { ReturnCancel(); } else { ReturnOk(ioc); } }; ShowAlertDialog(readOnlyExplanation + " " + (RequestedWritableRequirements == WritableRequirements.WriteDemanded ? _app.GetResourceString(UiStringKey.CopyFileRequired) : _app.GetResourceString(UiStringKey.CopyFileRequiredForEditing)) + " " + _app.GetResourceString(UiStringKey.ClickOkToSelectLocation), onOk, onCancel); return; } ReturnOk(ioc); }
public override void BindView(View view, Context context, ICursor cursor) { String path = cursor.GetString(1); TextView textView = view.FindViewById <TextView>(Resource.Id.file_filename); IOConnectionInfo ioc = new IOConnectionInfo { Path = path }; var fileStorage = _app.GetFileStorage(ioc); String displayName = cursor.GetString(6); if (string.IsNullOrEmpty(displayName)) { displayName = fileStorage.GetDisplayName(ioc); } textView.Text = displayName; textView.Tag = ioc.Path; }
public override void Run() { try { IOConnectionInfo ioc = _app.GetDb().Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (fileStorage is CachingFileStorage) { throw new Exception("Cannot sync a cached database!"); } StatusLogger.UpdateMessage(UiStringKey.CheckingDatabaseForChanges); //download file from remote location and calculate hash: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.DownloadingRemoteFile)); MemoryStream remoteData = new MemoryStream(); using ( HashingStreamEx hashingRemoteStream = new HashingStreamEx(fileStorage.OpenFileForRead(ioc), false, new SHA256Managed())) { hashingRemoteStream.CopyTo(remoteData); hashingRemoteStream.Close(); if (!MemUtil.ArraysEqual(_app.GetDb().KpDatabase.HashOfFileOnDisk, hashingRemoteStream.Hash)) { _app.TriggerReload(_context); Finish(true); } else { Finish(true, _app.GetResourceString(UiStringKey.RemoteDatabaseUnchanged)); } } } catch (Exception e) { Finish(false, e.Message); } }
public void Start() { string messageSuffix = ShowDatabaseIocInStatus ? "(" + App.GetFileStorage(Db.Ioc).GetDisplayName(Db.Ioc) + ")" : ""; if (CanRecycle) { App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title, QuestionRecycleResourceId, (dlgSender, dlgEvt) => { DeletePermanently = true; ProgressTask pt = new ProgressTask(App, Ctx, this); pt.Run(); }, (dlgSender, dlgEvt) => { DeletePermanently = false; ProgressTask pt = new ProgressTask(App, Ctx, this); pt.Run(); }, (dlgSender, dlgEvt) => { }, Ctx, messageSuffix); } else { App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title, QuestionNoRecycleResourceId, (dlgSender, dlgEvt) => { ProgressTask pt = new ProgressTask(App, Ctx, this); pt.Run(); }, null, (dlgSender, dlgEvt) => { }, Ctx, messageSuffix); } }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.exporting_database); var pd = _app.CurrentDb.KpDatabase; PwExportInfo pwInfo = new PwExportInfo(pd.RootGroup, pd, true); try { var fileStorage = _app.GetFileStorage(_targetIoc); if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = false; } using (var writeTransaction = fileStorage.OpenWriteTransaction(_targetIoc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions))) { Stream sOut = writeTransaction.OpenFile(); _fileFormat.Export(pwInfo, sOut, new NullStatusLogger()); if (sOut != null) { sOut.Close(); } writeTransaction.CommitWrite(); } if (fileStorage is IOfflineSwitchable) { ((IOfflineSwitchable)fileStorage).IsOffline = App.Kp2a.OfflineMode; } Finish(true); } catch (Exception ex) { Finish(false, ex.Message); } }
public override void Run() { if (!_dontSave) { try { if (_db.CanWrite == false) { //this should only happen if there is a problem in the UI so that the user sees an edit interface. Finish(false, "Cannot save changes. File is read-only!"); return; } string message = _app.GetResourceString(UiStringKey.saving_database); if (ShowDatabaseIocInStatus) { message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")"; } StatusLogger.UpdateMessage(message); IOConnectionInfo ioc = _db.Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (_streamForOrigFile == null) { if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) || (_db.KpDatabase.HashOfFileOnDisk == null)) //first time saving { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); return; } } if ( (_streamForOrigFile != null) || fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion) || //first try to use the fast change detection (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) == FileHashChange.Changed) //if that fails, hash the file and compare: ) { //ask user... _app.AskYesNoCancel(UiStringKey.TitleSyncQuestion, UiStringKey.MessageSyncQuestion, UiStringKey.YesSynchronize, UiStringKey.NoOverwrite, //yes = sync (sender, args) => { Action runHandler = () => { //note: when synced, the file might be downloaded once again from the server. Caching the data //in the hashing function would solve this but increases complexity. I currently assume the files are //small. MergeIn(fileStorage, ioc); PerformSaveWithoutCheck(fileStorage, ioc); _db.UpdateGlobals(); Finish(true); }; RunInWorkerThread(runHandler); }, //no = overwrite (sender, args) => { RunInWorkerThread(() => { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); }); }, //cancel (sender, args) => { RunInWorkerThread(() => Finish(false)); }, _ctx ); } else { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); } } catch (Exception e) { /* TODO KPDesktop: * catch(Exception exSave) * { * MessageService.ShowSaveWarning(pd.IOConnectionInfo, exSave, true); * bSuccess = false; * } */ Kp2aLog.LogUnexpectedError(e); Finish(false, e.Message); return; } } else { Finish(true); } }
public override void Run() { try { IOConnectionInfo ioc = _app.GetDb().Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (!(fileStorage is CachingFileStorage)) { throw new Exception("Cannot sync a non-cached database!"); } StatusLogger.UpdateMessage(UiStringKey.SynchronizingCachedDatabase); CachingFileStorage cachingFileStorage = (CachingFileStorage)fileStorage; //download file from remote location and calculate hash: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.DownloadingRemoteFile)); string hash; MemoryStream remoteData; try { remoteData = cachingFileStorage.GetRemoteDataAndHash(ioc, out hash); } catch (FileNotFoundException) { StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.RestoringRemoteFile)); cachingFileStorage.UpdateRemoteFile(ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)); Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); return; } //check if remote file was modified: if (cachingFileStorage.GetBaseVersionHash(ioc) != hash) { //remote file is modified if (cachingFileStorage.HasLocalChanges(ioc)) { //conflict! need to merge _saveDb = new SaveDb(_context, _app, new ActionOnFinish((success, result) => { if (!success) { Finish(false, result); } else { Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); } _saveDb = null; }), false, remoteData); _saveDb.Run(); _app.GetDb().MarkAllGroupsAsDirty(); } else { //only the remote file was modified -> reload database. //note: it's best to lock the database and do a complete reload here (also better for UI consistency in case something goes wrong etc.) _app.TriggerReload(_context); Finish(true); } } else { //remote file is unmodified if (cachingFileStorage.HasLocalChanges(ioc)) { //but we have local changes -> upload: StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.UploadingFile)); cachingFileStorage.UpdateRemoteFile(ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)); StatusLogger.UpdateSubMessage(""); Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully)); } else { //files are in sync: just set the result Finish(true, _app.GetResourceString(UiStringKey.FilesInSync)); } } } catch (Exception e) { Finish(false, e.Message); } }
public bool DidOpenFileChange() { return(_app.GetFileStorage(Ioc).CheckForFileChangeFast(Ioc, LastFileVersion)); }
public override void Run() { try { try { //make sure the file data is stored in the recent files list even if loading fails SaveFileData(_ioc, _keyfileOrProvider); 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; if (preloadedMemoryStream != null) { databaseStream = preloadedMemoryStream; } else { using (Stream s = _app.GetFileStorage(_ioc).OpenFileForRead(_ioc)) { databaseStream = new MemoryStream(); s.CopyTo(databaseStream); databaseStream.Seek(0, SeekOrigin.Begin); } } //ok, try to load the database. Let's start with Kdbx format and retry later if that is the wrong guess: _format = new KdbxDatabaseFormat(KdbpFile.GetFormatToUse(_app.GetFileStorage(_ioc).GetFileExtension(_ioc))); TryLoad(databaseStream); success = true; } catch (Exception e) { this.Exception = e; throw; } } catch (KeyFileException) { Kp2aLog.Log("KeyFileException"); Finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/ _app.GetResourceString(UiStringKey.keyfile_does_not_exist), false, Exception); } catch (AggregateException e) { string message = e.Message; foreach (var innerException in e.InnerExceptions) { message = innerException.Message; // Override the message shown with the last (hopefully most recent) inner exception Kp2aLog.LogUnexpectedError(innerException); } Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + message, false, Exception); return; } catch (DuplicateUuidsException e) { Kp2aLog.Log(e.ToString()); Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + e.Message + _app.GetResourceString(UiStringKey.DuplicateUuidsErrorAdditional), false, Exception); return; } catch (Exception e) { if (!(e is InvalidCompositeKeyException)) { Kp2aLog.LogUnexpectedError(e); } Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + (e.Message ?? (e is FileNotFoundException ? _app.GetResourceString(UiStringKey.FileNotFound) : "")), false, Exception); return; } }
public override void Run() { if (!_dontSave) { try { if (_db.CanWrite == false) { //this should only happen if there is a problem in the UI so that the user sees an edit interface. Finish(false, "Cannot save changes. File is read-only!"); return; } string message = _app.GetResourceString(UiStringKey.saving_database); if (ShowDatabaseIocInStatus) { message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")"; } StatusLogger.UpdateMessage(message); IOConnectionInfo ioc = _db.Ioc; IFileStorage fileStorage = _app.GetFileStorage(ioc); if (_streamForOrigFile == null) { if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) || (_db.KpDatabase.HashOfFileOnDisk == null)) //first time saving { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); return; } } bool hasStreamForOrigFile = (_streamForOrigFile != null); bool hasChangeFast = hasStreamForOrigFile || fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion); //first try to use the fast change detection; bool hasHashChanged = hasChangeFast || (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) == FileHashChange.Changed); //if that fails, hash the file and compare: if (hasHashChanged) { Kp2aLog.Log("Conflict. " + hasStreamForOrigFile + " " + hasChangeFast + " " + hasHashChanged); bool alwaysMerge = (PreferenceManager.GetDefaultSharedPreferences(Application.Context) .GetBoolean("AlwaysMergeOnConflict", false)); if (alwaysMerge) { MergeAndFinish(fileStorage, ioc); } else { //ask user... _app.AskYesNoCancel(UiStringKey.TitleSyncQuestion, UiStringKey.MessageSyncQuestion, UiStringKey.YesSynchronize, UiStringKey.NoOverwrite, //yes = sync (sender, args) => { Action runHandler = () => { MergeAndFinish(fileStorage, ioc); }; RunInWorkerThread(runHandler); }, //no = overwrite (sender, args) => { RunInWorkerThread(() => { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); }); }, //cancel (sender, args) => { RunInWorkerThread(() => Finish(false)); }, _ctx ); } } else { PerformSaveWithoutCheck(fileStorage, ioc); Finish(true); } } catch (Exception e) { /* TODO KPDesktop: * catch(Exception exSave) * { * MessageService.ShowSaveWarning(pd.IOConnectionInfo, exSave, true); * bSuccess = false; * } */ Kp2aLog.LogUnexpectedError(e); Finish(false, e.Message); return; } } else { Finish(true); } }