Beispiel #1
0
        public PwGroup AddTemplates(out List <PwEntry> addedEntries)
        {
            if (TemplateEntries.GroupBy(e => e.Uuid).Any(g => g.Count() > 1))
            {
                throw new Exception("invalid UUIDs in template list!");
            }

            PwGroup templateGroup;

            if (!_app.CurrentDb.GroupsById.TryGetValue(_app.CurrentDb.KpDatabase.EntryTemplatesGroup, out templateGroup))
            {
                //create template group
                templateGroup = new PwGroup(true, true, _app.GetResourceString(UiStringKey.TemplateGroupName), PwIcon.Folder);
                _app.CurrentDb.KpDatabase.RootGroup.AddGroup(templateGroup, true);
                _app.CurrentDb.KpDatabase.EntryTemplatesGroup        = templateGroup.Uuid;
                _app.CurrentDb.KpDatabase.EntryTemplatesGroupChanged = DateTime.Now;
                _app.DirtyGroups.Add(_app.CurrentDb.KpDatabase.RootGroup);
                _app.CurrentDb.GroupsById[templateGroup.Uuid] = templateGroup;
                _app.CurrentDb.Elements.Add(templateGroup);
            }
            addedEntries = new List <PwEntry>();

            foreach (var template in TemplateEntries)
            {
                if (_app.CurrentDb.EntriesById.ContainsKey(template.Uuid))
                {
                    continue;
                }
                PwEntry entry = CreateEntry(template);
                templateGroup.AddEntry(entry, true);
                addedEntries.Add(entry);
                _app.CurrentDb.EntriesById[entry.Uuid] = entry;
            }
            return(templateGroup);
        }
Beispiel #2
0
        private void ConvertException(IOConnectionInfo ioc, WebException ex)
        {
            var response = ex.Response as HttpWebResponse;

            if ((response != null) && (response.StatusCode == HttpStatusCode.NotFound))
            {
                throw new FileNotFoundException(ex.Message, ioc.Path, ex);
            }
            if (ex.Status == WebExceptionStatus.TrustFailure)
            {
                throw new Exception(_app.GetResourceString(UiStringKey.CertificateFailure), ex);
            }
            var inner1 = ex.InnerException as IOException;

            if (inner1 != null)
            {
                var inner2 = inner1.InnerException;
                if (inner2 != null)
                {
                    if (inner2.Message.Contains("Invalid certificate received from server."))
                    {
                        throw new Exception(_app.GetResourceString(UiStringKey.CertificateFailure), ex);
                    }
                }
            }
        }
 public void UpdateMessage(UiStringKey stringKey)
 {
     if (_app != null)
     {
         UpdateMessage(_app.GetResourceString(stringKey));
     }
 }
Beispiel #4
0
        private Exception LogAndConvertJavaException(Exception e)
        {
            Kp2aLog.Log(e.Message);

            if (e is UserInteractionRequiredException)
            {
                return(e);
            }
            //seems like UserInteractionRequiredException is not propagated correctly into the C# world, we can't catch it
            // -> rethrow correctly here
            // Note: the Contains-check looks a bit broad, but it should be safe
            if (e.ToString().Contains("keepass2android.javafilestorage.UserInteractionRequiredException"))
            {
                throw new UserInteractionRequiredException();
            }

            Java.Lang.Exception exception = e as Java.Lang.Exception;
            if (exception != null)
            {
                var ex = new Exception(exception.LocalizedMessage ??
                                       e.Message ??
                                       _app.GetResourceString(UiStringKey.ErrorOcurred) + exception.GetType().Name, e);
                return(ex);
            }

            return(e);
        }
