示例#1
0
        public void TestLoadEditSaveWithSyncOverwriteBecauseOfNoCheck()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
            //load it once again:
            IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //modify the database by adding a group in both databases:
            app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
            var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);
            //save the database from app 1:
            SaveDatabase(app);

            //the user doesn't want to perform check for file change:
            ((TestKp2aApp)app2).SetPreference(PreferenceKey.CheckForFileChangesOnSave, false);

            //save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
            SaveDatabase(app2);

            //make sure no question was asked
            Assert.AreEqual(null, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);

            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //ensure the sync was NOT performed (overwrite expected!):
            AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
示例#2
0
        public void TestLoadEditSaveWithSyncConflict()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
            //load it once again:
            IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //modify the database by renaming the same group in both databases:
            app.GetDb().KpDatabase.RootGroup.Groups.Single(g => g.Name == "Internet").Name += "abc";
            app2.GetDb().KpDatabase.RootGroup.Groups.Single(g => g.Name == "Internet").Name += "abcde";
            //app1 also changes the master password:
            var compositeKey = app.GetDb().KpDatabase.MasterKey;

            compositeKey.RemoveUserKey(compositeKey.GetUserKey(typeof(KcpPassword)));
            compositeKey.AddUserKey(new KcpPassword("abc"));

            //save the database from app 1:
            SaveDatabase(app);


            ((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Yes);

            //save the database from app 2: This save operation must fail because the target file cannot be loaded:
            Assert.IsFalse(TrySaveDatabase(app2));

            //make sure the right question was asked
            Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);
        }
示例#3
0
        public void TestLoadEditSaveWithSyncCancel()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
            //load it once again:
            IKp2aApp app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //modify the database by adding a group in both databases:
            app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
            var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);
            //save the database from app 1:
            SaveDatabase(app);

            //the user clicks the "cancel" button when asked if the sync should be performed
            ((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Cancel);

            //save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
            Assert.AreEqual(false, TrySaveDatabase(app2));

            //make sure the right question was asked
            Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);

            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //ensure the sync was NOT performed (cancel expected!):
            AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
示例#4
0
        public void TestLoadAndSave_TestIdenticalFiles_kdb()
        {
            IKp2aApp app = LoadDatabase(DefaultDirectory + "complexDb.kdb", "test", null);

            app.GetDb().Root.SortSubGroups(true);
            string kdbxXml = DatabaseToXml(app);

            newFilename = TestDbDirectory + "tmp_complexDb.kdb";
            if (File.Exists(newFilename))
            {
                File.Delete(newFilename);
            }
            app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename;
            app.GetDb().SaveData(Application.Context);


            IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null);

            appReloaded.GetDb().Root.SortSubGroups(true);
            string kdbxReloadedXml = DatabaseToXml(appReloaded);

            RemoveKdbLines(ref kdbxReloadedXml);
            RemoveKdbLines(ref kdbxXml);

            Assert.AreEqual(kdbxXml, kdbxReloadedXml);
        }
        public void TestLoadEditSaveWhenDeleted()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            IOConnection.DeleteFile(new IOConnectionInfo {
                Path = DefaultFilename
            });
            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //delete the file:
            File.Delete(DefaultFilename);

            //modify the database by adding a group:
            app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
            //save the database again:
            _testCacheSupervisor.Reset();
            SaveDatabase(app);
            Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle);
            _testCacheSupervisor.AssertNoCall();

            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //ensure the change was saved:
            AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
示例#6
0
        public void TestLoadEditSaveWithWriteBecauseTargetNotExists()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //modify the database by adding a group:
            app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);

            //delete the file:
            File.Delete(DefaultFilename);

            //save the database:
            SaveDatabase(app);

            //make sure no question was asked
            Assert.AreEqual(null, ((TestKp2aApp)app).LastYesNoCancelQuestionTitle);

            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //ensure the file was saved:
            AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
示例#7
0
        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);
        }
示例#8
0
        private static string DatabaseToXml(IKp2aApp app)
        {
            KdbxFile kdb     = new KdbxFile(app.GetDb().KpDatabase);
            var      sOutput = new OnCloseToStringMemoryStream();

            kdb.Save(sOutput, app.GetDb().KpDatabase.RootGroup, KdbxFormat.PlainXml, null);
            return(sOutput.Text);
        }
