public override void Run() { StatusLogger.UpdateMessage(UiStringKey.SettingPassword); PwDatabase pm = _app.GetDb().KpDatabase; CompositeKey newKey = new CompositeKey(); if (String.IsNullOrEmpty(_password) == false) { newKey.AddUserKey(new KcpPassword(_password)); } if (String.IsNullOrEmpty(_keyfile) == false) { try { newKey.AddUserKey(new KcpKeyFile(_keyfile)); } catch (Exception) { //TODO MessageService.ShowWarning (strKeyFile, KPRes.KeyFileError, exKF); return; } } DateTime previousMasterKeyChanged = pm.MasterKeyChanged; CompositeKey previousKey = pm.MasterKey; pm.MasterKeyChanged = DateTime.Now; pm.MasterKey = newKey; // Save Database _onFinishToRun = new AfterSave(previousKey, previousMasterKeyChanged, pm, OnFinishToRun); SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, _dontSave); save.SetStatusLogger(StatusLogger); save.Run(); }
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() { 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 override void Run() { StatusLogger.UpdateMessage(UiStringKey.AddingGroup); // Generate new group Group = new PwGroup(true, true, _name, (PwIcon)_iconId); if (_groupCustomIconId != null) { Group.CustomIconUuid = _groupCustomIconId; } Parent.AddGroup(Group, true); // Commit to disk SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, DontSave); save.SetStatusLogger(StatusLogger); save.Run(); }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.SynchronizingOtpAuxFile); try { //simply open the file. The file storage does a complete sync. using (App.Kp2a.GetOtpAuxFileStorage(_ioc).OpenFileForRead(_ioc)) { } Finish(true); } catch (Exception e) { Finish(false, e.Message); } }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.AddingEntry); List <PwEntry> addedEntries; var templateGroup = AddTemplates(out addedEntries); if (addedEntries.Any()) { _app.DirtyGroups.Add(templateGroup); // Commit to disk SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun); save.SetStatusLogger(StatusLogger); save.Run(); } }
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(); }
public override void Run() { if (Success) { // Mark parent group dirty _addGroup.Db.Dirty.Add(_addGroup.Parent); // Add group to global list _addGroup.Db.Groups[_addGroup.Group.Uuid] = _addGroup.Group; } else { StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); _addGroup.Parent.Groups.Remove(_addGroup.Group); } base.Run(); }
public override void Run() { if (Success) { PwGroup parent = _entry.ParentGroup; // Mark parent group dirty _app.DirtyGroups.Add(parent); } else { StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); //TODO test fail _entry.ParentGroup.Entries.Remove(_entry); } base.Run(); }
public override void Run() { StatusLogger.UpdateMessage(UiStringKey.AddingEntry); //make sure we're not adding the entry if it was added before. //(this might occur in very rare cases where the user dismissis the save dialog //by rotating the screen while saving and then presses save again) if (_parentGroup.FindEntry(_entry.Uuid, false) == null) { _parentGroup.AddEntry(_entry, true); } // Commit to disk SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun); save.SetStatusLogger(StatusLogger); save.Run(); }
public override void Run() { StatusLogger.UpdateMessage(StatusMessage); List <PwGroup> touchedGroups = new List <PwGroup>(); List <PwGroup> permanentlyDeletedGroups = new List <PwGroup>(); Android.Util.Log.Debug("KP2A", "Calling PerformDelete.."); PerformDelete(touchedGroups, permanentlyDeletedGroups); _onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) => { if (success) { foreach (var g in touchedGroups) { App.DirtyGroups.Add(g); } foreach (var g in permanentlyDeletedGroups) { //remove groups from global lists if present there App.DirtyGroups.Remove(g); Db.GroupsById.Remove(g.Uuid); Db.Elements.Remove(g); } } else { // Let's not bother recovering from a failure to save. It is too much work. App.Lock(false); } }, OnFinishToRun); // Commit database SaveDb save = new SaveDb(Ctx, App, Db, OnFinishToRun, false); save.ShowDatabaseIocInStatus = ShowDatabaseIocInStatus; save.SetStatusLogger(StatusLogger); save.Run(); }
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 override void Run() { if (Success) { // Mark parent group dirty. Even only the last modification date changed, this might affect sort order PwGroup parent = _updatedEntry.ParentGroup; if (parent != null) { // Mark parent group dirty _app.GetDb().Dirty.Add(parent); } } else { StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); // If we fail to save, back out changes to global structure //TODO test fail _updatedEntry.AssignProperties(_backup, false, true, false); } base.Run(); }
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() { 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 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 { 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); } }