Beispiel #5
0
        protected void EnsureRecycleBinExists(ref PwGroup pgRecycleBin,
                                              ref bool bGroupListUpdateRequired)
        {
            if ((Db == null) || (Db.KpDatabase == null))
            {
                return;
            }

            if (pgRecycleBin == Db.KpDatabase.RootGroup)
            {
                pgRecycleBin = null;
            }

            if (pgRecycleBin == null)
            {
                pgRecycleBin = new PwGroup(true, true, App.GetResourceString(UiStringKey.RecycleBin),
                                           PwIcon.TrashBin)
                {
                    EnableAutoType  = false,
                    EnableSearching = false,
                    IsExpanded      = false
                };

                Db.KpDatabase.RootGroup.AddGroup(pgRecycleBin, true);
                Db.GroupsById[pgRecycleBin.Uuid] = pgRecycleBin;
                Db.Elements.Add(pgRecycleBin);
                Db.KpDatabase.RecycleBinUuid = pgRecycleBin.Uuid;

                bGroupListUpdateRequired = true;
            }
            else
            {
                System.Diagnostics.Debug.Assert(pgRecycleBin.Uuid.Equals(Db.KpDatabase.RecycleBinUuid));
            }
        }
Beispiel #6
0
        private void MergeIn(IFileStorage fileStorage, IOConnectionInfo ioc)
        {
            StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.SynchronizingDatabase));

            PwDatabase pwImp      = new PwDatabase();
            PwDatabase pwDatabase = _app.GetDb().KpDatabase;

            pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey);
            pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep();
            pwImp.MasterKey        = pwDatabase.MasterKey;
            var stream = GetStreamForBaseFile(fileStorage, ioc);

            _app.GetDb().DatabaseFormat.PopulateDatabaseFromStream(pwImp, stream, null);


            pwDatabase.MergeIn(pwImp, PwMergeMethod.Synchronize, null);
        }
Beispiel #7
0
        public PwGroup Search(Database database, SearchParameters sp, IDictionary <PwUuid, KeyValuePair <string, string> > resultContexts)
        {
            if (sp.RegularExpression)            // Validate regular expression
            {
                new Regex(sp.SearchString);
            }

            string  strGroupName = _app.GetResourceString(UiStringKey.search_results) + " (\"" + sp.SearchString + "\")";
            PwGroup pgResults    = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch)
            {
                IsVirtual = true
            };

            PwObjectList <PwEntry> listResults = pgResults.Entries;


            database.Root.SearchEntries(sp, listResults, resultContexts, new NullStatusLogger());


            return(pgResults);
        }
        private static PwEntry CreateCopy(PwEntry entry, IKp2aApp app)
        {
            var newEntry = entry.CloneDeep();

            newEntry.SetUuid(new PwUuid(true), true);             // Create new UUID
            string strTitle = newEntry.Strings.ReadSafe(PwDefs.TitleField);

            newEntry.Strings.Set(PwDefs.TitleField, new ProtectedString(
                                     false, strTitle + " - " + app.GetResourceString(UiStringKey.DuplicateTitle)));

            return(newEntry);
        }
Beispiel #9
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);
            }
        }
Beispiel #10
0
                public void AddToEntry(IKp2aApp app, PwEntry entry, int position)
                {
                    Dictionary <FieldType, string> fn = new Dictionary <FieldType, string>()
                    {
                        { FieldType.ProtectedInline, "Protected Inline" },
                        { FieldType.Inline, "Inline" }
                    };

                    string fieldKey = app.GetResourceString(FieldName);

                    entry.Strings.Set("_etm_position_" + fieldKey, new ProtectedString(false, position.ToString()));
                    entry.Strings.Set("_etm_title_" + fieldKey, new ProtectedString(false, fieldKey));
                    entry.Strings.Set("_etm_type_" + fieldKey, new ProtectedString(false, fn[Type]));
                }
Beispiel #11
0
        public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task)
        {
            _task = task;
            _handler = app.UiThreadHandler;
            _app = app;

            // Show process dialog
            _progressDialog = app.CreateProgressDialog(ctx);
            _progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
            _progressDialog.SetMessage("Initializing...");

            // Set code to run when this is finished
            _task.OnFinishToRun = new AfterTask(task.OnFinishToRun, _handler, _progressDialog);
            _task.SetStatusLogger(new ProgressDialogStatusLogger(_app, _handler, _progressDialog));
        }