示例#9
0
        private void TestSync(string filename)
        {
//create the default database:
            IKp2aApp app = SetupAppWithDatabase(filename);

            DisplayGroups(app, "After create");
            //save it and reload it so we have a base version
            Android.Util.Log.Debug("KP2A", "-- Save first version -- ");
            SaveDatabase(app);
            Android.Util.Log.Debug("KP2A", "-- Load DB -- ");
            app = LoadDatabase(filename, DefaultPassword, DefaultKeyfile);
            DisplayGroups(app, "After reload");
            //load it once again:
            Android.Util.Log.Debug("KP2A", "-- Load DB to app 2-- ");
            IKp2aApp app2 = LoadDatabase(filename, DefaultPassword, DefaultKeyfile);

            DisplayGroups(app2, "After load to app2");

            //modify the database by adding a group in both databases:
            app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
            var group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Energy);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);
            //save the database from app 1:
            Android.Util.Log.Debug("KP2A", "-- Save from app 1 (with TestGroup) -- ");
            SaveDatabase(app);


            ((TestKp2aApp)app2).SetYesNoCancelResult(TestKp2aApp.YesNoCancelResult.Yes);

            //save the database from app 2: This save operation must detect the changes made from app 1 and ask if it should sync:
            Android.Util.Log.Debug("KP2A", "-- Save from app 2 (with TestGroup2, requires merge) -- ");
            SaveDatabase(app2);
            DisplayGroups(app2, "After save with merge");
            //make sure the right question was asked
            Assert.AreEqual(UiStringKey.TitleSyncQuestion, ((TestKp2aApp)app2).LastYesNoCancelQuestionTitle);

            //add group 2 to app 1:
            app.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);
            app.GetDb().KpDatabase.RootGroup.SortSubGroups(true);

            Android.Util.Log.Debug("KP2A", "-- Load DB to new app -- ");
            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(filename, DefaultPassword, DefaultKeyfile);

            resultApp.GetDb().KpDatabase.RootGroup.SortSubGroups(true);
            //ensure the sync was successful:
            string kdbxXml       = DatabaseToXml(app);
            string kdbxResultXml = DatabaseToXml(resultApp);

            RemoveKdbLines(ref kdbxXml, true);
            RemoveKdbLines(ref kdbxResultXml, true);

            Assert.AreEqual(kdbxXml, kdbxResultXml);

            //AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
        /*
         * public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave)
         *  : base(finish)
         * {
         *              SetMembers(ctx, db, group, act, dontSave);
         *      }
         *
         *      public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, bool dontSave):base(finish) {
         *              SetMembers(ctx, db, group, null, dontSave);
         *      }
         */
        private void SetMembers(Context ctx, IKp2aApp app, PwGroup group, bool dontSave)
        {
            base.SetMembers(ctx, app.GetDb());

            _group   = group;
            DontSave = dontSave;
        }
示例#11
0
            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);
                }
            }
示例#12
0
 public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish)
     : base(finish, app)
 {
     Ctx = ctx;
     Db = app.GetDb();
     _entry = entry;
 }
示例#13
0
        /*
         * public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave)
         *  : base(finish)
         * {
         *              SetMembers(ctx, db, group, act, dontSave);
         *      }
         *
         *      public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, bool dontSave):base(finish) {
         *              SetMembers(ctx, db, group, null, dontSave);
         *      }
         */
        private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave)
        {
            base.SetMembers(activity, app.GetDb());

            _group   = group;
            DontSave = dontSave;
        }
        protected AddEntry(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish) : base(finish)
        {
            _ctx         = ctx;
            _parentGroup = parentGroup;
            _app         = app;
            _entry       = entry;

            _onFinishToRun = new AfterAdd(app.GetDb(), entry, OnFinishToRun);
        }
示例#15
0
        protected AddEntry(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish)
            : base(finish)
        {
            _ctx = ctx;
            _parentGroup = parentGroup;
            _app = app;
            _entry = entry;

            _onFinishToRun = new AfterAdd(app.GetDb(), entry, OnFinishToRun);
        }
