Click here to Skip to main content
12,360,631 members (54,200 online)
Click here to Skip to main content

Stats

109.3K views
2.7K downloads
139 bookmarked
Posted

Windows Mobile Password Safe

, 12 Jan 2009 CPOL
A password safe with a touch screen UI introducing Fluid Controls.
Fluid.dll
passwords.pws
PasswordSafe.exe
PasswordSafe
Fluditity
bin
Classes
vssver2.scc
Controls
enums
vssver2.scc
Events
vssver2.scc
Interfaces
vssver2.scc
vssver2.scc
Fluid.csproj.user
GdiPlus
mssccprj.scc
NativeMethods
vssver2.scc
vssver2.scc
Native
vssver2.scc
obj
Properties
vssver2.scc
vssver2.scc
PasswordSafe
bin
Release
Fluid.dll
passwords.pws
PasswordSafe.exe
Classes
vssver2.scc
Encryption
vssver2.scc
EventArgs
vssver2.scc
ListBoxes
vssver2.scc
PasswordSafe.csproj.user
Properties
vssver2.scc
Resources
lock.bmp
minus.png
props.bmp
save.bmp
saved.bmp
search.bmp
searchd.bmp
undo24.bmp
undo24_d.bmp
Untitled.png
vssver2.scc
security.ico
Templates
vssver2.scc
Themes
vssver2.scc
vssver2.scc
Xml
vssver2.scc
vssver2.scc
using System;

using System.Collections.Generic;
using System.Text;
using PasswordSafe.Xml;
using Fluid.Controls;
using PasswordSafe.Properties;

namespace PasswordSafe.Classes
{
    /// <summary>
    /// Builds lists from data retreived from a PasswordReader to be used in ListBoxes.
    /// </summary>
    public class ListBuilder : IComparer<PasswordData>, IComparer<object>
    {
        private PasswordReader reader;

        private PasswordCategory defaultCategory;

        public PasswordCategory DefaultCategory
        {
            get
            {
                if (defaultCategory == null)
                {
                    CreateDefaultCategory();
                }
                return defaultCategory;
            }
        }

        /// <summary>
        /// Creates a new ListBuilder instance with data from a PasswordReader.
        /// </summary>
        /// <param name="reader">The PasswordReader class from which to retreive the data.</param>
        public ListBuilder(PasswordReader reader)
        {
            this.reader = reader;
        }

        private void CreateDefaultCategory()
        {
            PasswordCategory c = new PasswordCategory("Not Specified");
            c.IsDefault = true;
            c.Fields.Add(new FieldInfo("user", "Username"));
            c.Fields.Add(new FieldInfo("password", "Password"));
            c.Fields.Add(new FieldInfo("email", "EMail"));
            c.Fields.Add(new FieldInfo("url", "Url"));
            c.Fields.Add(new Separator());
            c.Fields.Add(new FieldInfo("info", "Info"));
            defaultCategory = c;
        }

        private NotifyList listBoxCategories;

        /// <summary>
        /// Gets an enumeration of all PasswordCategories.
        /// </summary>
        public IEnumerable<PasswordCategory> Categories
        {
            get
            {
                foreach (object item in listBoxCategories)
                {
                    PasswordCategory category = item as PasswordCategory;
                    if (category != null) yield return category;
                }
            }
        }

        /// <summary>
        /// Gets the list of categories including group headers for listboxes.
        /// </summary>
        public NotifyList ListBoxCategories
        {
            get { return GetCategories(); }
        }

        private NotifyList GetCategories()
        {
            if (listBoxCategories != null) return listBoxCategories;
            List<object> sortList = new List<object>();
            listBoxCategories = new NotifyList();
            foreach (PasswordCategory c in reader.Categories)
            {
                sortList.Add(c);
            }
            sortList.Add(DefaultCategory);
            sortList.Sort(this);
            foreach (object o in sortList) listBoxCategories.Add(o);
            all = new PasswordCategory("all");
            all.passwords = this.Passwords;
            all.ReadOnly = true;
            all.Title = "All Passwords";
            all.IsDefault = true;
            listBoxCategories.Insert(0, all);
            listBoxCategories.Insert(1, new GroupHeader());
            listBoxCategories.ModifyChanged += new EventHandler(ListModifyChanged);

            return listBoxCategories;
        }

        private PasswordCategory all;

        private List<PasswordData> passwords;

        public List<PasswordData> Passwords
        {
            get
            {
                EnsurePasswordList();
                return passwords;
            }
        }

        private bool modified;
        /// <summary>
        /// Gets if the data was modified and needs to be saved.
        /// </summary>
        public bool Modified
        {
            get { return modified; }
            set
            {
                if (modified != value)
                {
                    modified = value;
                    OnModifiedChanged();
                }
            }
        }

        private void OnModifiedChanged()
        {
            if (ModifiedChanged != null) ModifiedChanged(this, EventArgs.Empty);
        }


        public event EventHandler ModifiedChanged;