Beispiel #12
0
        public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task)
        {
            _task    = task;
            _handler = app.UiThreadHandler;
            _app     = app;

            // Show process dialog
            _progressDialog = app.CreateProgressDialog(ctx);
            _progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
            _progressDialog.SetMessage("Initializing...");

            // Set code to run when this is finished
            _task.OnFinishToRun = new AfterTask(task.OnFinishToRun, _handler, _progressDialog);
            _task.SetStatusLogger(new ProgressDialogStatusLogger(_app, _handler, _progressDialog));
        }
        private void IocForCopySelected(IOConnectionInfo targetIoc)
        {
            PerformCopy(() =>
            {
                IOConnectionInfo sourceIoc = _selectedIoc;

                try
                {
                    CopyFile(targetIoc, sourceIoc);
                }
                catch (Exception e)
                {
                    return(() =>
                    {
                        ShowToast(_app.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message);
                        ReturnCancel();
                    });
                }


                return(() => { ReturnOk(targetIoc); });
            });
        }
        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);
            }
        }
Beispiel #15
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;
                            }
                        }
                    }
                }
            }

            HashSet <Database> removeDatabases = new HashSet <Database>();
            Database           addDatabase     = _app.FindDatabaseForElement(_targetGroup);

            if (addDatabase == null)
            {
                Finish(false, "Did not find target database. Did you lock it?");
                return;
            }

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


                PwGroup pgParent = elementToMove.ParentGroup;
                if (pgParent != _targetGroup)
                {
                    if (pgParent != null) // Remove from parent
                    {
                        PwEntry entry = elementToMove as PwEntry;
                        if (entry != null)
                        {
                            var dbRem = _app.FindDatabaseForElement(entry);
                            removeDatabases.Add(dbRem);
                            dbRem.EntriesById.Remove(entry.Uuid);
                            dbRem.Elements.Remove(entry);
                            pgParent.Entries.Remove(entry);
                            _targetGroup.AddEntry(entry, true, true);
                            addDatabase.EntriesById.Add(entry.Uuid, entry);
                            addDatabase.Elements.Add(entry);
                        }
                        else
                        {
                            PwGroup group = (PwGroup)elementToMove;
                            if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group)))
                            {
                                Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
                                return;
                            }

                            var dbRem = _app.FindDatabaseForElement(@group);
                            if (dbRem == null)
                            {
                                Finish(false, "Did not find source database. Did you lock it?");
                                return;
                            }

                            dbRem.GroupsById.Remove(group.Uuid);
                            dbRem.Elements.Remove(group);
                            removeDatabases.Add(dbRem);
                            pgParent.Groups.Remove(group);
                            _targetGroup.AddGroup(group, true, true);
                            addDatabase.GroupsById.Add(group.Uuid, group);
                            addDatabase.Elements.Add(group);
                        }
                    }
                }
            }



            //first save the database where we added the elements
            var allDatabasesToSave = new List <Database> {
                addDatabase
            };

            //then all databases where we removed elements:
            removeDatabases.RemoveWhere(db => db == addDatabase);
            allDatabasesToSave.AddRange(removeDatabases);

            int  indexToSave     = 0;
            bool allSavesSuccess = true;

            void ContinueSave(bool success, string message, Activity activeActivity)
            {
                allSavesSuccess &= success;
                indexToSave++;
                if (indexToSave == allDatabasesToSave.Count)
                {
                    OnFinishToRun.SetResult(allSavesSuccess);
                    OnFinishToRun.Run();
                    return;
                }
                SaveDb saveDb = new SaveDb(_ctx, _app, allDatabasesToSave[indexToSave], new ActionOnFinish(activeActivity, ContinueSave), false);

                saveDb.SetStatusLogger(StatusLogger);
                saveDb.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
                saveDb.Run();
            }

            SaveDb save = new SaveDb(_ctx, _app, allDatabasesToSave[0], new ActionOnFinish(ActiveActivity, ContinueSave), false);

            save.SetStatusLogger(StatusLogger);
            save.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
            save.Run();
        }
Beispiel #16
0
        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);
            }
        }
Beispiel #17
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();
        }
Beispiel #18
0
        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;
            }
        }
Beispiel #19
0
        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);
            }
        }