/* This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin. Keepass2Android is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Keepass2Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Keepass2Android. If not, see . */ using System; using System.Collections.Generic; using Android.Content; using KeePassLib; using KeePassLib.Serialization; namespace keepass2android { public class Database { public Dictionary Groups = new Dictionary(new PwUuidEqualityComparer()); public Dictionary Entries = new Dictionary(new PwUuidEqualityComparer()); public HashSet Dirty = new HashSet(new PwGroupEqualityFromIdComparer()); public PwGroup Root; public PwDatabase KpDatabase; public IOConnectionInfo Ioc; public DateTime LastChangeDate; public SearchDbHelper SearchHelper; public IDrawableFactory DrawableFactory; readonly IKp2aApp _app; public Database(IDrawableFactory drawableFactory, IKp2aApp app) { DrawableFactory = drawableFactory; _app = app; } private bool _loaded; private bool _reloadRequested; public bool ReloadRequested { get { return _reloadRequested; } set { _reloadRequested = value; } } public bool Loaded { get { return _loaded;} set { _loaded = value; } } public bool Open { get { return Loaded && (!Locked); } } bool _locked; public bool Locked { get { return _locked; } set { _locked = value; } } public bool DidOpenFileChange() { if ((Loaded == false) || (Ioc.IsLocalFile() == false)) { return false; } return System.IO.File.GetLastWriteTimeUtc(Ioc.Path) > LastChangeDate; } public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, String password, String keyfile, UpdateStatus status) { Ioc = iocInfo; PwDatabase pwDatabase = new PwDatabase(); KeePassLib.Keys.CompositeKey key = new KeePassLib.Keys.CompositeKey(); key.AddUserKey(new KeePassLib.Keys.KcpPassword(password)); if (!String.IsNullOrEmpty(keyfile)) { try { key.AddUserKey(new KeePassLib.Keys.KcpKeyFile(keyfile)); } catch (Exception) { throw new KeyFileException(); } } pwDatabase.Open(iocInfo, key, status); if (iocInfo.IsLocalFile()) { LastChangeDate = System.IO.File.GetLastWriteTimeUtc(iocInfo.Path); } else { LastChangeDate = DateTime.MinValue; } Root = pwDatabase.RootGroup; PopulateGlobals(Root); Loaded = true; KpDatabase = pwDatabase; SearchHelper = new SearchDbHelper(app); } public bool QuickUnlockEnabled { get; set; } //KeyLength of QuickUnlock at time of loading the database. //This is important to not allow an attacker to set the length to 1 when QuickUnlock is started already. public int QuickUnlockKeyLength { get; set; } public PwGroup SearchForText(String str) { PwGroup group = SearchHelper.SearchForText(this, str); return group; } public PwGroup Search(SearchParameters searchParams) { return SearchHelper.Search(this, searchParams); } public PwGroup SearchForExactUrl(String url) { PwGroup group = SearchHelper.SearchForExactUrl(this, url); return group; } public PwGroup SearchForHost(String url, bool allowSubdomains) { PwGroup group = SearchHelper.SearchForHost(this, url, allowSubdomains); return group; } public void SaveData(Context ctx) { KpDatabase.UseFileTransactions = _app.GetBooleanPreference(PreferenceKey.UseFileTransactions); KpDatabase.Save(null); } private void PopulateGlobals (PwGroup currentGroup) { var childGroups = currentGroup.Groups; var childEntries = currentGroup.Entries; foreach (PwEntry e in childEntries) { Entries [e.Uuid] = e; } foreach (PwGroup g in childGroups) { Groups[g.Uuid] = g; PopulateGlobals(g); } } public void Clear() { Groups.Clear(); Entries.Clear(); Dirty.Clear(); DrawableFactory.Clear(); Root = null; KpDatabase = null; Ioc = null; _loaded = false; _locked = false; _reloadRequested = false; } public void MarkAllGroupsAsDirty() { foreach ( PwGroup group in Groups.Values ) { Dirty.Add(group); } } } }