        void EnsurePasswordList()
        {
            if (passwords == null)
            {
                passwords = new List<PasswordData>();
                PasswordCategory defautCategory = DefaultCategory;
                foreach (PasswordData d in reader.Passwords)
                {
                    if (d.Category == null)
                    {
                        d.Category = defaultCategory;
                    }
                    passwords.Add(d);
                }
                passwords.Sort(this);
            }
        }

        private NotifyList currentPasswords;
        private List<object> passwordCopy = new List<object>();

        public NotifyList GetPasswords(PasswordCategory category, bool headers)
        {
            if (category == all) category = null;
            EnsurePasswordList();
            List<PasswordData> passwords = new List<PasswordData>();
            foreach (PasswordData d in this.passwords)
            {
                if (category == null || d.Category == category)
                {
                    passwords.Add(d);
                }
            }
            passwords.Sort(this);
            NotifyList sorted = new NotifyList();

            foreach (PasswordData d in passwords)
            {
                sorted.Add(d);
            }
            passwords.Clear();
            if (headers && sorted.Count > 3) sorted = AddHeaders(sorted);
            sorted.ModifyChanged += new EventHandler(ListModifyChanged);

            currentPasswords = sorted;
            passwordCopy.Clear();
            foreach (var p in sorted)
            {
                passwordCopy.Add(p);
            }

            return sorted;
        }


        void ListModifyChanged(object sender, EventArgs e)
        {
            Modified = true;
        }

        private NotifyList AddHeaders(NotifyList passwords)
        {
            NotifyList list = new NotifyList();

            string current = "";

            foreach (PasswordData d in passwords)
            {
                string c = d.Name.Substring(0, 1).ToUpper();

                if (current != c)
                {
                    current = c;
                    list.Add(new GroupHeader(c));
                }
                list.Add(d);
            }
            list.ModifyChanged += new EventHandler(ListModifyChanged);
            return list;

        }

        #region IComparer<PasswordData> Members

        int IComparer<PasswordData>.Compare(PasswordData x, PasswordData y)
        {
            return x.Name.CompareTo(y.Name);
        }

        #endregion

        #region IComparer<object> Members

        int IComparer<object>.Compare(object x, object y)
        {
            PasswordCategory a = x as PasswordCategory;
            if (a != null)
            {
                PasswordCategory b = y as PasswordCategory;
                return a.Name.CompareTo(b.Name);
            }
            return 0;
        }

        #endregion

        /// <summary>
        /// Gets or sets the instance for global use.
        /// </summary>
        /// <remarks>
        /// The main form sets the instance while other controls access the instance.
        /// </remarks>
        public static ListBuilder Instance;

        /// <summary>
        /// Creates a list of details of a password.
        /// </summary>
        /// <param name="password">the data of the password.</param>
        /// <param name="newItem">true if this password is new, otherwise false.</param>
        /// <returns></returns>
        public NotifyList GetDetails(PasswordData password, bool newItem)
        {
            NotifyList list = new NotifyList();

            PasswordCategory c = password.Category;

            if (c.Fields.Count == 0) c = DefaultCategory;

            foreach (FieldInfo field in c.Fields)
            {
                Separator separator = field as Separator;
                if (separator == null)
                {
                    string name = field.Name;
                    string value = password.Values[name];

                    PWNameValue item = new PWNameValue(field.Title + ":", field.Name, password);
                    list.Add(item);
                }
                else
                {
                    GroupHeader header = new GroupHeader(separator.Title);
                    list.Add(header);
                }
            }
            if (newItem)
            {
                PWNameValue nameValue = new PWNameValue("Name", "name", password);
                list.Insert(0, nameValue);
                GroupHeader gh = list[1] as GroupHeader;
                if (gh == null)
                {
                    list.Insert(1, new GroupHeader());
                }
            }
            list.Modified = false;
            list.ModifyChanged += new EventHandler(ListModifyChanged);


            return list;
        }

        public PasswordData CreateNewPassword(PasswordCategory category)
        {
            EnsurePasswordList();
            PasswordData data = new PasswordData();
            data.Category = category;
            passwords.Add(data);
            return data;
        }

        public void DeletePassword(PasswordData password)
        {
            password.Category = null;
            Passwords.Remove(password);
        }

        public void AddCategory(PasswordCategory category)
        {
            string text = category.Title;
            for (int i = 2; i < listBoxCategories.Count; i++)
            {
                PasswordCategory c = listBoxCategories[i] as PasswordCategory;
                if (c != null)
                {
                    if (c.Name == category.Name) return; //already in list, so return.
                    if (c.Title.CompareTo(text) > 0)
                    {
                        listBoxCategories.Insert(i, category);
                        return;
                    }
                }
            }
            listBoxCategories.Add(category);
        }

        public void RemoveCategory(PasswordCategory category)
        {
            listBoxCategories.Remove(category);
        }


        private List<CategoryListBoxItem> defaultCategories;

        /// <summary>
        /// Gets the list of all default categories.
        /// </summary>
        public List<CategoryListBoxItem> DefaultCategories
        {
            get
            {
                return GetDefaultCategories();
            }
        }