示例#16
0
        public void TestLoadAndSave_TestIdenticalFiles()
        {
            IKp2aApp app     = LoadDatabase(DefaultDirectory + "complexDb.kdbx", "test", null);
            var      kdbxXml = DatabaseToXml(app);

            newFilename = TestDbDirectory + "tmp_complexDb.kdbx";
            if (File.Exists(newFilename))
            {
                File.Delete(newFilename);
            }
            app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename;
            app.GetDb().SaveData(Application.Context);


            IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null);

            var kdbxReloadedXml = DatabaseToXml(appReloaded);

            Assert.AreEqual(kdbxXml, kdbxReloadedXml);
        }
示例#17
0
        public void TestLoadKdbxAndSaveKdbp_TestIdenticalFiles()
        {
            IKp2aApp app = LoadDatabase(DefaultDirectory + "complexDb.kdbx", "test", null);

            //string kdbxXml = DatabaseToXml(app);

            newFilename = TestDbDirectory + "tmp_complexDb.kdbp";
            if (File.Exists(newFilename))
            {
                File.Delete(newFilename);
            }
            app.GetDb().KpDatabase.IOConnectionInfo.Path = newFilename;
            app.GetDb().SaveData(Application.Context);


            IKp2aApp appReloaded = LoadDatabase(newFilename, "test", null);

            /*
             * Unfortunately we cannot compare the xml because there are slight differences:
             *  - the order of ProtectedStrings in the xml is different (which is ok)
             *  - the CustomIconUuids are serialized as Zeros instead of not being serialized (which is ok as well)
             * string kdbxReloadedXml = DatabaseToXml(appReloaded);
             *
             * bool areEqual = kdbxXml.Equals(kdbxReloadedXml);
             *
             * if (!areEqual)
             * {
             *      using (StreamWriter w1 = File.CreateText(TestDbDirectory + "FromOriginalKdbx.xml"))
             *      {
             *              w1.Write(kdbxXml);
             *      }
             *      using (StreamWriter w2 = File.CreateText(TestDbDirectory + "FromKdbp.xml"))
             *      {
             *              w2.Write(kdbxReloadedXml);
             *      }
             *
             * }
             * Assert.IsTrue(areEqual, "reloaded->xml differs from loaded->xml");
             */
            AssertDatabasesAreEqual(app.GetDb().KpDatabase, appReloaded.GetDb().KpDatabase);
        }
示例#18
0
        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);
            }
        }
示例#19
0
        public void TestLoadEditSave()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            IOConnection.DeleteFile(new IOConnectionInfo {
                Path = DefaultFilename
            });
            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
            //modify the database by adding a group:
            app.GetDb().KpDatabase.RootGroup.AddGroup(new PwGroup(true, true, "TestGroup", PwIcon.Apple), true);
            //save the database again:
            SaveDatabase(app);

            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //ensure the change was saved:
            AssertDatabasesAreEqual(app.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
示例#20
0
            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();
            }
示例#21
0
 private static string DatabaseToXml(IKp2aApp app)
 {
     KdbxFile kdb = new KdbxFile(app.GetDb().KpDatabase);
     var sOutput = new OnCloseToStringMemoryStream();
     kdb.Save(sOutput, app.GetDb().KpDatabase.RootGroup, KdbxFormat.PlainXml, null);
     return sOutput.Text;
 }
示例#22
0
 private void DisplayGroups(IKp2aApp app, string name)
 {
     LogDebug("Groups display: " + name);
     DisplayGroupRecursive(0, app.GetDb().Root);
 }
示例#23
0
 public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish) : base(activiy, finish, app)
 {
     Ctx    = activiy;
     Db     = app.GetDb();
     _entry = entry;
 }
示例#24
0
 public static bool ContainsAllTemplates(IKp2aApp app)
 {
     return(TemplateEntries.All(t => app.GetDb().Entries.ContainsKey(t.Uuid)));
 }
        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);
            }
        }
示例#26
0
 private void DisplayGroups(IKp2aApp app, string name)
 {
     LogDebug("Groups display: " + name);
     DisplayGroupRecursive(0, app.GetDb().Root);
 }
示例#27
0
            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);
                }
            }
示例#28
0
        public override void Run()
        {
            if (!_dontSave)
            {
                try
                {
                    if (_app.GetDb().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;
                    }

                    StatusLogger.UpdateMessage(UiStringKey.saving_database);
                    IOConnectionInfo ioc         = _app.GetDb().Ioc;
                    IFileStorage     fileStorage = _app.GetFileStorage(ioc);

                    if (_streamForOrigFile == null)
                    {
                        if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave)) ||
                            (_app.GetDb().KpDatabase.HashOfFileOnDisk == null))                                //first time saving
                        {
                            PerformSaveWithoutCheck(fileStorage, ioc);
                            Finish(true);
                            return;
                        }
                    }


                    if (
                        (_streamForOrigFile != null) ||
                        fileStorage.CheckForFileChangeFast(ioc, _app.GetDb().LastFileVersion) ||                          //first try to use the fast change detection
                        (FileHashChanged(ioc, _app.GetDb().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);
                                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);
            }
        }
示例#29
0
 public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish) : base(finish, app)
 {
     Ctx    = ctx;
     Db     = app.GetDb();
     _entry = entry;
 }
        public void TestLoadEditSaveWhenModified()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            IOConnection.DeleteFile(new IOConnectionInfo {
                Path = DefaultFilename
            });
            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app c: " + group.Name);
            }

            //load once more:
            var app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //modifiy once:
            PwGroup group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Apple);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app b: " + group.Name);
            }

            SaveDatabase(app2);

            _testCacheSupervisor.Reset();

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app d: " + group.Name);
            }
            Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle);
            _testCacheSupervisor.AssertNoCall();

            //modify the database by adding a group:
            PwGroup group1 = new PwGroup(true, true, "TestGroup", PwIcon.Apple);

            app.GetDb().KpDatabase.RootGroup.AddGroup(group1, true);

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app a: " + group.Name);
            }


            //save the database again:
            _testCacheSupervisor.Reset();
            SaveDatabase(app);
            Assert.AreEqual(((TestKp2aApp)app).LastYesNoCancelQuestionTitle, UiStringKey.TitleSyncQuestion);
            _testCacheSupervisor.AssertNoCall();


            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group1, true);
            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app: " + group.Name);
            }

            foreach (var group in resultApp.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("resultApp: " + group.Name);
            }

            //ensure the change was saved:
            AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
示例#31
0
        public override void Run()
        {
            //check if we will run into problems. Then finish with error before we start doing anything.
            foreach (var _elementToMove in _elementsToMove)
            {
                PwGroup pgParent = _elementToMove.ParentGroup;
                if (pgParent != _targetGroup)
                {
                    if (pgParent != null)
                    {
                        PwGroup group = _elementToMove as PwGroup;
                        if (group != null)
                        {
                            if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group)))
                            {
                                Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
                                return;
                            }
                        }
                    }
                }
            }

            foreach (var elementToMove in _elementsToMove)
            {
                _app.GetDb().Dirty.Add(elementToMove.ParentGroup);

                PwGroup pgParent = elementToMove.ParentGroup;
                if (pgParent != _targetGroup)
                {
                    if (pgParent != null) // Remove from parent
                    {
                        PwEntry entry = elementToMove as PwEntry;
                        if (entry != null)
                        {
                            pgParent.Entries.Remove(entry);
                            _targetGroup.AddEntry(entry, true, true);
                        }
                        else
                        {
                            PwGroup group = (PwGroup)elementToMove;
                            if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group)))
                            {
                                Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
                                return;
                            }
                            pgParent.Groups.Remove(group);
                            _targetGroup.AddGroup(group, true, true);
                        }
                    }
                }
            }


            _onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) =>
            {
                if (!success)
                {                       // Let's not bother recovering from a failure.
                    _app.LockDatabase(false);
                }
            }, OnFinishToRun);

            // Save
            SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, false);

            save.SetStatusLogger(StatusLogger);
            save.Run();
        }