        private List<CategoryListBoxItem> GetDefaultCategories()
        {
            if (defaultCategories == null)
            {
                defaultCategories = new List<CategoryListBoxItem>();
                string xml = Resources.Categories;
                foreach (PasswordCategory c in PasswordReader.ReadCategories(xml))
                {
                    bool isUsed = false;
                    CategoryListBoxItem item = new CategoryListBoxItem { Category = c, IsUsed = isUsed };
                    defaultCategories.Add(item);
                }
            }
            foreach (var c in defaultCategories)
            {
                c.IsUsed = IsCategoryUsed(c.Category.Name);
            }
            return defaultCategories;
        }

        private bool IsCategoryUsed(string categoryName)
        {
            foreach (var c in Categories)
            {
                if (c.Name.Equals(categoryName, StringComparison.InvariantCultureIgnoreCase)) return true;
            }
            return false;
        }

        internal void AddCategories(List<CategoryListBoxItem> categories)
        {
            listBoxCategories.RaiseListChangedEvents = false;
            foreach (var item in categories)
            {
                if (item.IsUsed)
                {
                    AddCategory(item.Category);
                }
                else
                {
                    PasswordCategory category = GetCategory(item.Category.Name);
                    if (category != null) RemoveCategory(category);
                }
            }
            listBoxCategories.RaiseListChangedEvents = true;
            listBoxCategories.ResetBindings();
        }

        private PasswordCategory GetCategory(string name)
        {
            foreach (var c in this.Categories)
            {
                if (c.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) return c;
            }
            return null;
        }

        char[] matrix;

        private char[] EnsureMatrix()
        {
            if (matrix == null)
            {
                matrix = new char[256];
                for (int i = 0; i <= 255; i++)
                {
                    char c = Char.ToLower(Convert.ToChar(i));

                    if ("1".IndexOf(c) >= 0) c = '1';
                    else if ("2abc".IndexOf(c) >= 0) c = '2';
                    else if ("3def".IndexOf(c) >= 0) c = '3';
                    else if ("3ghi".IndexOf(c) >= 0) c = '4';
                    else if ("5jkl".IndexOf(c) >= 0) c = '5';
                    else if ("6mno".IndexOf(c) >= 0) c = '6';
                    else if ("7pqrs".IndexOf(c) >= 0) c = '7';
                    else if ("8tuv".IndexOf(c) >= 0) c = '8';
                    else if ("9wxyz".IndexOf(c) >= 0) c = '9';
                    else if ("# ".IndexOf(c) >= 0) c = '#';
                    else if ("0+".IndexOf(c) >= 0) c = '0';
                    else if (c == '*') c = '*';
                    else c = '\0';

                    matrix[i] = c;
                }
            }
            return matrix;
        }

        private string MakeSearchable(string text)
        {
            StringBuilder sb = new StringBuilder();

            char[] matrix = EnsureMatrix();
            foreach (char c in text)
            {
                int i = (int)c;
                if (i > 255) i = 255;
                char mc = matrix[i];
                if (mc != '\0')
                {
                    sb.Append(mc);
                }
            }
            return sb.ToString();
        }

        public void Filter(string text)
        {
            if (currentPasswords == null) return;

            bool modified = this.Modified;
            bool empty = string.IsNullOrEmpty(text);
            List<object> toAdd = new List<object>();
            foreach (object o in passwordCopy)
            {
                bool match = empty;
                if (!match)
                {
                    PasswordData p = o as PasswordData;
                    if (p != null)
                    {
                        string compare = MakeSearchable(p.Name);
                        match = compare.IndexOf(text) >= 0;
                    }
                }
                if (match)
                {
                    toAdd.Add(o);
                }
            }
            currentPasswords.RaiseListChangedEvents = false;
            currentPasswords.Clear();
            foreach (object o in toAdd)
            {
                currentPasswords.Add(o);
            }
            currentPasswords.RaiseListChangedEvents = true;
            currentPasswords.ResetBindings();

            // do not accidantely mark the data as begin modified:
            this.Modified = modified;
        }

        public void UnModified()
        {
            Modified = false;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Thomas Gerber
Software Developer (Senior)
Germany Germany
MCPD
Enterprise Application Developer 3.5
Windows Developer 3.5
.ASP.NET Developer 3.5
.NET 2.0 Windows Developer
.NET 2.0 Web Developer
.NET 2.0 Enterprise Application Developer


MCTS
.NET 3.5 Windows Forms Applications
.NET 3.5 ASP.NET Applications
.NET 3.5, ADO.NET Application Development
.NET 3.5 WCF
.NET 3.5 WPF
.NET 3.5 WF
Microsoft SQL Server 2008, Database Development
.NET 2.0 Windows Applications
.NET 2.0 Web Applications
.NET 2.0 Distributed Applications
SQL Server 2005
Sharepoint Services 3.0 Application Development
Windows Vista Client Configuration

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160621.1 | Last Updated 12 Jan 2009
Article Copyright 2009 by Thomas Gerber
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid