Re: Beagle Thunderbird Patch



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Aug darn, there goes some stupid fun, this one should have the actual
code ;)

Cheers,
Kevin Kubasik
240-838-6616
http://kubasik.net/blog


Pierre Östlund wrote:
> Didn't you forget the actual Thunderbird code in this patch? Seems to me 
> that this is only beagle-search code and Makefile updates?
> 
> Thanks!
> 
> Pierre
> 
> Kevin Kubasik wrote:
> Here she is, I'll also attach this in the bugzilla, but heres what we
> have, and its ready for SVN in my opinion. (Although, don't get too
> excited, were gonna have a long week of bugfixing ahead of us, its a
> boatload-of-code).
> 
> I'm going to be doing some more testing and possibly change some more
> stuff this evening, so I might send another e-mail with an updated patch
> (but its not super-likely).
> 
> 

> _______________________________________________
> Dashboard-hackers mailing list
> Dashboard-hackers gnome org
> http://mail.gnome.org/mailman/listinfo/dashboard-hackers
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iQIVAwUBRLpLav3xZFNDM330AQi8dA/9FsPe6DaSrlMgWlhfg/G9E1Im7xAHmdG0
qJE58lmott4ffGFTx0WVt1Wchk77Su5VEmVEBoCvUAGyMx/ncTJPBX/aXGotqaaR
1gdRKwOOH0aIBYMvB+IQrKG2lzkLRcUhP8TNZaAt0ciMbQDCEJhm2DE313S9BXTh
uuzNlrVB3Z0y7QCAcFUTenuIiixSNXFozcprJ3jPBB1bXcZbvDQtlAr0D49bFjL5
kXOqP+tbJjIZbJCVrrJI7Yux9wtujxTxYeAAR8i8vXjvkFkaQ2ql2msQwAchNRKV
VbPzcx3lJSWUHFkjIUS1sAqtfsN82+Dztx+4Vudjp122HzxtUPCuywdUNWiIzP9k
XAY4F4mL+Bw8v8PxmYp9lhui+WlnucLFkBh85vlBzkKfl0FZBn+bGQO9GBJ5vmwM
uf+VWqRy1e26L2deJuFGcPgmNz1EsLg0mgBCpssTW56v6AqWSb3EVVXOZdhNt9Nk
W6JUoE6qwMkVaYiUFt95wbhCc8FimIxs2foC3a0lWIgdtObykAKngsYkaip2A3tL
pGY+XZMcMBNlcEL7lFFjslNk+LgMrm9XhBc+/ou1rmaYFku9PNeJNccCnENRrpuk
6dCTMnI44rwaC6jy20B1l1M71+UcCal0Mu3yjLPgxp2rbMPlSFM4B/ZlOlNqCcel
yXOBZ0FalLE=
=NVcb
-----END PGP SIGNATURE-----
Index: search/Tiles/MailAttachment.cs
===================================================================
--- search/Tiles/MailAttachment.cs	(revision 2690)
+++ search/Tiles/MailAttachment.cs	(working copy)
@@ -22,13 +22,13 @@
 			if (! base.Validate (hit))
 				return false;
 
-			string str = hit ["parent:fixme:hasAttachments"];
-
+			string str = hit.GetFirstProperty ("parent:fixme:hasAttachments");
+			//Console.WriteLine (str);
 			if (hit.ParentUri == null || str == null || str == "false")
 				return false;
 
-			str = hit ["fixme:attachment_title"];
-
+			str = hit.GetFirstProperty ("fixme:attachment_title");
+			//Console.WriteLine (str);
 			if (str == null || str == "")
 				return false;
 
@@ -69,25 +69,30 @@
 
 		public override void Open ()
 		{
-			if (GetHitProperty (Hit, "fixme:client") != "evolution") {
+			SafeProcess p = MailMessage.GetClientProcess (GetHitProperty (Hit, "fixme:client"));
+
+			if (p == null) {
 				OpenFromMime (Hit);
 				return;
 			}
 
-			SafeProcess p = new SafeProcess ();
-			p.Arguments = new string [2];
-			p.Arguments [0] = "evolution";
-
 			if (Hit.ParentUriAsString != null)
-				p.Arguments [1] = Hit.ParentUriAsString;
+				p.Arguments [p.Arguments.Length-1] = Hit.ParentUriAsString;
 			else
-				p.Arguments [1] = Hit.UriAsString;
+				p.Arguments [p.Arguments.Length-1] = Hit.UriAsString;
 
 			try {
 				p.Start ();
 			} catch (SafeProcessException e) {
 				Console.WriteLine ("Unable to run {0}: {1}", p.Arguments [0], e.Message);
+				p.Arguments [0] = "mozilla-thunderbird";
+				try {
+					p.Start();
+				} catch (SafeProcessException e2) {
+					Console.WriteLine ("Unable to run {0}: {1}", p.Arguments [0], e2.Message);
+				}
 			}
-		}	
+		}
+		
 	}
 }
Index: search/Tiles/MailMessage.cs
===================================================================
--- search/Tiles/MailMessage.cs	(revision 2690)
+++ search/Tiles/MailMessage.cs	(working copy)
@@ -1,5 +1,6 @@
 using System;
 using System.Diagnostics;
+using System.IO;
 using Mono.Unix;
 using Beagle.Util;
 
@@ -93,30 +94,55 @@
 			details.AddLabelPair (label, Utils.NiceLongDate (Timestamp));
 
 			details.AddSnippet ();
+			//Console.WriteLine ( details.snippet_text );
 
 			return details;
 		}
 
+		public static SafeProcess GetClientProcess (string client)
+		{
+			SafeProcess p = null;
+
+			if (client == "evolution") {
+				p = new SafeProcess ();
+				p.Arguments = new string [2];
+				p.Arguments [0] = "evolution";
+			} else if (client == "thunderbird") {
+				
+
+				p = new SafeProcess ();
+				p.Arguments = new string [3];
+				p.Arguments [0] = "thunderbird";
+				p.Arguments [1] = "-mail";
+			}
+
+			return p;
+		}
+
 		public override void Open ()
 		{
-			if (Hit.GetFirstProperty ("fixme:client") != "evolution") {
+			SafeProcess p = GetClientProcess (Hit.GetFirstProperty ("fixme:client"));
+
+			if (p == null) {
 				OpenFromMime (Hit);
 				return;
 			}
 
-			SafeProcess p = new SafeProcess ();
-			p.Arguments = new string [2];
-			p.Arguments [0] = "evolution";
-
 			if (Hit.ParentUriAsString != null)
-				p.Arguments [1] = Hit.ParentUriAsString;
+				p.Arguments [p.Arguments.Length-1] = Hit.ParentUriAsString;
 			else
-				p.Arguments [1] = Hit.UriAsString;
+				p.Arguments [p.Arguments.Length-1] = Hit.UriAsString;
 
 			try {
 				p.Start ();
 			} catch (SafeProcessException e) {
 				Console.WriteLine ("Unable to run {0}: {1}", p.Arguments [0], e.Message);
+				p.Arguments [0] = "mozilla-thunderbird";
+				try {
+					p.Start();
+				} catch (SafeProcessException e2) {
+					Console.WriteLine ("Unable to run {0}: {1}", p.Arguments [0], e2.Message);
+				}
 			}
 		}
 
Index: search/Tiles/Contact.cs
===================================================================
--- search/Tiles/Contact.cs	(revision 2690)
+++ search/Tiles/Contact.cs	(working copy)
@@ -78,10 +78,30 @@
 			return details;
 		}
 
+		public static SafeProcess GetClientProcess (string client)
+		{
+			SafeProcess p = null;
+
+   			if (client == "evolution") {
+				p = new SafeProcess ();
+				p.Arguments = new string [2];
+				p.Arguments [0] = "evolution";
+			} else if (client == "thunderbird") {
+				p = new SafeProcess ();
+				p.Arguments = new string [4];
+				p.Arguments [0] = "beagle-contactviewer";
+				p.Arguments [1] = "--manager";
+				p.Arguments [2] = "Thunderbird";
+			}
+
+			return p;
+                }
+
+
 		public override void Open ()
 		{
-			SafeProcess p = new SafeProcess ();
-			p.Arguments = new string [] { "evolution", Hit.UriAsString };
+			SafeProcess p = GetClientProcess (Hit.GetFirstProperty ("fixme:client"));
+			p.Arguments [p.Arguments.Length-1] = Hit.UriAsString;
 
 			try {
 				p.Start ();
Index: Util/Thunderbird.cs
===================================================================
--- Util/Thunderbird.cs	(revision 0)
+++ Util/Thunderbird.cs	(revision 0)
@@ -0,0 +1,822 @@
+//
+// Thunderbird.cs: A utility class with methods and classes that might be needed to parse Thunderbird data
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+using Beagle;
+using Beagle.Util;
+
+using GMime;
+
+namespace Beagle.Util {
+
+	public class Thunderbird {
+	
+		public static bool Debug = false;
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+	
+		public enum AccountType {
+			Pop3,
+			Imap,
+			Rss,
+			Nntp,
+			AddressBook,
+			MoveMail,
+			Invalid
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		public class Account {
+			private string server_string = null;
+			private string path = null;
+			private int server_port = -1;
+			private AccountType account_type;
+			private char delimiter;
+			
+			public Account (string server, string path, int port, AccountType type, char delim)
+			{
+				this.server_string = server;
+				this.path = path;
+				this.server_port = port;
+				this.account_type = type;
+				this.delimiter = delim;
+			}
+
+			public string Server {
+				get { return server_string; }
+			}
+			
+			public string Path {
+				get { return path; }
+			}
+			
+			public int Port {
+				get { return (server_port > 0 ? server_port : Thunderbird.ParsePort (Type)); }
+			}
+			
+			public AccountType Type {
+				get { return account_type; }
+			}
+			
+			public char Delimiter {
+				get { return (delimiter ==  char.MinValue ? '/' : delimiter); }
+			}
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		public class StorageBase {
+			protected Hashtable data;
+			protected System.Uri uri;
+			protected Account account;
+			
+			public StorageBase ()
+			{
+				data = new Hashtable ();
+			}
+			
+			public string GetString (string key)
+			{
+				return Convert.ToString (data [key]);
+			}
+			
+			public int GetInt (string key)
+			{
+				try {
+					if (!data.ContainsKey (key))
+						return -1;
+					
+					return Convert.ToInt32 (data [key]);
+				} catch (Exception e) {
+					return -1;
+				}
+			}
+			
+			public bool GetBool (string key)
+			{
+				try {
+					return Convert.ToBoolean (data [key]);
+				} catch (Exception e) {
+					return false;
+				}
+			}
+			
+			public object GetObject (string key)
+			{
+				return data [key];
+			}
+			
+			public void SetObject (string key, object value)
+			{
+				if (key != null)
+					data [key] = value;
+			}
+			
+			public System.Uri Uri {
+				get { return uri; }
+				set { uri = value; }
+			}
+			
+			public Account Account {
+				get { return account; }
+			}
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		// String types:
+		// id, sender, subject, recipients, date, mailbox
+		// Integer types:
+		// size, msgOffset, offlineMsgSize
+		// Bool types:
+		// FullIndex
+		public class Mail : StorageBase {
+			private string workfile;
+		
+			public Mail (Account account, Hashtable data, string workfile)
+			{
+				foreach (string key in data.Keys) {
+					if (key == "id")
+						SetObject (key, data [key]);
+					else if (key == "sender")
+						SetObject (key, Utils.HeaderDecodePhrase ((string) data [key]));
+					else if (key == "subject")
+						SetObject (key, Utils.HeaderDecodeText ((string) data [key]));
+					else if (key == "recipients")
+						SetObject (key, Utils.HeaderDecodePhrase ((string) data [key]));
+					else if (key == "date")
+						SetObject (key, Thunderbird.HexDateToString ((string) data [key]));
+					else if (key == "size")
+						SetObject (key, Thunderbird.Hex2Dec ((string) data [key]));
+					else if (key == "msgOffset")
+						SetObject (key, Thunderbird.Hex2Dec ((string) data[key]));
+					else if (key == "offlineMsgSize")
+						SetObject (key, Thunderbird.Hex2Dec ((string) data [key]));
+					else if (key == "message-id")
+						SetObject (key, (string) data [key]);
+					else if (key == "references")
+						SetObject (key, (data [key] as string).Replace ("\\", ""));
+				}
+				
+				this.account = account;
+				this.workfile = workfile;
+				SetObject ("mailbox", Thunderbird.ConstructMailboxString (workfile, account));
+				this.uri = Thunderbird.NewUri (Account, GetString ("mailbox"), GetString ("id"));
+			}
+			
+			private GMime.Message ConstructMessage ()
+			{
+				GMime.Message message = null;
+				
+				// Try to fully index this mail by loading the entire mail into memory
+				if (GetBool ("FullIndex"))
+					message = FullMessage ();
+				
+				// Make sure we have the correct status set on this message, in case something went wrong
+				if (message == null || (message != null && message.Stream.Length <= 1)) {
+					SetObject ("FullIndex", (object) false);
+					return PartialMessage ();
+				} else 
+					return message;
+			}
+			
+			private GMime.Message PartialMessage ()
+			{
+				string date = GetString ("date");
+				GMime.Message message = new GMime.Message (true);
+
+				message.Subject = GetString ("subject");
+				message.Sender = GetString ("sender");
+				message.MessageId = GetString ("message-id");
+				message.SetDate ((date != string.Empty ? DateTime.Parse (date) : new DateTime (1970, 1, 1, 0, 0, 0)), 0);
+				
+				// Add references
+				if (data.ContainsKey ("references")) {
+					foreach (Match m in Regex.Matches ((data ["references"] as string), @"\<(?>[^\<\>]+)\>"))
+						message.AddHeader ("References", m.Value);
+				}
+				
+				return message;
+			}
+
+			private GMime.Message FullMessage ()
+			{
+				int fd;
+				string file = Thunderbird.GetFullyIndexableFile (workfile);
+				GMime.Message message = null;
+
+				// gmime will go nuts and make the daemon "segmentation fault" in case the file doesn't exist!
+				if (!File.Exists (file))
+					return message;
+
+				try {
+					fd = Mono.Unix.Native.Syscall.open (file, Mono.Unix.Native.OpenFlags.O_RDONLY);
+					StreamFs stream = new StreamFs (fd, Offset, Offset + Size);
+					Parser parser = new Parser (stream);
+					message = parser.ConstructMessage ();
+				
+					stream.Dispose ();
+					parser.Dispose ();
+				} catch (Exception e) {}
+
+				return message;
+			}
+			
+			public int Offset {
+				get {
+					int msg_offset = GetInt ("msgOffset"); 
+					return (msg_offset >= 0 ? msg_offset : Thunderbird.Hex2Dec (GetString ("id"))); 
+				}
+			}
+			
+			public int Size {
+				get {
+					int msg_offline_size = GetInt ("offlineMsgSize");
+					return (msg_offline_size >= 0 ? msg_offline_size : GetInt ("size")); 
+				}
+			}
+
+			public GMime.Message Message {
+				get { return ConstructMessage (); }
+			}
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		// String types:
+		// id, FirstName, LastName, DisplayName, NickName, PrimaryEmail, SecondEmail,
+		// WorkPhone, FaxNumber, HomePhone, PagerNumber, CellularNumber, HomeAddress,
+		// HomeAddress2, HomeCity, HomeState, HomeZipCode,  HomeCountry, WorkAddress,
+		// WorkAddress2, WorkCity, WorkState, WorkZipCode, WorkCountry, JobTitle, Department,
+		// Company, _AimScreenName, FamilyName, WebPage1, WebPage2, BirthYear, BirthMonth
+		// , BirthDay, Custom1, Custom2, Custom3, Custom4, Notes, PreferMailFormat
+		// Integer types:
+		// None
+		public class Contact : StorageBase {
+			private string workfile;
+		
+			public Contact (Account account, Hashtable data, string workfile)
+			{
+				this.account = account;
+				this.data = data;
+				this.workfile = workfile;
+				this.uri = NewUri (account, Thunderbird.ConstructMailboxString (workfile, account), GetString ("id"));
+			}
+			
+			public string Workfile {
+				get { return workfile; }
+			}
+		
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		// String types:
+		// id, subject, sender, date, message-id
+		// Integer types:
+		// size
+		public class RssFeed : StorageBase {
+			private string workfile;
+		
+			public RssFeed (Account account, Hashtable data, string workfile)
+			{
+				foreach (string key in data.Keys) {
+					if (key == "id")
+						SetObject (key, data [key]);
+					else if (key == "subject") // title
+						SetObject (key, Utils.HeaderDecodePhrase ((string) data [key]));
+					else if (key == "sender") // publisher
+						SetObject (key, Utils.HeaderDecodePhrase ((string) data [key]));
+					else if (key == "date") // date
+						SetObject (key, HexDateToString ((string) data [key]));
+					else if (key == "size") // size
+						SetObject (key, Hex2Dec ((string) data [key]));
+					else if (key == "message-id") { // links
+						string tmp = (string) data [key];
+						SetObject (key, Utils.HeaderDecodePhrase (tmp.Substring (0, tmp.LastIndexOf ("@"))));
+					}
+				}
+				
+				this.account = account;
+				this.workfile = workfile;
+				this.uri = NewUri (account, ConstructMailboxString (workfile, account), GetString ("id"));
+			}
+			
+			// FIXME: Make this a lot faster!
+			private StringReader ConstructContent ()
+			{
+				string content = null;
+				string file = GetFullyIndexableFile (workfile);
+				
+				if (!File.Exists (file))
+					return null;
+				
+				try {
+					StreamReader reader = new StreamReader (file);
+					
+					char[] tmp = new char [GetInt ("size")];
+					reader.BaseStream.Seek (Hex2Dec (GetString ("id")), SeekOrigin.Begin);
+					reader.Read (tmp, 0, tmp.Length);
+					
+					// We don't want to index all HTTP headers, so we cut 'em off
+					content = new string (tmp);
+					content = content.Substring (content.IndexOf ("<html>"));
+					
+					reader.Close ();
+				} catch (Exception e) { }
+				
+				return (content != null ? new StringReader (content) : null);
+			}
+			
+			public string Workfile {
+				get { return workfile; }
+			}
+			
+			public StringReader Content {
+				get { return ConstructContent (); }
+			}
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		// String types:
+		// id, subject, sender, date
+		// Integer types:
+		// size
+		// An NNTP message resambles a mail so very much...
+		public class NntpMessage : Mail {
+		
+			public NntpMessage (Account account, Hashtable data, string workfile)
+				: base (account, data, workfile)
+			{
+				foreach (string key in data.Keys) {
+					if (key == "id")
+						SetObject (key,  data [key]);
+					else if (key == "subject")
+						SetObject (key, Utils.HeaderDecodeText ((string) data [key]));
+					else if (key == "sender")
+						SetObject (key, Utils.HeaderDecodePhrase ((string) data [key]));
+					else if (key == "date")
+						SetObject (key, Thunderbird.HexDateToString ((string) data [key]));
+					else if (key == "size")
+						SetObject (key, Thunderbird.Hex2Dec ((string) data [key]));
+				}
+				
+				Uri = NewUri (account, ConstructMailboxString (workfile, account), GetString ("id"));
+			}
+		
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		// Still just a stub, will be fixed later on
+		public class MoveMail : StorageBase {
+		
+			public MoveMail (Account account, Hashtable data, string workfile)
+			{
+				this.account = account;
+				this.data = data;
+				//this.workfile = workfile;
+				this.uri = NewUri (account, GetString ("tmp"), GetString ("id"));
+			}
+		
+		}
+
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		public class Database : IEnumerable {
+			private static MorkDatabase db;
+			private Account account;
+			private string file;
+			
+			private IEnumerator current = null;
+
+			public Database (Account account, string file)
+			{
+				this.account = account;
+				this.file = file;
+			}
+			
+			public void Load ()
+			{
+				db = new MorkDatabase (file);
+				db.Read();
+				
+				switch (account.Type) {
+				case AccountType.Pop3:
+				case AccountType.Imap:
+				case AccountType.Rss:
+				case AccountType.Nntp:
+				case AccountType.MoveMail:
+					db.EnumNamespace = "ns:msg:db:row:scope:msgs:all";
+					break;
+				case AccountType.AddressBook:
+					db.EnumNamespace = "ns:addrbk:db:row:scope:card:all";
+					break;
+				}
+				
+				current = db.GetEnumerator ();
+			}
+			
+			public Account Account {
+				get { return account; }
+			}
+			
+			public int Count {
+				get {
+					if (db == null)
+						return 0;
+						
+					return (account.Type == AccountType.AddressBook ? 
+						db.GetRowCount ("ns:addrbk:db:row:scope:card:all", "BF") : 
+						db.GetRowCount ("ns:msg:db:row:scope:msgs:all"));
+				}
+			}
+			
+			public string Filename {
+				get { return (db != null ? db.Filename : string.Empty); }
+			}
+			
+			public MorkDatabase Db {
+				get { return db; }
+			}
+			
+			public IEnumerator GetEnumerator ()
+			{
+				return new DatabaseEnumerator (db, account, current);
+			}
+			
+			public class DatabaseEnumerator : IEnumerator {
+				private MorkDatabase db;
+				private Account account;
+				private IEnumerator enumerator;
+
+				public DatabaseEnumerator (MorkDatabase db, Account account, IEnumerator enumerator)
+				{
+					this.db = db;
+					this.enumerator = enumerator;
+					this.account = account;
+				}
+				
+				public bool MoveNext ()
+				{
+					return (enumerator != null ? enumerator.MoveNext () : false);
+				}
+				
+				public void Reset ()
+				{
+					enumerator.Reset ();
+				}
+				
+				public object Current {
+					get { 
+						switch (account.Type) {
+						case AccountType.Pop3:
+						case AccountType.Imap:
+							return new Mail (account, db.Compile ((string) enumerator.Current, 
+								"ns:msg:db:row:scope:msgs:all"), db.Filename); 
+						case AccountType.AddressBook:
+							return new Contact (account, db.Compile ((string) enumerator.Current,
+								"ns:addrbk:db:row:scope:card:all"), db.Filename);
+						case AccountType.Rss:
+							return new RssFeed (account, db.Compile ((string) enumerator.Current, 
+								"ns:msg:db:row:scope:msgs:all"), db.Filename);
+						case AccountType.Nntp:
+							return new NntpMessage (account, db.Compile ((string) enumerator.Current, 
+								"ns:msg:db:row:scope:msgs:all"), db.Filename);
+						case AccountType.MoveMail:
+							return new MoveMail (account, db.Compile ((string) enumerator.Current,
+								"ns:msg:db:row:scope:msgs:all"), db.Filename);
+						}
+						
+						return null;
+					}
+				}
+			}
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+
+		public static string HexDateToString (string hex)
+		{
+			DateTime time = new DateTime (1970,1,1,0,0,0);
+			
+			try {
+				time = time.AddSeconds (
+					Int32.Parse (hex, NumberStyles.HexNumber));
+			} catch (Exception e) {}
+			
+			return time.ToString ();
+		}
+		
+		public static int Hex2Dec (string hex)
+		{
+			int dec = -1;
+			
+			try {
+				dec = Convert.ToInt32 (hex, 16);
+			} catch (Exception e) { }
+			
+			return dec;
+		}
+		
+		public static int ParsePort (AccountType type)
+		{
+			int port = 0;
+			
+			switch (type) {
+			case AccountType.Pop3:
+				port = 110;
+				break;
+			case AccountType.Imap:
+				port = 143;
+				break;
+			}
+			
+			return port;
+		}
+		
+		public static AccountType ParseAccountType (string type_str)
+		{
+			AccountType type;
+			
+			try {
+				type = (AccountType) Enum.Parse (typeof (AccountType), type_str, true);
+			} catch {
+				type = AccountType.Invalid;
+			}
+			
+			return type;
+		}
+		
+		// A hack to extract a potential delimiter from a namespace-string
+		public static char GetDelimiter (string[] namespace_str)
+		{
+			MatchCollection matches = null;
+			Regex reg = new Regex (@"\\\""(.*)(?<delimiter>[^,])\\\""", RegexOptions.Compiled);
+			
+			if (namespace_str == null)
+				return char.MinValue;
+			
+			foreach (string str in namespace_str) {
+				try {
+					matches = reg.Matches (str);
+				} catch (Exception e) {
+					continue;
+				}
+
+				foreach (Match m in matches) {
+					char delim = Convert.ToChar (m.Result ("${delimiter}"));
+					if (delim != ' ')
+						return delim;
+				}
+			}
+			
+			return char.MinValue;
+		}
+		
+		public static Uri NewUri (Account account, string mailbox, string id)
+		{
+			Uri uri = null;
+
+			switch (account.Type) {
+				case AccountType.Pop3:
+				case AccountType.MoveMail:
+				case AccountType.Rss: // rss, movemail and pop3 share the same uri scheme
+					uri = new Uri (String.Format ("mailbox://{0}/{1}?number={2}", 
+						account.Path, mailbox, Convert.ToInt32 (id, 16))); 
+					break;
+				case AccountType.Imap:
+					uri = new Uri (String.Format ("imap://{0}:{1}/fetch%3EUID%3E{2}%3E{3}",
+						account.Server, account.Port, mailbox, Convert.ToInt32 (id, 16)));
+					break;
+				case AccountType.AddressBook:
+					uri = new Uri (String.Format ("abook://{0}?id={1}", mailbox, id));
+					break;
+				case AccountType.Nntp:
+					uri = new Uri (String.Format ( "news://{0}:{1}/{2}?number={3}"; , 
+						new string[] {account.Server, account.Port.ToString(), mailbox, id} ));
+					break;
+				case AccountType.Invalid:
+					break;
+			}
+			
+			return uri;
+		}
+		
+		public static  string GetFullyIndexableFile (string mork_file)
+		{
+			string mailbox_file = Path.Combine (
+				Path.GetDirectoryName (mork_file), 
+				Path.GetFileNameWithoutExtension (mork_file));
+			
+			return mailbox_file;
+		}
+		
+		// a generic way to determine where thunderbird is storing it's files
+		public static string GetRootPath ()
+		{
+			foreach (string dir in Directory.GetDirectories (PathFinder.HomeDir, ".*thunderbird*")) {
+				if (File.Exists (Path.Combine (dir, "profiles.ini")))
+					return dir;
+			}
+			
+			return null;
+		}
+		
+		public static string[] GetProfilePaths (string root)
+		{
+			string line;
+			StreamReader reader;
+			ArrayList profiles = new ArrayList ();
+			
+			try {
+				reader = new StreamReader (Path.Combine (root, "profiles.ini"));
+			} catch (Exception e) { 
+				return (string[]) profiles.ToArray ();
+			}
+			
+			// Read the profile path
+			while ((line = reader.ReadLine ()) != null) {
+				if (line.StartsWith ("Path=")) {
+					profiles.Add (String.Format ("{0}/{1}", root, line.Substring (5)));
+					continue;
+				}
+			}
+
+			return (string[]) profiles.ToArray (typeof (string));
+		}
+		
+		public static string GetRelativePath (string mork_file)
+		{
+			string path = null;
+			foreach (string root in Thunderbird.GetProfilePaths (Thunderbird.GetRootPath ())) {
+				if (!mork_file.StartsWith (root))
+					continue;
+
+				path = mork_file.Substring (root.Length+1);
+				break;
+			}
+			
+			return path;
+		}
+		
+		public static ArrayList ReadAccounts (string profile_dir)
+		{
+			string line = null;
+			Queue accounts = new Queue();
+			Hashtable tbl = new Hashtable ();
+			ArrayList account_list = new ArrayList ();
+			StreamReader reader;
+			Regex id_reg = new Regex (@"account.account(?<id>\d).server");
+			Regex reg = new Regex (@"user_pref\(""mail\.(?<key>.*)""\s*,\s*(""(?<value>.*)"" | (?<value>.*))\);",
+				RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);
+
+			try {
+				reader = new StreamReader (Path.Combine (profile_dir, "prefs.js"));
+			} catch (Exception e) {
+				if (Debug)
+					Logger.Log.Debug ("Failed to open file {0}: {1}", Path.Combine (profile_dir , "prefs.js"), e.Message);
+
+				return account_list;
+			}
+
+			while ((line = reader.ReadLine()) != null) {
+				if (!line.StartsWith ("user_pref(\"mail."))
+					continue;
+
+				try {
+					string key = reg.Match (line).Result ("${key}");
+
+					if (key.StartsWith ("account.account")) {
+						if (Debug)
+							Logger.Log.Debug ("account.account: {0}", id_reg.Match (key).Result ("${id}"));
+
+						accounts.Enqueue (id_reg.Match (key).Result ("${id}"));
+					}
+
+					tbl [key] = reg.Match (line).Result ("${value}");
+				} catch (Exception e) { 
+					if (Debug)
+						Logger.Log.Debug ("ReadAccounts 1: {0}", e.Message);				
+				}
+			}
+			
+			if (Debug)
+				Logger.Log.Info ("ReadAccounts: {0} accounts", accounts.Count);
+
+			while (accounts.Count > 0) {
+				string id = "server.server" + (accounts.Dequeue() as string);
+				AccountType type = ParseAccountType ((string) tbl [id + ".type"]);
+				char delimiter = GetDelimiter (new string [] { (string) tbl [id + ".namespace.personal"], 
+					(string) tbl [id + ".namespace.public"], (string) tbl [id + ".namespace.other_users"]});
+				
+				if (type == AccountType.Invalid)
+					continue;
+				
+				if (Debug)
+					Logger.Log.Debug ("ReadAccounts 2: {0}", id);
+
+				try {
+					account_list.Add (new Account (
+						String.Format ("{0} {1}", (string) tbl [id + ".userName"], (string) tbl [id + ".hostname"]), 
+						(string) tbl [id + ".directory"], Convert.ToInt32 ((string) tbl [id + ".port"]), type, delimiter));
+				} catch (Exception e) {
+					if (Debug)
+						Logger.Log.Debug ("ReadAccounts 3: {0}", e.Message);
+					continue;
+				}
+			}
+			
+			// In case the address book file exists, add it as well
+			if (File.Exists (Path.Combine (profile_dir, "abook.mab"))) {
+				account_list.Add (new Account (Path.GetFileName (profile_dir), 
+					Path.Combine (profile_dir, "abook.mab"), 0, AccountType.AddressBook, ' '));
+			}
+
+			return account_list;
+		}
+		
+		public static bool IsMorkFile (string path, string filename)
+		{
+			string full_path = Path.Combine (path, filename);
+			
+			if (Path.GetExtension (filename) == ".msf" && File.Exists (full_path))
+				return true;
+		
+			return false;
+		}
+		
+		public static bool IsFullyIndexable (string mork_file)
+		{
+			try {
+				FileInfo file_info = new FileInfo (GetFullyIndexableFile (mork_file));
+				if (file_info.Length > 0)
+					return true;
+			} catch (Exception e) {}
+			
+			return false;
+		}
+		
+		public static string ConstructMailboxString (string mork_file, Account account)
+		{
+			string mailbox = null;
+
+			switch (account.Type) {
+			case AccountType.Pop3:
+			case AccountType.Rss:
+			case AccountType.MoveMail:
+				mailbox = GetFullyIndexableFile (mork_file.Substring (account.Path.Length+1));
+				break;
+			case AccountType.Imap:
+				mailbox = mork_file.Substring (account.Path.Length+1);
+				mailbox = account.Delimiter + GetFullyIndexableFile (mailbox).Replace 
+					(".sbd/", Convert.ToString (account.Delimiter));
+				break;
+			case AccountType.AddressBook:
+				mailbox = mork_file;
+				break;
+			case AccountType.Nntp:
+				// Doesn't really matter what this is as long as it's unique (at least until I've figure the uri schemes)
+				mailbox = account.Server;
+				break;
+			case AccountType.Invalid:
+				mailbox = String.Format ("InvalidMailbox-{0}", mork_file);
+				break;
+			}
+
+			return mailbox;
+		}
+	}
+
+}
Index: Util/Mork.cs
===================================================================
--- Util/Mork.cs	(revision 0)
+++ Util/Mork.cs	(revision 0)
@@ -0,0 +1,382 @@
+//
+// Mork.cs: A parser for mork files (used by software such as Firefox and Thunderbird)
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Text;
+using System.Collections;
+using System.Text.RegularExpressions;
+
+namespace Beagle.Util
+{
+	public class MorkDatabase : IEnumerable {
+		protected string mork_file;
+		protected string enum_namespace;
+		
+		protected Hashtable dicts;
+		protected Hashtable metadicts;
+		protected Hashtable rows;
+		protected Hashtable tables;
+		
+		protected string regex_dict = @"(?<id>\w+)\s*=(?<value>(?>[^()]+|\((?<n>)|\) (?<-n>))*)\)(\(|>)";
+		protected string regex_row = @"(?<action>[-!+]?)\[(-|)(?<roid>[0-9A-Za-z:\^]+)(?<cells>(?>[^\[\]]+)?)\]";
+		protected string regex_cell = @"\^(?<key>[0-9A-Fa-f]+)(\^(?<pvalue>[0-9A-Fa-f]+)|=(?<value>[0-9A-Fa-f]+))";
+		protected string regex_table = @"{.*?:(?<ns>[0-9A-Fa-f\^]+) {\(k\^(?<tbl>[0-9A-Fa-f]+):c\)";
+
+		public MorkDatabase (string mork_file)
+		{
+			this.mork_file = mork_file;
+			this.dicts = new Hashtable ();
+			this.metadicts = new Hashtable ();
+			this.rows = new Hashtable ();
+			this.tables = new Hashtable ();
+		}
+		
+		public void Read ()
+		{
+			string content;
+			StreamReader reader;
+			
+			reader = new StreamReader (mork_file);
+			content  = reader.ReadToEnd ();
+			reader.Close ();
+			
+			Reset ();
+			Read (content);
+		}
+
+		protected void Read (string content)
+		{
+			int position = -1;
+
+			while (++position != content.Length) {
+				
+				if (content [position].Equals ('/') && content [position].Equals ('/'))
+					// Ignore comments
+					position = content.IndexOf ('\n');
+				else if (content [position].Equals ('<') && content [position+2].Equals ('<'))
+					// Parse metadict information
+					ParseMetaDict (Read (content, ref position, "<(", ")>"));
+				else if (content [position].Equals ('<'))
+					// Parse dict information
+					ParseDict (Read (content, ref position, "<(", ")>"));
+				else if (content [position].Equals ('{')) {
+					// Parse table information
+					ParseTable (Read (content, ref position, "{", "}"));
+				 }else if (content [position].Equals ('[')) 
+					// Parse rows
+					ParseRows (Read (content, ref position, "[", "]"), null, null);
+				else if (content [position].Equals ('@') && content [position+1].Equals ('$'))
+					// Parse groups
+					ParseGroups (Read (content, ref position, "@$${", "@$$}"));
+			}
+		}
+		
+		protected string Read (string content, ref int position, string start, string end)
+		{
+			int tmp = position, start_position = position;
+			
+			do {
+				position = content.IndexOf (end, position+1);
+				if ((tmp = content.IndexOf (start, tmp+1)) < 0)
+					break;
+			} while (tmp < position);
+			
+			return content.Substring (start_position, position-start_position+1);
+		}
+		
+		protected virtual void ParseDict (string dict)
+		{
+			Regex reg = new Regex (@"(?<id>[0-9A-Fa-f]+)\s*=(?<value>(.*))", RegexOptions.Compiled);
+			
+			// This is sooo lame that, but it's an easy solution that works
+			foreach (string t in Regex.Replace (dict.Substring (2, dict.Length-3).Replace ("\\\n", "").
+				Replace ("\n", ""), @"\)\s*\(", "\n").Split ('\n')) {
+				
+				try {
+					Match m = reg.Match (t);
+					dicts [m.Result ("${id}")] = m.Result ("${value}");
+						
+				} catch (Exception e) { }
+			}
+			
+		}
+		
+		protected virtual void ParseMetaDict (string metadict)
+		{
+			Regex reg = new Regex (@"(?<id>[0-9A-Fa-f]+)=(?<value>[^()]+)", RegexOptions.Compiled);
+			
+			foreach (Match m in reg.Matches (metadict))
+				metadicts [m.Result ("${id}")] = m.Result ("${value}");
+		}
+		
+		protected virtual void ParseTable (string table)
+		{
+			int start = table.IndexOf ('}')+1;
+			Match m = new Regex (regex_table, RegexOptions.Compiled).Match (table);
+			
+			ParseRows (table.Substring (start, table.Length-start-1), m.Result ("${ns}"), m.Result ("${tbl}"));
+		}
+		
+		protected virtual void ParseRows (string rows, string ns, string table)
+		{
+			Regex reg = new Regex (regex_row, RegexOptions.Compiled);
+			
+			foreach (Match m in reg.Matches (Clean (rows))) {
+				// tmp [0] == id, tmp [1] == ns
+				string[] tmp = m.Result ("${roid}").Split (':');
+				
+				if (m.Result ("${action}") == "-" || m.Result ("${cells}") == string.Empty)
+					RemoveRow (tmp [0], (tmp.Length > 1 ? tmp [1] : ns));
+				else
+					AddRow (tmp [0], (tmp.Length > 1 ? tmp [1] : ns), table, m.Result ("${cells}"));
+			}
+		}
+		
+		protected virtual void ParseGroups (string groups)
+		{
+			int start = groups.IndexOf ("{@")+2;
+			
+			Read (groups.Substring (start, groups.Length-start-1));
+		}
+		
+		protected string Clean (string str)
+		{
+			return str.Replace ("\n", "").Replace (" ", "");
+		}
+		
+		public string ParseNamespace (string ns)
+		{
+			if (ns.StartsWith ("^"))
+				return ns;
+			else {
+				foreach (string key in metadicts.Keys)
+					if ((metadicts [key] as string) == ns)
+						return String.Format ("^{0}", key);
+			}
+			
+			return ns;
+		}
+		
+		public void AddRow (string id, string ns, string table, string cells)
+		{
+			string ns2 = ParseNamespace (ns);
+			
+			if (id == string.Empty || ns2 == string.Empty || cells == string.Empty)
+				return;
+			else if (!rows.ContainsKey (ns2))
+				rows [ns2] = new Hashtable ();
+			
+			// Add row with a twist... (aka hack)
+			if (!Exists (id, ns2))
+				(rows [ns2] as Hashtable).Add (id, cells);
+			else
+				(rows [ns2] as Hashtable) [id] = UpdateCells (GetCells (id, ns2), cells);
+			
+			// Save table association
+			if (!tables.ContainsKey (id))
+				tables [id] = table;
+		}
+		
+		private string UpdateCells (string old_cells, string new_cells)
+		{
+			string ret_string = string.Empty;
+			Hashtable tbl = new Hashtable ();
+			Regex reg = new Regex (@"(?<key>\^[0-9A-Fa-f]+)((?<value>(\^|=)[0-9A-Fa-f]+))", RegexOptions.Compiled);
+			
+			foreach (Match m in reg.Matches (String.Concat (old_cells, new_cells)))
+				tbl [m.Result ("${key}")] = m.Result ("${value}");
+			
+			foreach (string key in tbl.Keys)
+				ret_string = String.Concat (ret_string, String.Format ("({0}{1})", key, tbl [key]));
+			
+			return ret_string;
+		}
+		
+		public void RemoveRow (string id, string ns)
+		{
+			string ns2 = ParseNamespace (ns);
+			
+			if (!rows.ContainsKey (ns2))
+				return;
+			
+			(rows [ns2] as Hashtable).Remove (id);
+			tables.Remove (id);
+		}
+		
+		public string GetCells (string id, string ns)
+		{
+			string ns2 = ParseNamespace (ns);
+			
+			return (ns2 != null ?(rows [ns2] as Hashtable) [id] as string : null);
+		}
+		
+		public Hashtable Compile (string id, string ns)
+		{
+			string ns2 = ParseNamespace (ns);
+			
+			if (!Exists (id, ns2))
+				return null;
+			
+			Hashtable tbl = new Hashtable ();
+			Regex reg = new Regex (regex_cell, RegexOptions.Compiled);
+			
+			foreach (Match m in reg.Matches (GetCells (id, ns2))) {
+				string value = (string) (m.Result ("${pvalue}") != string.Empty ? 
+							dicts [m.Result("${pvalue}")] : m.Result ("${value}"));
+				
+				tbl [metadicts [m.Result ("${key}")]] = Decode (value, Encoding);
+			}
+			
+			tbl ["id"] = id;
+			tbl ["table"] = tables [id];
+			
+			return tbl;
+		}
+
+		public bool Exists (string id, string ns)
+		{
+			string ns2 = ParseNamespace (ns);
+			
+			return (ns2 != null ? (rows [ns] as Hashtable).ContainsKey (id) : false);
+		}
+		
+		public int GetRowCount (string ns)
+		{
+			string ns2 = ParseNamespace (ns);
+			
+			if (ns2 == null || rows [ns2] == null)
+				return -1;
+			
+			return (rows [ns2] as Hashtable).Count;
+		}
+		
+		public int GetRowCount (string ns, string table)
+		{
+			int count = 0;
+			string ns2 = ParseNamespace (ns);
+			
+			if (ns2 == null || rows [ns2] == null)
+				return -1;
+			
+			foreach (string id in (rows [ns2] as Hashtable).Keys) {
+				if ((string) tables [id] == table)
+					count++;
+			}
+			
+			return count;
+		}
+		
+		public IEnumerator GetEnumerator ()
+		{
+			string ns = ParseNamespace (EnumNamespace);
+			
+			if (ns == null || (rows [ns] as Hashtable) == null || Empty)
+				return null;
+			
+			return (rows [ns] as Hashtable).Keys.GetEnumerator ();
+		}
+		
+		public void Reset ()
+		{
+			dicts.Clear ();
+			metadicts.Clear ();
+			rows.Clear ();
+			tables.Clear ();
+		}
+
+		public static string Convert (int char1, int char2, System.Text.Encoding to_encoding)
+		{
+			byte[] bytes;
+			System.Text.Encoding from;
+			
+			if (char2 == -1) {
+				from = System.Text.Encoding.UTF7;
+				bytes = new byte[] { System.Convert.ToByte (char1) };
+			} else {
+				from = System.Text.Encoding.UTF8;
+				bytes = new byte[] { System.Convert.ToByte (char1), System.Convert.ToByte (char2) };
+			}
+			
+			return to_encoding.GetString (System.Text.Encoding.Convert (from, to_encoding, bytes));
+		}
+		
+		public static string Decode (string str, System.Text.Encoding to_encoding)
+		{
+			foreach (Match m in Regex.Matches (str, @"\$(?<1>[0-9A-F]{2})\$(?<2>[0-9A-F]{2})|\$(?<3>[0-9A-F]{2})")) {
+				string char1 = m.Result ("${1}"), char2 = m.Result ("${2}"), char3 = m.Result ("${3}");
+				
+				if (char1 != string.Empty) {
+					str = str.Replace (String.Format (@"${0}${1}", char1, char2), 
+						Convert (Thunderbird.Hex2Dec (char1), Thunderbird.Hex2Dec (char2), to_encoding));
+				} else {
+					str = str.Replace (String.Format (@"${0}", char3), 
+						Convert (Thunderbird.Hex2Dec (char3), -1, to_encoding));
+				}
+			}
+			
+			return str;
+		}
+
+		public int Rows {
+			get {
+				int count = 0;
+				
+				foreach (Hashtable r in rows.Values)
+					count += r.Count;
+			
+				return count;
+			}
+		}
+		
+		public string EnumNamespace {
+			get { return enum_namespace; }
+			set { enum_namespace = value; }
+		}
+		
+		public string Filename {
+			get { return mork_file; }
+		}
+
+		// There will always exist an item with id 1 in namespace 80, which means
+		// that when there are less than two items in the database, it's empty
+		public bool Empty {
+			get { return (rows.Count > 1 ? false : true); }
+		}
+		
+		public System.Text.Encoding Encoding {
+			get { 
+				System.Text.Encoding encoding = System.Text.Encoding.GetEncoding ("iso-8859-1");
+				
+				try {
+					encoding = System.Text.Encoding.GetEncoding ((string) metadicts ["f"]); 
+				} catch { }
+			
+				return encoding;
+			}
+		}
+	}
+}
Index: Util/Makefile.am
===================================================================
--- Util/Makefile.am	(revision 2690)
+++ Util/Makefile.am	(working copy)
@@ -114,6 +114,11 @@
 	$(srcdir)/SemWeb/XPathSemWebNavigator.cs	\
 	$(srcdir)/PropertyKeywordAttribute.cs
 
+if ENABLE_THUNDERBIRD
+UTIL_CSFILES +=				\
+	$(srcdir)/Mork.cs		\
+	$(srcdir)/Thunderbird.cs
+endif
 
 if HAS_LIBCHM 
 UTIL_CSFILES +=					\
Index: beagled/ThunderbirdQueryable/Contact.cs
===================================================================
--- beagled/ThunderbirdQueryable/Contact.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/Contact.cs	(revision 0)
@@ -0,0 +1,150 @@
+//
+// Contact.cs: Adds address book indexing support to the Thunderbird backend
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+using GMime;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {	
+	
+	[ThunderbirdIndexableGenerator (TB.AccountType.AddressBook, "Address book support", true)]
+	public class ContactIndexableGenerator : ThunderbirdIndexableGenerator {
+
+		public ContactIndexableGenerator (ThunderbirdIndexer indexer, TB.Account account, string abook_file)
+			: base (indexer, account, abook_file)
+		{
+		}
+		
+		public override bool HasNextIndexable ()
+		{
+			do {
+				if (DbEnumerator == null || !DbEnumerator.MoveNext ()) {
+					Done = true;
+					indexer.NotificationEvent -= OnNotification;
+					indexer.ChildComplete ();
+					return false;
+				}
+			} while ((DbEnumerator.Current as TB.Contact).GetString ("table") != "BF" ||
+				IsUpToDate ((DbEnumerator.Current as TB.Contact).Uri));
+			
+			return true;
+		}
+		
+		public override Indexable GetNextIndexable ()
+		{
+			return ContactToIndexable (DbEnumerator.Current as TB.Contact);
+		}
+		
+		public override void LoadDatabase ()
+		{
+			try {
+				db = new TB.Database (account, DbFile);
+				db.Load ();
+			} catch (Exception e) {
+				Logger.Log.Debug ("Failed to load {0}: {1}", DbFile, e.Message);
+				return;
+			}
+			
+			if (db.Count <= 0)
+				return;
+			
+			Logger.Log.Info ("Indexing address book containing {0} contact(s) ({1})", db.Count, RelativePath);
+		}
+
+		private Indexable ContactToIndexable (TB.Contact contact)
+		{
+			Indexable indexable = NewIndexable (contact.Uri, DateTime.Now.ToUniversalTime (), "Contact");
+			
+			indexable.AddProperty (Property.New ("fixme:FirstName", contact.GetString ("FirstName")));
+			indexable.AddProperty (Property.New ("fixme:LastName", contact.GetString ("LastName")));
+			indexable.AddProperty (Property.New ("fixme:DisplayName", contact.GetString ("LastName")));
+			indexable.AddProperty (Property.New ("fixme:NickName", contact.GetString ("NickName")));
+			indexable.AddProperty (Property.NewKeyword ("fixme:PrimaryEmail", contact.GetString ("PrimaryEmail")));
+			indexable.AddProperty (Property.NewKeyword ("fixme:SecondEmail", contact.GetString ("SecondEmail")));
+			indexable.AddProperty (Property.New ("fixme:WorkPhone", contact.GetString ("WorkPhone")));
+			indexable.AddProperty (Property.New ("fixme:FaxNumber", contact.GetString ("FaxNumber")));
+			indexable.AddProperty (Property.New ("fixme:HomePhone", contact.GetString ("HomePhone")));
+			indexable.AddProperty (Property.New ("fixme:PagerNumber", contact.GetString ("PagerNumber")));
+			indexable.AddProperty (Property.New ("fixme:CellularNumber", contact.GetString ("CellularNumber")));
+			indexable.AddProperty (Property.New ("fixme:HomeAddress", contact.GetString ("HomeAddress")));
+			indexable.AddProperty (Property.New ("fixme:HomeAddress2", contact.GetString ("HomeAddress2")));
+			indexable.AddProperty (Property.New ("fixme:HomeCity", contact.GetString ("HomeCity")));
+			indexable.AddProperty (Property.New ("fixme:HomeState", contact.GetString ("HomeState")));
+			indexable.AddProperty (Property.New ("fixme:HomeZipCode", contact.GetString("HomeZipCode")));
+			indexable.AddProperty (Property.New ("fixme:HomeCountry", contact.GetString ("HomeCountry")));
+			indexable.AddProperty (Property.New ("fixme:WorkAddress", contact.GetString ("WorkAddress")));
+			indexable.AddProperty (Property.New ("fixme:WorkAddress2", contact.GetString ("WorkAddress2")));
+			indexable.AddProperty (Property.New ("fixme:WorkCity", contact.GetString ("WorkCity")));
+			indexable.AddProperty (Property.New ("fixme:WorkState", contact.GetString ("WorkState")));
+			indexable.AddProperty (Property.New ("fixme:WorkZipCode", contact.GetString ("WorkZipCode")));
+			indexable.AddProperty (Property.New ("fixme:WorkCountry", contact.GetString ("WorkCountry")));
+			indexable.AddProperty (Property.New ("fixme:JobTitle", contact.GetString ("JobTitle")));
+			indexable.AddProperty (Property.New ("fixme:Department", contact.GetString ("Department")));
+			indexable.AddProperty (Property.New ("fixme:Company", contact.GetString ("Company")));
+			indexable.AddProperty (Property.New ("fixme:_AimScreenName", contact.GetString ("_AimScreenName")));
+			indexable.AddProperty (Property.New ("fixme:FamilyName", contact.GetString ("FamilyName")));
+			indexable.AddProperty (Property.NewKeyword ("fixme:WebPage1", contact.GetString ("WebPage1")));
+			indexable.AddProperty (Property.NewKeyword ("fixme:WebPage2", contact.GetString ("WebPage2")));
+			indexable.AddProperty (Property.New ("fixme:BirthYear", contact.GetString ("BirthYear")));
+			indexable.AddProperty (Property.New ("fixme:BirthMonth", contact.GetString ("BirthMonth")));
+			indexable.AddProperty (Property.New ("fixme:BirthDay", contact.GetString ("BirthDay")));
+			indexable.AddProperty (Property.New ("fixme:Custom1", contact.GetString ("Custom1")));
+			indexable.AddProperty (Property.New ("fixme:Custom2", contact.GetString ("Custom2")));
+			indexable.AddProperty (Property.New ("fixme:Custom3", contact.GetString ("Custom3")));
+			indexable.AddProperty (Property.New ("fixme:Custom4", contact.GetString ("Custom4")));
+			indexable.AddProperty (Property.New ("fixme:Notes", contact.GetString ("Notes")));
+			indexable.AddProperty (Property.New ("fixme:PreferMailFormat", contact.GetString ("PreferMailFormat")));
+			
+			indexable.AddProperty (Property.NewKeyword ("fixme:Email", contact.GetString ("PrimaryEmail")));
+			indexable.AddProperty (Property.New ("fixme:Name", contact.GetString ("DisplayName")));
+			
+			return indexable;
+		}
+		
+		// Why? Because it's very likely that the user will sometimes change contact details. Current IsUpToDate
+		// (in ThunderbirdIndexableGenerator-class) only checks the "fullyIndexed" property and when the contact
+		// was indexed, thus if the user changes an email address it won't be updated until beagle is restarted.
+		// By always returning false here, we make sure that beagle always re-index contacts when something
+		// happens. It's a really fast and not a very cpu intensive task, so it doesn't really matter.
+		protected new bool IsUpToDate (Uri uri)
+		{
+			// Remove this uri from the cache
+			if (stored_cache != null)
+				stored_cache.Remove (uri.ToString ());
+			
+			return false;
+		}
+	}
+}
+	
Index: beagled/ThunderbirdQueryable/ThunderbirdInotify.cs
===================================================================
--- beagled/ThunderbirdQueryable/ThunderbirdInotify.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/ThunderbirdInotify.cs	(revision 0)
@@ -0,0 +1,160 @@
+//
+// ThunderbirdInotify.cs. This class will sumnarize inotify events and raise an event every 30 seconds (to prevent inotify hammering)
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+
+using Beagle;
+using Beagle.Util;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {
+
+	public class ThunderbirdInotify {
+		protected struct Event {
+			public Inotify.Watch Watch;
+			public string Path;
+			public string Subitem;
+			public string Srcpath;
+			public Inotify.EventType Type;
+			public long OldFileSize;
+			public long CurrentFileSize;
+			
+			public Event (Inotify.Watch watch, string path, string subitem,
+				string srcpath, Inotify.EventType type, long old_size, long current_size)
+			{
+				this.Watch = watch;
+				this.Path = path;
+				this.Subitem = subitem;
+				this.Srcpath = srcpath;
+				this.Type = type;
+				this.OldFileSize = old_size;
+				this.CurrentFileSize = current_size;
+			}
+		}
+
+		private Queue queue;
+		
+		public ThunderbirdInotify ()
+		{
+			queue = new Queue ();
+			
+			GLib.Timeout.Add (30000, new GLib.TimeoutHandler (Process));
+		}
+		
+		public void Watch (string path, Inotify.EventType type)
+		{
+			Inotify.Subscribe (path, OnInotify, type);
+		}
+		
+		private void OnInotify (Inotify.Watch watch,
+					string path,
+					string subitem,
+					string srcpath,
+					Inotify.EventType type)
+		{
+			if (subitem == null)
+				return;
+
+			// Unsubscribe to directories that have been removed
+			if ((type & Inotify.EventType.Delete) != 0 && (type & Inotify.EventType.IsDirectory) != 0)
+				watch.Unsubscribe ();
+
+			lock (queue.SyncRoot) {
+				bool found = false;
+				for (int i = 0; i < queue.Count; i++) {
+					Event ev = (Event) queue.Dequeue ();
+					
+					if (ev.Path == path && ev.Subitem == subitem && ev.Srcpath == srcpath) {
+						found = true;
+						ev.Type = (ev.Type | type);
+						queue.Enqueue (ev);
+						break;
+					}
+					
+					queue.Enqueue (ev);
+				}
+				
+				if (!found) {
+					queue.Enqueue (new Event (watch, path, subitem, srcpath, 
+						type, -1, GetFileSize (Path.Combine (path, subitem))));
+				}
+			}
+		}
+			
+		private bool Process ()
+		{
+			Queue tmp = new Queue ();
+			
+			lock (queue.SyncRoot) {
+				while (queue.Count > 0) {
+					Event ev = (Event) queue.Dequeue();
+					long size = GetFileSize (Path.Combine (ev.Path, ev.Subitem));
+					
+					if (Thunderbird.Debug) {
+						Logger.Log.Debug ("EVENT: {0} ({1}) [{2}, {3}]", 
+							Path.Combine (ev.Path, ev.Subitem).ToString (), ev.Type, ev.CurrentFileSize, size);
+					}
+
+					if (size != ev.CurrentFileSize) {
+						ev.OldFileSize = ev.CurrentFileSize;
+						ev.CurrentFileSize = size;
+						tmp.Enqueue (ev);
+						continue;
+					}
+						
+					OnInotifyEvent (ev);
+				}
+
+				while (tmp.Count > 0)
+					queue.Enqueue (tmp.Dequeue ());
+			}
+		
+			return true;
+		}
+
+		private long GetFileSize (string filename)
+		{
+			long filesize = -1;
+			
+			try {
+				FileInfo file = new FileInfo (filename);
+				filesize = file.Length;
+			} catch (Exception e) { }
+				
+			return filesize;
+		}
+		
+		protected virtual void OnInotifyEvent (Event ev)
+		{
+			if (InotifyEvent != null)
+				InotifyEvent (ev.Watch, ev.Path, ev.Subitem, ev.Srcpath, ev.Type);
+		}
+		
+		public event Inotify.InotifyCallback InotifyEvent;
+	}
+
+}
Index: beagled/ThunderbirdQueryable/LuceneAccess.cs
===================================================================
--- beagled/ThunderbirdQueryable/LuceneAccess.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/LuceneAccess.cs	(revision 0)
@@ -0,0 +1,136 @@
+//
+// LuceneAccess.cs: Provides low level access to the underlying Lucene database
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.Collections;
+
+using Lucene.Net.Documents;
+using Lucene.Net.Index;
+using LNS = Lucene.Net.Search;
+
+using Beagle.Daemon;
+using Beagle.Util;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {
+
+	public class LuceneAccess : LuceneQueryingDriver {
+		public class StoredInfo 
+		{
+			public DateTime LastIndex;
+			public bool FullyIndexed;
+			public Uri Uri;
+		}
+		
+		public LuceneAccess (string index_name, int minor_version, bool read_only)
+			: base (index_name, minor_version, read_only)
+		{
+		
+		}
+		
+		public StoredInfo DocumentToStoredInfo (Document doc)
+		{
+			int count = 0;
+			StoredInfo info = new StoredInfo ();
+
+			info.Uri = GetUriFromDocument (doc);
+
+			foreach (Field f in doc.Fields ()) {
+				Property prop = GetPropertyFromDocument (f, doc, false);
+				if (prop == null)
+					continue;
+
+				switch (prop.Key) {
+				case "fixme:indexDateTime":
+					info.LastIndex = StringFu.StringToDateTime (prop.Value);
+					count++;
+					break;
+				case "fixme:fullyIndexed":
+					info.FullyIndexed = Convert.ToBoolean (prop.Value);
+					count++;
+					break;
+				}
+				
+				if (count == 2)
+					break;
+			}
+
+			return info;
+		}
+		
+		private class SingletonCollector : LNS.HitCollector
+		{
+			public int MatchId = -1;
+			
+			public override void Collect (int id, float score)
+			{
+				MatchId = id;
+			}
+		}
+		
+		public StoredInfo GetStoredInfo (Uri uri)
+		{
+			StoredInfo info = new StoredInfo ();
+
+			LNS.Query query = UriQuery ("Uri", uri);
+			SingletonCollector collector = new SingletonCollector ();
+			
+			LNS.IndexSearcher searcher = LuceneCommon.GetSearcher (PrimaryStore);
+			searcher.Search (query, null, collector);
+			
+			if (collector.MatchId != -1) { 
+				Document doc = searcher.Doc (collector.MatchId);
+				info = DocumentToStoredInfo (doc);
+			}
+			
+			LuceneCommon.ReleaseSearcher (searcher);
+			
+			return info;
+		}
+		
+		public Hashtable GetStoredUriStrings (string server, string file)
+		{
+			Hashtable uris = new Hashtable ();
+
+			Term term = new Term (PropertyToFieldName (PropertyType.Keyword, "fixme:file"), file);
+			LNS.QueryFilter filter = new LNS.QueryFilter (new LNS.TermQuery (term));
+			
+			term = new Term (PropertyToFieldName (PropertyType.Keyword, "fixme:account"), server);
+			LNS.TermQuery query = new LNS.TermQuery (term);
+			
+			LNS.IndexSearcher searcher = LuceneCommon.GetSearcher (PrimaryStore);
+			LNS.Hits hits = searcher.Search (query, filter);
+			
+			for (int i = 0; i < hits.Length (); i++) {
+				StoredInfo info = DocumentToStoredInfo (hits.Doc (i));	
+				uris.Add (info.Uri.ToString (), info.FullyIndexed);
+			}
+
+			LuceneCommon.ReleaseSearcher (searcher);
+			
+			return uris;
+		}
+	}
+}
Index: beagled/ThunderbirdQueryable/ThunderbirdIndexableGenerator.cs
===================================================================
--- beagled/ThunderbirdQueryable/ThunderbirdIndexableGenerator.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/ThunderbirdIndexableGenerator.cs	(revision 0)
@@ -0,0 +1,258 @@
+//
+// ThunderbirdIndexableGenerator.cs: A helper class that makes it very easy to add new features to this backend
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+using GMime;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {
+
+	// This is a generic IndexableGenerator-class and should be used to index mork files only!
+	public abstract class ThunderbirdIndexableGenerator : IIndexableGenerator {
+		protected ThunderbirdIndexer indexer;
+		protected TB.Database db;
+		protected TB.Account account;
+		protected IEnumerator db_enumerator;
+		
+		private bool full_index;
+		private string db_file;
+		private bool done;
+		private string relative_path;
+		protected Hashtable stored_cache;
+		
+		public ThunderbirdIndexableGenerator (ThunderbirdIndexer indexer, TB.Account account, string db_file)
+		{
+			this.indexer = indexer;
+			this.indexer.NotificationEvent += OnNotification;
+			this.account = account;
+			this.full_index = true;
+			this.db_file = db_file;
+			this.done = false;
+			this.relative_path = Thunderbird.GetRelativePath (db_file);
+			
+			// Load the database and make sure the enumerator is up to date. Otherwise we will
+			// get lots of null exceptions when enumerating the database.
+			LoadDatabase ();
+			ResetEnumerator ();
+
+			// Fetch all already stored uris in the index. This way we can remove one uri at the time
+			// while we are indexing and thus in the end now which mails that doesn't exist anymore.
+			stored_cache = indexer.Lucene.GetStoredUriStrings (account.Server, relative_path);
+		}
+		
+		public abstract bool HasNextIndexable ();
+		public abstract Indexable GetNextIndexable ();
+		public abstract void LoadDatabase ();
+		
+		public virtual bool IsUpToDate (Uri uri)
+		{
+			if (uri == null)
+				return false;
+			
+			LuceneAccess.StoredInfo info = indexer.Lucene.GetStoredInfo (uri);
+
+			// Remove this uri from the cache
+			if (stored_cache != null)
+				stored_cache.Remove (uri.ToString ());
+			
+			// Check if this time is "older" than the time we began to index and if the index
+			// status has changed (partial vs. full indexing)
+			if (info != null && ThunderbirdQueryable.IndexingStart.CompareTo (info.LastIndex) < 0 && 
+				FullIndex == info.FullyIndexed) {
+				return true;
+			}
+
+			return false;
+		}
+		
+		public virtual void PostFlushHook ()
+		{
+			if (!Done || (stored_cache == null) || (Done && stored_cache.Count == 0))
+				return;
+			
+			if (Thunderbird.Debug)
+				Logger.Log.Debug ("Cleaning out old objects in {0} ({1})", RelativePath, stored_cache.Count);
+		
+			ArrayList uris = new ArrayList ();
+			foreach (string uri_str in stored_cache.Keys)
+				uris.Add (new Uri (uri_str));
+				
+			indexer.ScheduleRemoval ((Uri[]) uris.ToArray (typeof (Uri)), 
+				String.Format ("PostFlushHook-{0}", RelativePath), Scheduler.Priority.Delayed);
+		}
+		
+		protected virtual Indexable NewIndexable (Uri uri, DateTime timestamp, string hit_type)
+		{
+			Indexable indexable;
+			
+			indexable = new Indexable (uri);
+			indexable.HitType = hit_type;
+			indexable.Timestamp = timestamp;
+			
+			indexable.AddProperty (Property.NewKeyword ("fixme:account", account.Server));
+			indexable.AddProperty (Property.NewKeyword ("fixme:client", "thunderbird"));
+			indexable.AddProperty (Property.NewUnsearched ("fixme:fullyIndexed", full_index));
+			indexable.AddProperty (Property.NewUnsearched ("fixme:file", RelativePath));
+			indexable.AddProperty (Property.NewDate ("fixme:indexDateTime", DateTime.UtcNow));
+			
+			return indexable;
+		}
+		
+		protected virtual void ResetEnumerator ()
+		{
+			if (db != null && db.Count > 0)
+				db_enumerator = db.GetEnumerator ();
+			else
+				db_enumerator = null;
+		}
+		
+		protected virtual void OnNotification (object o, NotificationEventArgs args)
+		{
+			if (args.Account != account)
+				return;
+			
+			switch (args.Type) {
+			case NotificationType.StopIndexing:
+				indexer.NotificationEvent -= OnNotification;
+				Logger.Log.Debug ("Stopping running task {0}", account.Server);
+				break;
+				
+			case NotificationType.RestartIndexing:
+				LoadDatabase ();
+				break;
+				
+			case NotificationType.UpdateAccountInformation:
+				account = (TB.Account) args.Data;
+				LoadDatabase ();
+				break;
+				
+			}
+		}
+
+		// Done should be set to true when there's no more objects to index. This will allow
+		// PostFlushHook to remove old objects from the index.
+		public bool Done {
+			get { return done; }
+			set { done = value; }
+		}
+		
+		public string DbFile {
+			get { return db_file; }
+			set { db_file = value; }
+		}
+		
+		public bool FullIndex {
+			get { return full_index; }
+			set { full_index = value; }
+		}
+		
+		// Realtive path to current mork_file
+		public string RelativePath {
+			get { return relative_path; }
+		}
+		
+		protected IEnumerator DbEnumerator {
+			get { return db_enumerator; }
+		}
+		
+		public string StatusName { 
+			get { return account.Server; }
+		}
+	}
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	
+	[AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+	public class ThunderbirdIndexableGeneratorAttribute : System.Attribute {
+		private TB.AccountType type;
+		private string description;
+		private bool enabled;
+		
+		public ThunderbirdIndexableGeneratorAttribute (TB.AccountType type, string description, bool enabled)
+		{
+			this.type = type;
+			this.description = description;
+			this.enabled = enabled;
+		}
+		
+		public TB.AccountType Type {
+			get { return type; }
+			set { type = value; }
+		}
+		
+		public string Description {
+			get { return description; }
+			set { description = value; }
+		}
+		
+		public bool Enabled {
+			get { return enabled; }
+			set { enabled = value; }
+		}
+	}
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	
+	
+	public class UriRemovalIndexableGenerator : IIndexableGenerator {
+		private Uri[] uris;
+		
+		private IEnumerator enumerator;
+		
+		public UriRemovalIndexableGenerator (Uri[] uris)
+		{
+			this.uris = uris;
+			this.enumerator = this.uris.GetEnumerator ();
+		}
+		
+		public Indexable GetNextIndexable ()
+		{
+			return new Indexable (IndexableType.Remove, (Uri) enumerator.Current);
+		}
+		
+		public bool HasNextIndexable ()
+		{
+			while (enumerator == null || !enumerator.MoveNext ())
+				return false;
+			
+			return true;
+		}
+		
+		public string StatusName {
+			get { return String.Format ("Removing {0} uris", uris.Length); }
+		}
+		
+		public void PostFlushHook () { }
+	}
+}
Index: beagled/ThunderbirdQueryable/NNTP.cs
===================================================================
--- beagled/ThunderbirdQueryable/NNTP.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/NNTP.cs	(revision 0)
@@ -0,0 +1,112 @@
+//
+// NNTP.cs: Adds NNTP indexing support to the Thunderbird backend
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+using GMime;
+	
+namespace Beagle.Daemon.ThunderbirdQueryable {	
+	
+	[ThunderbirdIndexableGenerator (TB.AccountType.Nntp, "NNTP Support", false)]
+	public class NNTPIndexableGenerator : ThunderbirdIndexableGenerator {
+	
+		public NNTPIndexableGenerator (ThunderbirdIndexer indexer, TB.Account account, string file)
+			: base (indexer, account, file)
+		{
+		}
+		
+		public override bool HasNextIndexable ()
+		{
+			do {
+				if (DbEnumerator == null || !DbEnumerator.MoveNext ()) {
+					Done = true;
+					indexer.NotificationEvent -= OnNotification;
+					indexer.ChildComplete ();
+					return false;
+				}
+			} while (IsUpToDate ((DbEnumerator.Current as TB.NntpMessage).Uri));
+			
+			return true;
+		}
+		
+		public override Indexable GetNextIndexable ()
+		{
+			TB.NntpMessage message = DbEnumerator.Current as TB.NntpMessage;
+			
+			// If status is different, than something happend when loading this mail and we dont'
+			// want to change it's status.
+			if (message.GetObject ("FullIndex") == null)
+				message.SetObject ("FullIndex", (object) FullIndex);
+			
+			return NntpMessageToIndexable (message);
+		}
+		
+		public override void LoadDatabase ()
+		{
+			try {
+				db = new TB.Database (account, DbFile);
+				db.Load ();
+			} catch (Exception e) {
+				Logger.Log.Debug ("Failed to load {0}: {1}", DbFile, e.Message);
+				return;
+			}
+			
+			if (db.Count <= 0)
+				return;
+			
+			FullIndex = (Thunderbird.IsFullyIndexable (DbFile) ? true : false);
+			Logger.Log.Info ("Indexing {0} NNTP messages", db.Count);
+		}
+		
+		// FIXME: This need some more info
+		private Indexable NntpMessageToIndexable (TB.NntpMessage message)
+		{
+			Indexable indexable;
+			
+			indexable = new Indexable (message.Uri);
+			indexable.HitType = "MailMessage";
+			indexable.MimeType = "message/rfc822";
+			indexable.Timestamp = DateTime.Parse (message.GetString ("date")).ToUniversalTime ();
+			
+			indexable.AddProperty (Property.NewKeyword ("fixme:client", "thunderbird"));
+			indexable.AddProperty (Property.NewUnsearched ("fixme:fullyIndexed", message.GetBool ("FullIndex")));
+			indexable.AddProperty (Property.NewDate ("fixme:indexDateTime", DateTime.UtcNow));
+			
+			string subject = GMime.Utils.HeaderDecodePhrase (message.GetString ("subject"));
+			indexable.AddProperty (Property.New ("dc:title", subject));
+			
+			return indexable;
+		}
+	}
+}
Index: beagled/ThunderbirdQueryable/Mail.cs
===================================================================
--- beagled/ThunderbirdQueryable/Mail.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/Mail.cs	(revision 0)
@@ -0,0 +1,111 @@
+//
+// Mail.cs: Adds POP3 and IMAP indexing support to the Thunderbird backend
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+using GMime;
+	
+namespace Beagle.Daemon.ThunderbirdQueryable {
+
+	[ThunderbirdIndexableGenerator (TB.AccountType.Pop3, "POP3 Support", true)]
+	[ThunderbirdIndexableGenerator (TB.AccountType.Imap, "IMAP Support", true)]
+	public class MailIndexableGenerator : ThunderbirdIndexableGenerator {
+
+		public MailIndexableGenerator (ThunderbirdIndexer indexer, TB.Account account, string mork_file)
+			: base (indexer, account, mork_file)
+		{
+		}
+		
+		public override bool HasNextIndexable ()
+		{
+			do {
+				while (DbEnumerator == null || !DbEnumerator.MoveNext ()) {
+					Done = true;
+					indexer.NotificationEvent -= OnNotification;
+					indexer.ChildComplete ();
+					return false;
+				}
+			} while (IsUpToDate ((DbEnumerator.Current as TB.Mail).Uri));
+			
+			return true;
+		}
+		
+		public override Indexable GetNextIndexable ()
+		{
+			TB.Mail mail = DbEnumerator.Current as TB.Mail;
+
+			// If status is different, than something happend when loading this mail and we dont'
+			// want to change it's status.
+			if (mail.GetObject ("FullIndex") == null)
+				mail.SetObject ("FullIndex", (object) FullIndex);
+			
+			return MailToIndexable (mail);
+		}
+
+		public override void LoadDatabase ()
+		{
+			try {
+				db = new TB.Database (account, DbFile);
+				db.Load ();
+			} catch (Exception e) {
+				Logger.Log.Warn ("Failed to load {0}: {1}", DbFile, e.Message);
+				return;
+			}
+			
+			if (db.Count <= 0)
+				return;
+			
+			FullIndex = (Thunderbird.IsFullyIndexable (DbFile) ? true : false);
+			Logger.Log.Info ("Indexing {0} containing {1} mails ({2})", RelativePath, db.Count, (FullIndex ? "Full" : "Partial"));
+		}
+
+		private Indexable MailToIndexable (TB.Mail mail)
+		{
+			Indexable indexable;
+			GMime.Message message = mail.Message;
+			FullIndex = mail.GetBool ("FullIndex"); // Make sure this is up to date
+			
+			indexable = NewIndexable (mail.Uri, message.Date.ToUniversalTime (), "MailMessage");
+			indexable.MimeType = "message/rfc822";
+			indexable.CacheContent = true;
+			indexable.AddProperty (Property.NewKeyword ("fixme:folder", mail.GetString ("mailbox")));
+			indexable.SetBinaryStream (message.Stream);
+			
+			if (mail.GetBool ("FullIndex"))
+				indexable.ContentUri = UriFu.PathToFileUri (Thunderbird.GetFullyIndexableFile (DbFile));
+			
+			return indexable;
+		}
+	}
+}
Index: beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs
===================================================================
--- beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/ThunderbirdQueryable.cs	(revision 0)
@@ -0,0 +1,180 @@
+//
+// ThunderbirdQueryable.cs: This is where all the magic begins!
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Collections;
+using System.Text.RegularExpressions;
+
+using Beagle;
+using Beagle.Util;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {
+
+	[QueryableFlavor (Name = "Thunderbird", Domain = QueryDomain.Local, RequireInotify = false)]
+	public class ThunderbirdQueryable : LuceneQueryable {
+		private static DateTime indexing_start;
+		private ThunderbirdIndexer indexer;
+		
+		public ThunderbirdQueryable () :
+			base ("ThunderbirdIndex")
+		{
+			// Remove one second from the start time to make sure we don't run into any troubles
+			indexing_start = DateTime.UtcNow.Subtract (new TimeSpan (0, 0, 1));
+			indexer = null;
+			
+			GMime.Global.Init ();
+			
+			if (Environment.GetEnvironmentVariable ("BEAGLE_THUNDERBIRD_DEBUG") != null) {
+				Thunderbird.Debug = true;
+				Logger.Log.Debug ("Running Thunderbird backend in debug mode");
+			}
+		}
+		
+		public override void Start ()
+		{
+			base.Start ();
+			ExceptionHandlingThread.Start (new ThreadStart (StartWorker));
+		}
+		
+		private void StartWorker ()
+		{
+			Logger.Log.Info ("Starting Thunderbird backend");
+			Stopwatch watch = new Stopwatch ();
+			watch.Start ();
+			
+			string root_path = Thunderbird.GetRootPath ();
+			if (!Directory.Exists (root_path)) {
+				GLib.Timeout.Add (60000, new GLib.TimeoutHandler (IndexDataCheck));
+				Logger.Log.Info ("No data available for indexing in {0}", root_path);
+				return;
+			}
+			
+			State = QueryableState.Crawling;
+			indexer = new ThunderbirdIndexer (this, Thunderbird.GetProfilePaths (root_path));
+			indexer.Crawl ();
+			State = QueryableState.Idle;
+			
+			watch.Stop ();
+			Logger.Log.Info ("Thunderbird backend done in {0}s", watch.ElapsedTime);
+		}
+		
+		private bool IndexDataCheck ()
+		{
+			if (!Directory.Exists (Thunderbird.GetRootPath ()))
+				return true;
+				
+			StartWorker ();
+			return false;
+		}
+		
+		// We need this in order to perform custom queries to the lucene database
+		override protected LuceneQueryingDriver BuildLuceneQueryingDriver (string index_name,
+										   int    minor_version,
+										   bool   read_only_mode)
+		{
+			return new LuceneAccess (index_name, minor_version, read_only_mode);
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		public Scheduler.Task NewRemoveTaskByDate (DateTime end_date)
+		{
+			return NewAddTask (new DateIndexableGenerator (Driver, Lucene, end_date));
+		}
+		
+		// The purpose of this IndexableGenerator is to remove mails older than the
+		// specified date (when beagle began to index Thunderbird mails)
+		private class DateIndexableGenerator : IIndexableGenerator {
+			private LuceneQueryingDriver driver;
+			private LuceneAccess lucene;
+			private DateTime end_date;
+			
+			private Uri[] stored_uris;
+			private IEnumerator enumerator;
+			
+			public DateIndexableGenerator (LuceneQueryingDriver driver, LuceneAccess lucene, DateTime end_date)
+			{
+				this.driver = driver;
+				this.lucene = lucene;
+				this.end_date = end_date;
+				this.stored_uris = null;
+			}
+			
+			public Indexable GetNextIndexable ()
+			{
+				return new Indexable (IndexableType.Remove, (Uri) enumerator.Current);
+			}
+			
+			public bool HasNextIndexable ()
+			{
+				if (stored_uris == null) {
+					stored_uris = driver.PropertyQuery (Property.NewKeyword ("fixme:client", "thunderbird"));
+					enumerator = stored_uris.GetEnumerator ();
+				}
+				
+				do {
+					while (enumerator == null || !enumerator.MoveNext ())
+						return false;
+				} while (MatchesDate ((enumerator.Current as Uri)));
+				
+				return true;
+			}
+			
+			private bool MatchesDate (Uri uri)
+			{
+				LuceneAccess.StoredInfo info = lucene.GetStoredInfo (uri);
+				
+				try {
+					if (!info.Equals (end_date) && info.LastIndex.CompareTo (end_date) < 0)
+						return false;
+				} catch (Exception e) {}
+				
+				return true;
+			}
+			
+			public string StatusName {
+				get {
+					return String.Format ("Removing Thunderbird mails past {0}", end_date.ToString ()); 
+				}
+			}
+			
+			public void PostFlushHook () { }
+		}
+		
+		/////////////////////////////////////////////////////////////////////////////////////
+		
+		public LuceneAccess Lucene {
+			get { return (LuceneAccess) Driver; }
+		}
+		
+		public static DateTime IndexingStart {
+			get { return indexing_start; }
+		}
+	}
+
+}
Index: beagled/ThunderbirdQueryable/RSS.cs
===================================================================
--- beagled/ThunderbirdQueryable/RSS.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/RSS.cs	(revision 0)
@@ -0,0 +1,115 @@
+//
+// RSS.cs: Adds RSS feed indexing support to the Thunderbird backend
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {	
+
+	[ThunderbirdIndexableGenerator (TB.AccountType.Rss, "RSS Support", true)]
+	public class RSSIndexableGenerator : ThunderbirdIndexableGenerator {
+		private string feed_url;
+		
+		public RSSIndexableGenerator (ThunderbirdIndexer indexer, TB.Account account, string mork_file)
+			: base (indexer, account, mork_file)
+		{
+		}
+			
+		public override bool HasNextIndexable ()
+		{
+			do {
+				if (DbEnumerator == null || !DbEnumerator.MoveNext ()) {
+					Done = true;
+					indexer.NotificationEvent -= OnNotification;
+					indexer.ChildComplete ();
+					return false;
+				}
+			} while (IsUpToDate ((DbEnumerator.Current as TB.RssFeed).Uri));
+			
+			return true;
+		}
+		
+		public override Indexable GetNextIndexable ()
+		{
+			TB.RssFeed feed = DbEnumerator.Current as TB.RssFeed;
+			
+			// If status is different, than something happend when loading this mail and we dont'
+			// want to change it's status.
+			if (feed.GetObject ("FullIndex") == null)
+				feed.SetObject ("FullIndex", (object) FullIndex);
+			
+			return RssFeedToIndexable (feed);
+		}
+		
+		public override void LoadDatabase ()
+		{
+			string folder_name = null;
+			
+			try {
+				db = new TB.Database (account, DbFile);
+				db.Load ();
+				
+				Hashtable tbl = db.Db.Compile ("1", "ns:msg:db:row:scope:dbfolderinfo:all");
+				feed_url = tbl ["feedUrl"] as string;
+				folder_name = tbl ["folderName"] as string;
+			} catch (Exception e) {
+				Logger.Log.Debug ("Failed to load {0}: {1}", DbFile, e.Message);
+				return;
+			}
+			
+			if (db.Count <= 0)
+				return;
+			
+			Logger.Log.Info ("Indexing \"{0}\" RSS feed containing {1} entries ({2})", folder_name, db.Count, RelativePath);
+		}
+		
+		private Indexable RssFeedToIndexable (TB.RssFeed feed)
+		{
+			Indexable indexable;
+			StringReader content = feed.Content;
+			
+			indexable = NewIndexable (feed.Uri, DateTime.Parse (feed.GetString ("date")).ToUniversalTime (), "FeedItem");
+			indexable.MimeType = "text/html";
+			
+			indexable.AddProperty (Property.NewKeyword ("dc:identifier", feed.GetString ("message-id")));
+			indexable.AddProperty (Property.NewKeyword ("dc:source", feed_url));
+			indexable.AddProperty (Property.New ("dc:publisher", feed.GetString ("sender")));
+			if (content == null)
+				indexable.AddProperty (Property.New ("dc:title", feed.GetString ("subject")));
+			
+			indexable.SetTextReader (content);
+			
+			return indexable;
+		}
+	}
+}
Index: beagled/ThunderbirdQueryable/MoveMail.cs
===================================================================
--- beagled/ThunderbirdQueryable/MoveMail.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/MoveMail.cs	(revision 0)
@@ -0,0 +1,106 @@
+//
+// MoveMail: Adds Unix Mailspool (MoveMail) indexing support to the Thunderbird backend
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+using GMime;
+	
+namespace Beagle.Daemon.ThunderbirdQueryable {	
+	
+	[ThunderbirdIndexableGenerator (TB.AccountType.MoveMail, "Movemail Support", false)]
+	public class MoveMailIndexableGenerator : ThunderbirdIndexableGenerator {
+	
+		public MoveMailIndexableGenerator (ThunderbirdIndexer indexer, TB.Account account, string file)
+			: base (indexer, account, file)
+		{
+		}
+		
+		public override bool HasNextIndexable ()
+		{
+			do {
+				if (DbEnumerator == null || !DbEnumerator.MoveNext ()) {
+					Done = true;
+					indexer.NotificationEvent -= OnNotification;
+					indexer.ChildComplete ();
+					return false;
+				}
+			} while (IsUpToDate ((DbEnumerator.Current as TB.MoveMail).Uri));
+			
+			return true;
+		}
+		
+		public override Indexable GetNextIndexable ()
+		{
+			TB.MoveMail message = DbEnumerator.Current as TB.MoveMail;
+			
+			// If status is different, than something happend when loading this mail and we dont'
+			// want to change it's status.
+			if (message.GetObject ("FullIndex") == null)
+				message.SetObject ("FullIndex", (object) FullIndex);
+			
+			return MoveMailToIndexable (message);
+		}
+		
+		public override void LoadDatabase ()
+		{
+			try {
+				db = new TB.Database (account, DbFile);
+				db.Load ();
+			} catch (Exception e) {
+				Logger.Log.Debug ("Failed to load {0}: {1}", DbFile, e.Message);
+				return;
+			}
+			
+			if (db.Count <= 0)
+				return;
+			
+			FullIndex = (Thunderbird.IsFullyIndexable (DbFile) ? true : false);
+			Logger.Log.Info ("Indexing {0} Movemails ({1})", db.Count, RelativePath);
+		}
+		
+		// FIXME: This need some more info
+		private Indexable MoveMailToIndexable (TB.MoveMail mail)
+		{
+			Indexable indexable;
+
+			indexable = NewIndexable (mail.Uri, DateTime.UtcNow, "MailMessage");
+			indexable.MimeType = "message/rfc822";
+			
+			string subject = GMime.Utils.HeaderDecodePhrase (mail.GetString ("subject"));
+			indexable.AddProperty (Property.New ("dc:title", subject));
+			
+			return indexable;
+		}
+	}
+}
Index: beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs
===================================================================
--- beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs	(revision 0)
+++ beagled/ThunderbirdQueryable/ThunderbirdIndexer.cs	(revision 0)
@@ -0,0 +1,462 @@
+//
+// ThunderbirdIndexer.cs: This class launches IndexableGenerators and makes sure instant-updates work
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Collections;
+using System.Reflection;
+
+using Beagle.Util;
+using Beagle.Daemon;
+using TB = Beagle.Util.Thunderbird;
+
+namespace Beagle.Daemon.ThunderbirdQueryable {
+
+	public class ThunderbirdIndexer {
+		private ThunderbirdQueryable queryable;
+
+		private bool init_phase, first_lap;
+		private string[] root_paths;
+		private Hashtable supported_types;
+		private ArrayList account_list;
+		private ThunderbirdInotify inotify;
+	
+		public delegate void NotificationEventHandler (object o, NotificationEventArgs args);
+	
+		public ThunderbirdIndexer (ThunderbirdQueryable queryable, string[] root_paths)
+		{
+			this.queryable = queryable;
+			this.root_paths = root_paths;
+			this.supported_types = new Hashtable ();
+			this.init_phase = true;
+			this.first_lap = true;
+			this.account_list = new ArrayList ();
+			this.inotify = new ThunderbirdInotify ();
+			
+			LoadSupportedTypes ();
+			
+			foreach (string path in root_paths) {
+				Inotify.Subscribe (path, OnInotifyEvent, 
+					Inotify.EventType.Delete | 
+					Inotify.EventType.MovedTo | 
+					Inotify.EventType.Modify |
+					Inotify.EventType.Create);
+			}
+			
+			inotify.InotifyEvent += OnInotifyEvent;
+		}
+		
+		// Loads all supported types, checks if they have a correct constructor and is enabled
+		private void LoadSupportedTypes ()
+		{
+			Assembly assembly = Assembly.GetCallingAssembly ();
+			
+			foreach (Type type in ReflectionFu.ScanAssemblyForInterface (assembly, typeof (IIndexableGenerator))) {
+			
+				foreach (ThunderbirdIndexableGeneratorAttribute attr in 
+					ReflectionFu.ScanTypeForAttribute (type, typeof (ThunderbirdIndexableGeneratorAttribute))) {
+
+					foreach (ConstructorInfo constructor in type.GetConstructors ()) {
+					
+						ParameterInfo[] parameters = constructor.GetParameters ();
+						if(parameters.Length != 3)
+							continue;
+						
+						if (parameters [0].ParameterType.Equals (typeof (ThunderbirdIndexer)) &&
+							parameters [1].ParameterType.Equals (typeof (TB.Account)) &&
+							parameters [2].ParameterType.Equals (typeof (string))) {
+							
+							// Make sure we should enable this type
+							if (attr.Enabled)
+								supported_types [attr.Type]  = type;
+							
+						} else
+							Logger.Log.Debug ("{0} has an invalid constructor!", type.ToString ());
+					}
+				}
+			}	
+		}
+		
+		public void Crawl ()
+		{
+			int launched = 0;
+			
+			foreach (string path in root_paths) {
+				foreach (TB.Account account in Thunderbird.ReadAccounts (path)) {
+					if (Shutdown.ShutdownRequested)
+						return;
+					
+					if (supported_types [account.Type] == null)
+						continue;
+					
+					IndexAccount (account);
+					launched++;
+				}
+			}
+			
+			init_phase = false;
+			Logger.Log.Info ("Indexing {0} ({1}) Thunderbird account(s) spread over {2} profile(s)", 
+				launched, account_list.Count, root_paths.Length);
+			
+			// Clean out old stuff in case no IndexableGenerator was launched
+			if (launched == 0)
+				ChildComplete ();
+		}
+		
+		public void IndexAccount (TB.Account account)
+		{
+			TB.Account stored_account = GetParentAccount (account.Path);
+
+			// We need to act upon changes made to accounts during Thunderbird runtime.
+			// The user might change from plain to SSL, which leads to a new port number
+			// that has to be taken in account for when indexing.
+			if (stored_account == null && Directory.Exists (account.Path) && supported_types [account.Type] != null) {
+				account_list.Add (account);
+				IndexDirectory (account.Path);
+				//Logger.Log.Info ("Indexing {0} account {1}", account.Type.ToString (), account.Server);
+			
+			} else if (stored_account == null && File.Exists (account.Path) && supported_types [account.Type] != null) {
+				account_list.Add (account);
+				IndexFile (account.Path);
+				//Logger.Log.Info ("Indexing {0} account {1}", account.Type.ToString (), account.Server);
+				
+			} else if (stored_account != null &&
+				(stored_account.Server != account.Server ||
+				stored_account.Port != account.Port ||
+				stored_account.Type != account.Type ||
+				stored_account.Delimiter != account.Delimiter)) {
+
+				account_list.Remove (stored_account);
+				account_list.Add (account);
+				
+				// Make sure all running indexables are aware of this since it can affect the way they index
+				NotificationEventArgs args;
+				args = new NotificationEventArgs (NotificationType.UpdateAccountInformation, stored_account);
+				args.Data = (object) account;
+				OnNotification (args);
+				
+				Logger.Log.Info ("Updated {0} with new account details", account.Server);
+			}
+		}
+		
+		public void IndexFile (string file)
+		{
+			TB.Account account = GetParentAccount (file);
+						
+			if (account == null || supported_types [account.Type] == null)
+				return;
+			
+			object[] param = new object[] {this, account, file};
+			ThunderbirdIndexableGenerator generator = Activator.CreateInstance (
+				(Type) supported_types [account.Type], param) as ThunderbirdIndexableGenerator;
+			
+			AddIIndexableTask (generator, file);
+		}
+		
+		private void IndexDirectory (string directory)
+		{
+			Queue pending = new Queue ();
+			
+			pending.Enqueue (directory);
+			while (pending.Count > 0) {
+				string dir = pending.Dequeue () as string;
+				
+				foreach (string subdir in DirectoryWalker.GetDirectories (dir)) {
+					if (Shutdown.ShutdownRequested)
+						return;
+						
+					pending.Enqueue (subdir);
+				}
+
+				if (Inotify.Enabled) {
+						inotify.Watch (dir, 
+						Inotify.EventType.Modify | 
+						Inotify.EventType.Create |
+						Inotify.EventType.Delete |
+						Inotify.EventType.MovedFrom |
+						Inotify.EventType.MovedTo);
+				}
+				
+				foreach (string file in DirectoryWalker.GetItems 
+					(dir, new DirectoryWalker.FileFilter (Thunderbird.IsMorkFile))) {
+					if (Shutdown.ShutdownRequested)
+						return;
+					
+					IndexFile (file);
+				}
+			}
+		}
+		
+		public void RemoveAccount (TB.Account account)
+		{
+			TB.Account acc = GetParentAccount (account.Path);
+			
+			if (acc == null)
+				return;
+			
+			ScheduleRemoval (Property.NewKeyword ("fixme:account", acc.Server), Scheduler.Priority.Delayed);
+			OnNotification (new NotificationEventArgs (NotificationType.StopIndexing, account));
+			account_list.Remove (acc);
+		}
+
+		private void AddIIndexableTask (IIndexableGenerator generator, string tag)
+		{
+			if (queryable.ThisScheduler.ContainsByTag (tag)) {
+				Logger.Log.Debug ("Not adding a Task for already running: {0}", tag);
+				return;
+			}
+
+			Scheduler.Task task = queryable.NewAddTask (generator);
+			task.Tag = tag;
+			queryable.ThisScheduler.Add (task);
+		}
+		
+		private void ScheduleRemoval (Property prop, Scheduler.Priority priority)
+		{
+			if (queryable.ThisScheduler.ContainsByTag (prop.ToString ())) {
+				Logger.Log.Debug ("Not adding a Task for already running: {0}", prop.ToString ());
+				return;
+			}
+			
+			Scheduler.Task task = queryable.NewRemoveByPropertyTask (prop);
+			task.Priority = priority;
+			task.SubPriority = 0;
+			queryable.ThisScheduler.Add (task);
+		}
+
+		public void ScheduleRemoval (Uri[] uris, string tag, Scheduler.Priority priority)
+		{
+			if (queryable.ThisScheduler.ContainsByTag (tag)) {
+				Logger.Log.Debug ("Not adding a Task for already running: {0}", tag);
+				return;
+			}
+
+			Scheduler.Task task = queryable.NewAddTask (new UriRemovalIndexableGenerator (uris));
+			task.Priority = priority;
+			task.SubPriority = 0;
+			queryable.ThisScheduler.Add (task);
+		}
+		
+		public void UpdateAccounts (string root_path)
+		{
+			ArrayList new_accounts;
+
+			try {
+				new_accounts = Thunderbird.ReadAccounts (root_path);
+			} catch (Exception e) {
+				Logger.Log.Warn ("Failed when reading Thunderbird accounts: {0}, account may have been added or removed", e);
+				return;
+			}
+
+			// Add all accounts again to make sure things are updated the way they should
+			foreach (TB.Account account in new_accounts)
+				IndexAccount (account);
+
+			// Remove non-existing accounts
+			foreach (TB.Account existing in account_list) {
+				bool found = false;
+			
+				foreach (TB.Account new_account in new_accounts) {
+					if (existing.Path == new_account.Path) {
+						found = true;
+						break;
+					}
+				}
+
+				if (!found) 
+						RemoveAccount (existing);
+			}
+		}
+		
+		public TB.Account GetParentAccount (string directory)
+		{
+			foreach (TB.Account acc in account_list) {
+				if (directory.StartsWith (acc.Path))
+					return acc;
+			}
+			
+			return null;
+		}
+
+		private void OnInotifyEvent (Inotify.Watch watch,
+						string path,
+						string subitem,
+						string srcpath,
+						Inotify.EventType type)
+		{
+			if (subitem == null)
+				return;
+				
+			string full_path = Path.Combine (path, subitem);
+
+			// If prefs.js is deleted... then we have nothing at all to index
+			if (((type & Inotify.EventType.MovedTo) != 0 && srcpath == Path.Combine (path, "prefs.js")) ||
+				((type & Inotify.EventType.Delete) != 0 && subitem == "prefs.js")) {
+				
+				foreach (TB.Account account in account_list)
+					RemoveAccount (account);
+				return;
+			}
+
+			// Update in case an account was removed or added
+			// Thunderbird saves prefs.js with a different name and then replacing the old one
+			// by "moving" it over the existing prefs.js. That's why MoveTo is used as inotfy type.
+			if ((((type & Inotify.EventType.Modify) != 0 || (type & Inotify.EventType.MovedTo) != 0 || 
+				(type & Inotify.EventType.Create) != 0) && subitem == "prefs.js")) {
+				
+				UpdateAccounts (path);
+				return;
+			}
+
+			// In case the address book file have been moved or deleted, we have to stop indexing it
+			if (((type & Inotify.EventType.MovedTo) != 0 && srcpath == Path.Combine (path, "abook.mab")) ||
+				((type & Inotify.EventType.Delete) != 0 && subitem == "abook.mab")) {
+				
+				TB.Account account = GetParentAccount (full_path);
+				
+				if (account != null)					
+					RemoveAccount (account);
+					
+				return;
+			}
+
+			// In case of a newly created addressbook, the current address book is modified or an old 
+			// address book is moved to where the address book can be found: either start indexing 
+			// or restart an already indexing IndeaxbleGenerator.
+			if ((((type & Inotify.EventType.Modify) != 0 || (type & Inotify.EventType.MovedTo) != 0 || 
+				(type & Inotify.EventType.Create) != 0) && subitem == "abook.mab")) {
+				
+				TB.Account account = GetParentAccount (full_path);
+				
+				if (account == null && File.Exists (full_path)) {
+					UpdateAccounts (path);
+					return;
+				} else if (account == null)
+					return;
+
+				// Tell any running indexable about this or start a new one
+				if (queryable.ThisScheduler.ContainsByTag (full_path))
+					OnNotification (new NotificationEventArgs (NotificationType.RestartIndexing, account));
+				else
+					IndexFile (full_path);
+				
+				return;
+			}
+			
+			// Re-index files when needed
+			if ((type & Inotify.EventType.Modify) != 0) {
+				TB.Account account = GetParentAccount (full_path);
+			
+				if (account == null || !Thunderbird.IsMorkFile (path, subitem))
+					return;
+				
+				// In case we have a running IndexableGenerator, tell it that we have a file that needs to 
+				// be re-indexed.
+				if (queryable.ThisScheduler.ContainsByTag (full_path))
+					OnNotification (new NotificationEventArgs (NotificationType.RestartIndexing, account));
+				else
+					IndexFile (full_path);
+					
+				return;
+			}
+			
+			// Index newly created directories
+			if ((type & Inotify.EventType.Create) != 0 && (type & Inotify.EventType.IsDirectory) != 0) {
+				if (GetParentAccount (full_path) != null && Inotify.Enabled)
+					Inotify.Subscribe (full_path, OnInotifyEvent, Inotify.EventType.All);
+					
+				return;
+			}
+		}
+
+		public void ChildComplete ()
+		{
+			if (NotificationEvent != null || init_phase || !first_lap)
+				return;
+			
+			if (Thunderbird.Debug)
+				Logger.Log.Debug ("Removing old Thunderbird objects");
+
+			Scheduler.Task task = queryable.NewRemoveTaskByDate (ThunderbirdQueryable.IndexingStart);
+			task.Priority = Scheduler.Priority.Idle;
+			task.Tag = "RemoveOldThunderbirdMails";
+			queryable.ThisScheduler.Add (task);
+			
+			// This makes sure that ChildComplete will only clean out all mails once in a lifetime
+			// (of the Thunderbird backend that is)
+			first_lap = false;
+		}
+
+		protected virtual void OnNotification(NotificationEventArgs args)
+		{
+			if (NotificationEvent != null)
+				NotificationEvent (this, args);
+		}
+
+		public event NotificationEventHandler NotificationEvent;
+		
+		public LuceneAccess Lucene {
+			get { return queryable.Lucene; }
+		}
+	}
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	
+	public enum NotificationType {
+		StopIndexing,
+		RestartIndexing,
+		UpdateAccountInformation
+	}
+	
+	/////////////////////////////////////////////////////////////////////////////////////
+	
+	public class NotificationEventArgs  : EventArgs
+	{
+		private NotificationType type;
+		private TB.Account account;
+		private object data;
+
+		public NotificationEventArgs (NotificationType type, TB.Account account)
+		{
+			this.type = type;
+			this.account = account;
+		}
+		
+		public NotificationType Type {
+			get { return type; }
+		}
+		
+		public TB.Account Account {
+			get { return account; }
+		}
+		
+		public object Data {
+			get { return data; }
+			set { data =value; }
+		}
+	}
+	
+}
Index: beagled/Filter.cs
===================================================================
--- beagled/Filter.cs	(revision 2690)
+++ beagled/Filter.cs	(working copy)
@@ -189,7 +189,7 @@
 
 		//////////////////////////
 		
-		private bool snippetMode = false;
+		private bool snippetMode = true;
 		private bool originalIsText = false;
 		private TextWriter snippetWriter = null;
 
@@ -508,13 +508,14 @@
 			}
 
 			try {
+				
 				DoOpen (info);
 
 				if (IsFinished)
 					return true;
 				else if (HasError)
 					return false;
-				
+					
 				DoPullProperties ();
 				
 				if (IsFinished) 
@@ -715,5 +716,6 @@
 		public ArrayList ChildIndexables {
 			get { return this.child_indexables; }
 		}
+		
 	}
 }
Index: beagled/Makefile.am
===================================================================
--- beagled/Makefile.am	(revision 2690)
+++ beagled/Makefile.am	(working copy)
@@ -592,6 +592,41 @@
 $(DAEMON_TARGET): $(DAEMON_CSFILES) $(DAEMON_LOCAL_ASSEMBLIES)
 	$(CSC) -out:$@ $(DAEMON_CSFLAGS) $(DAEMON_CSFILES) $(DAEMON_ASSEMBLIES)
 
+if ENABLE_THUNDERBIRD	
+THUNDERBIRD_DIR = ./ThunderbirdQueryable
+
+THUNDERBIRD_TARGET = $(THUNDERBIRD_DIR)/ThunderbirdBackends.dll
+
+THUNDERBIRD_CSFLAGS = -target:library
+
+
+THUNDERBIRD_CSFILES =						\
+	$(THUNDERBIRD_DIR)/LuceneAccess.cs			\
+	$(THUNDERBIRD_DIR)/ThunderbirdIndexer.cs   		\
+	$(THUNDERBIRD_DIR)/ThunderbirdIndexableGenerator.cs	\
+	$(THUNDERBIRD_DIR)/ThunderbirdQueryable.cs		\
+	$(THUNDERBIRD_DIR)/ThunderbirdInotify.cs		\
+	$(THUNDERBIRD_DIR)/Mail.cs				\
+	$(THUNDERBIRD_DIR)/Contact.cs				\
+	$(THUNDERBIRD_DIR)/RSS.cs				\
+	$(THUNDERBIRD_DIR)/NNTP.cs				\
+	$(THUNDERBIRD_DIR)/MoveMail.cs
+
+THUNDERBIRD_LOCAL_ASSEMBLIES =		\
+	../Util/Util.dll		\
+	../BeagleClient/Beagle.dll	\
+	BeagleDaemonLib.dll
+
+THUNDERBIRD_ASSEMBLIES =				\
+	-r:Mono.Posix				\
+	$(BEAGLED_LIBS)                 	\
+	$(THUNDERBIRD_LOCAL_ASSEMBLIES:%=-r:%)
+
+
+$(THUNDERBIRD_TARGET): $(THUNDERBIRD_CSFILES) $(THUNDERBIRD_LOCAL_ASSEMBLIES)
+	$(CSC) -out:$@ $(THUNDERBIRD_CSFLAGS) $(THUNDERBIRD_CSFILES) $(THUNDERBIRD_ASSEMBLIES)
+endif
+
 ############################################################
 ############################################################
 ############################################################
@@ -976,6 +1011,10 @@
 	$(BUILD_INDEX_TARGET)		\
 	$(BUILD_INDEX_WRAPPER)
 
+if ENABLE_THUNDERBIRD
+ALL_TARGETS += $(THUNDERBIRD_TARGET)
+endif
+
 if ENABLE_WEBSERVICES
 ALL_TARGETS += 				\
 	$(XSP_TARGET)			\
@@ -1051,13 +1090,20 @@
 #	$(INSTALL_DATA) ../Util/Util.dll ../images/Images.dll ../BeagleClient/Beagle.dll ../Tiles/Tiles.dll BeagleDaemonPlugins.dll BeagleDaemonLib.dll $(DESTDIR)$(XSPBIN_DIR)
 
 endif
-
+if ENABLE_THUNDERBIRD
+	$(INSTALL_DATA) $(THUNDERBIRD_TARGET)                 $(DESTDIR)/$(BACKENDDIR)
+	$(INSTALL_DATA) $(THUNDERBIRD_TARGET).mdb             $(DESTDIR)/$(BACKENDDIR)
+endif
 uninstall-local:
 if ENABLE_WEBSERVICES
 	rm -f $(DESTDIR)$(pkglibdir)/$(WEBSERVICES_BACKEND_TARGET)
 	rm -f $(DESTDIR)$(pkglibdir)/$(WEBSERVICES_XSP_TARGET)
 	rm -rf $(DESTDIR)$(XSP_DIR)
 endif
+if ENABLE_THUNDERBIRD
+	$(INSTALL_DATA) $(THUNDERBIRD_TARGET)                 $(DESTDIR)/$(BACKENDDIR)
+	$(INSTALL_DATA) $(THUNDERBIRD_TARGET).mdb             $(DESTDIR)/$(BACKENDDIR)
+endif
 if ENABLE_EVOLUTION
 	rm -f $(DESTDIR)$(BACKENDDIR)/$(EVO_DLL_TARGET)
 	rm -f $(DESTDIR)$(BACKENDDIR)/$(EVO_DLL_TARGET).mdb
@@ -1186,5 +1232,6 @@
 	$(WEBSERVICES_FRONTEND_TARGET)		\
 	$(WEBSERVICES_FRONTEND_TARGET).mdb	\
 	$(WEBSERVICES_XSP_TARGET)		\
-	$(WEBSERVICES_XSP_TARGET).mdb		
-
+	$(WEBSERVICES_XSP_TARGET).mdb		\
+	$(THUNDERBIRD_TARGET)			\
+	$(THUNDERBIRD_TARGET).mdb
Index: configure.in
===================================================================
--- configure.in	(revision 2690)
+++ configure.in	(working copy)
@@ -168,6 +168,13 @@
 LDFLAGS="$OLD_LDFLAGS"
 LIBS="$OLD_LIBS"
 
+dnl ----------------------------------------------
+AC_ARG_ENABLE([thunderbird],
+	AC_HELP_STRING([--disable-thunderbird], [Disable Thunderbird Mail Backend]),
+	enable_tbird=$enableval,
+	enable_tbird=yes)
+AM_CONDITIONAL(ENABLE_THUNDERBIRD, test "x$enable_tbird" = "xyes")
+
 dnl -------------------------------------------------------
 
 AC_ARG_ENABLE([gui],
@@ -645,6 +652,7 @@
 tools/Makefile
 search/Makefile
 ImLogViewer/Makefile
+ContactViewer/Makefile
 libbeagle/Makefile
 libbeagle/libbeagle-0.0.pc
 libbeagle/beagle/Makefile
@@ -678,6 +686,7 @@
 	galago-sharp?		  ${enable_galago}
 	libchm?			  ${has_libchm} 
 	google backend?		  ${enable_googledriver} (Unsupported)
+	Thunderbird backend? 	  ${enable_tbird}
 
 	Mozilla Extension?	  yes
 	Epiphany Extension?	  ${enable_epiphany_extension}
Index: Filters/FilterMail.cs
===================================================================
--- Filters/FilterMail.cs	(revision 2690)
+++ Filters/FilterMail.cs	(working copy)
@@ -53,7 +53,9 @@
 		{
 			// 1: Make email addresses non-keyword, add sanitized version
 			//    for eaching for parts of an email address.
-			SetVersion (1);
+			// 2: Snippet all mail and attachments
+			SetVersion (2);
+			SnippetMode = true;
 
 			AddSupportedFlavor (FilterFlavor.NewFromMimeType ("message/rfc822"));
 		}
@@ -81,8 +83,11 @@
 			stream.Dispose ();
 			parser.Dispose ();
 
-			if (this.message == null)
+			if (this.message == null){
+				Console.WriteLine ("NO MESSAGE!");
 				Error ();
+				
+			}
 		}
 
 		private bool HasAttachments (GMime.Object mime_part)
@@ -190,7 +195,7 @@
 			}
 
 			string l = handler.Reader.ReadLine ();
-
+			//Console.WriteLine (l);
 			if (l != null)
 				AppendText (l);
 			else
@@ -224,6 +229,7 @@
 			public PartHandler (Beagle.Daemon.Filter filter)
 			{
 				this.filter = filter;
+				this.filter.SnippetMode = true;
 			}
 
 			private bool IsMimeTypeHandled (string mime_type)
@@ -315,7 +321,8 @@
 
 						child.HitType = "MailMessage";
 						child.MimeType = part.ContentType.ToString ();
-						child.CacheContent = false;
+						//child.CacheContent = false;
+					
 
 						child.AddProperty (Property.NewKeyword ("fixme:attachment_title", ((GMime.Part)part).Filename));
 
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 2690)
+++ Makefile.am	(working copy)
@@ -36,6 +36,10 @@
 SUBDIRS += bludgeon
 endif
 
+if ENABLE_THUNDERBIRD
+SUBDIRS += ContactViewer
+endif
+
 # When the chooser work has been fixed up to use libbeagle, we can
 # reenable this directory.
 # SUBDIRS += chooser-fu
Index: ContactViewer/beagle-contactviewer.in
===================================================================
--- ContactViewer/beagle-contactviewer.in	(revision 0)
+++ ContactViewer/beagle-contactviewer.in	(revision 0)
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# This line will be automatically uncommented when you "make install"
+#installed=1
+
+if [ -z $installed ] ; then
+    echo "*** Running uninstalled @target@ ***"
+    THIS_PATH="../Util:../images:../Lucene.Net"
+    THIS_EXE="./@target@"
+    export LD_LIBRARY_PATH="../glue/.libs${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
+else
+    THIS_PATH="@pkglibdir@"
+    THIS_EXE="@pkglibdir@/@target@"
+    export LD_LIBRARY_PATH="@pkglibdir ${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
+fi
+
+MONO_GAC_PREFIX="@gacprefix ${MONO_GAC_PREFIX+:$MONO_GAC_PREFIX}" MONO_PATH="$THIS_PATH${MONO_PATH+:$MONO_PATH}" exec -a beagle-contactviewer mono $MONO_EXTRA_ARGS --debug $THIS_EXE "$@"
+
Index: ContactViewer/ContactViewer.cs
===================================================================
--- ContactViewer/ContactViewer.cs	(revision 0)
+++ ContactViewer/ContactViewer.cs	(revision 0)
@@ -0,0 +1,105 @@
+//
+// ContactViewer.cs
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using System;
+using Mono.Unix;
+using Beagle.Util;
+
+namespace ContactViewer {
+
+	public enum ContactManager {
+		Thunderbird
+	}
+
+	public class ContactViewer {
+		
+		private static Uri uri = null;
+		private static string contact = null;
+		
+		public static void Main (string[] args)
+		{
+			Catalog.Init ("beagle", Beagle.Util.ExternalStringsHack.LocaleDir);
+			
+			SystemInformation.SetProcessName ("beagle-contactviewer");
+
+			ParseArgs (args);
+
+			ContactManager contact_manager;
+			try {
+				contact_manager = (ContactManager) Enum.Parse (typeof (ContactManager), contact, true);
+			} catch (Exception) {
+				Console.WriteLine ("ERROR: '{0}' is not a valid contact manager.", contact);
+				Environment.Exit (3);
+				return;
+			}
+
+			new ContactWindow (contact_manager, uri);
+		}
+		
+		private static void PrintUsageAndExit ()
+		{
+			Console.WriteLine ("USAGE: beagle-contactviewer --manager <MANAGER>  [OPTIONS] <uri>");
+			
+			Environment.Exit (0);
+		}
+		
+		private static void ParseArgs (string[] args)
+		{
+			if (args.Length < 1)
+				PrintUsageAndExit ();
+			
+			for (int i = 0; i < args.Length; i++) {
+				switch (args [i]) {
+				case "-h":
+				case "--help":
+					PrintUsageAndExit ();
+					break;
+				case "--manager":
+					contact = args [i + 1];
+					i++;
+					break;
+				default:
+					if (args [i].StartsWith ("--")) {
+						Console.WriteLine ("WARN: Invalid option {0}", args [i]);
+					} else {
+						try {
+							uri = new Uri (args [i]);
+						} catch (Exception e) {
+							Console.WriteLine ("ERROR: Invalid URI!");
+							Environment.Exit (1);
+						}
+					}
+					break;
+				}
+			}
+			
+			if (contact == null) {
+				Console.WriteLine ("ERROR: Please specify a valid contact manager.");
+				Environment.Exit (2);
+			}
+		}
+	}
+}
Index: ContactViewer/Makefile.in
===================================================================
--- ContactViewer/Makefile.in	(revision 0)
+++ ContactViewer/Makefile.in	(revision 0)
@@ -0,0 +1,545 @@
+# Makefile.in generated by automake 1.8.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+ SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = ContactViewer
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASH = @BASH@
+BEAGLED_CFLAGS = @BEAGLED_CFLAGS@
+BEAGLED_LIBS = @BEAGLED_LIBS@
+BEAGLE_DEFINES = @BEAGLE_DEFINES@
+BEAGLE_UI_CFLAGS = @BEAGLE_UI_CFLAGS@
+BEAGLE_UI_LIBS = @BEAGLE_UI_LIBS@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DESKTOP_LAUNCH = @DESKTOP_LAUNCH@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_BLUDGEON_FALSE = @ENABLE_BLUDGEON_FALSE@
+ENABLE_BLUDGEON_TRUE = @ENABLE_BLUDGEON_TRUE@
+ENABLE_DESKTOP_LAUNCH_FALSE = @ENABLE_DESKTOP_LAUNCH_FALSE@
+ENABLE_DESKTOP_LAUNCH_TRUE = @ENABLE_DESKTOP_LAUNCH_TRUE@
+ENABLE_EPIPHANY_EXTENSION_FALSE = @ENABLE_EPIPHANY_EXTENSION_FALSE@
+ENABLE_EPIPHANY_EXTENSION_TRUE = @ENABLE_EPIPHANY_EXTENSION_TRUE@
+ENABLE_EVOLUTION_FALSE = @ENABLE_EVOLUTION_FALSE@
+ENABLE_EVOLUTION_TRUE = @ENABLE_EVOLUTION_TRUE@
+ENABLE_GALAGO_FALSE = @ENABLE_GALAGO_FALSE@
+ENABLE_GALAGO_TRUE = @ENABLE_GALAGO_TRUE@
+ENABLE_GOOGLEDRIVER_FALSE = @ENABLE_GOOGLEDRIVER_FALSE@
+ENABLE_GOOGLEDRIVER_TRUE = @ENABLE_GOOGLEDRIVER_TRUE@
+ENABLE_GSF_SHARP_FALSE = @ENABLE_GSF_SHARP_FALSE@
+ENABLE_GSF_SHARP_TRUE = @ENABLE_GSF_SHARP_TRUE@
+ENABLE_GTK_DOC_FALSE = @ENABLE_GTK_DOC_FALSE@
+ENABLE_GTK_DOC_TRUE = @ENABLE_GTK_DOC_TRUE@
+ENABLE_GUI_FALSE = @ENABLE_GUI_FALSE@
+ENABLE_GUI_TRUE = @ENABLE_GUI_TRUE@
+ENABLE_INOTIFY_FALSE = @ENABLE_INOTIFY_FALSE@
+ENABLE_INOTIFY_TRUE = @ENABLE_INOTIFY_TRUE@
+ENABLE_LIBBEAGLE_FALSE = @ENABLE_LIBBEAGLE_FALSE@
+ENABLE_LIBBEAGLE_TRUE = @ENABLE_LIBBEAGLE_TRUE@
+ENABLE_OPEN_WITH_FALSE = @ENABLE_OPEN_WITH_FALSE@
+ENABLE_OPEN_WITH_TRUE = @ENABLE_OPEN_WITH_TRUE@
+ENABLE_PYTHON_FALSE = @ENABLE_PYTHON_FALSE@
+ENABLE_PYTHON_TRUE = @ENABLE_PYTHON_TRUE@
+ENABLE_THUNDERBIRD_FALSE = @ENABLE_THUNDERBIRD_FALSE@
+ENABLE_THUNDERBIRD_TRUE = @ENABLE_THUNDERBIRD_TRUE@
+ENABLE_WEBSERVICES_FALSE = @ENABLE_WEBSERVICES_FALSE@
+ENABLE_WEBSERVICES_TRUE = @ENABLE_WEBSERVICES_TRUE@
+ENABLE_WV1_FALSE = @ENABLE_WV1_FALSE@
+ENABLE_WV1_TRUE = @ENABLE_WV1_TRUE@
+EPIPHANY_DEPENDENCY_CFLAGS = @EPIPHANY_DEPENDENCY_CFLAGS@
+EPIPHANY_DEPENDENCY_LIBS = @EPIPHANY_DEPENDENCY_LIBS@
+EPIPHANY_EXTENSIONS_DIR = @EPIPHANY_EXTENSIONS_DIR@
+EPIPHANY_PREFIX = @EPIPHANY_PREFIX@
+EPIPHANY_REQUIRED = @EPIPHANY_REQUIRED@
+EVO_CFLAGS = @EVO_CFLAGS@
+EVO_LIBDIR = @EVO_LIBDIR@
+EVO_LIBS = @EVO_LIBS@
+EXEEXT = @EXEEXT@
+EXIF_SOVERSION = @EXIF_SOVERSION@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GAC_PREFIX = @GAC_PREFIX@
+GALAGO_CFLAGS = @GALAGO_CFLAGS@
+GALAGO_LIBS = @GALAGO_LIBS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNOME_PREFIX = @GNOME_PREFIX@
+GNOME_VFS_CFLAGS = @GNOME_VFS_CFLAGS@
+GNOME_VFS_LIBS = @GNOME_VFS_LIBS@
+GSF_SHARP_CFLAGS = @GSF_SHARP_CFLAGS@
+GSF_SHARP_LIBS = @GSF_SHARP_LIBS@
+GTK_BINARY_VERSION = @GTK_BINARY_VERSION@
+GTK_DOC_USE_LIBTOOL_FALSE = @GTK_DOC_USE_LIBTOOL_FALSE@
+GTK_DOC_USE_LIBTOOL_TRUE = @GTK_DOC_USE_LIBTOOL_TRUE@
+HAS_LIBCHM_FALSE = @HAS_LIBCHM_FALSE@
+HAS_LIBCHM_TRUE = @HAS_LIBCHM_TRUE@
+HAS_LIBXSS_FALSE = @HAS_LIBXSS_FALSE@
+HAS_LIBXSS_TRUE = @HAS_LIBXSS_TRUE@
+HTML_DIR = @HTML_DIR@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_EPIPHANY_EXTENSION_FALSE = @INSTALL_EPIPHANY_EXTENSION_FALSE@
+INSTALL_EPIPHANY_EXTENSION_TRUE = @INSTALL_EPIPHANY_EXTENSION_TRUE@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@
+INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@
+INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_ICONV = @INTLTOOL_ICONV@
+INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@
+INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_MSGFMT = @INTLTOOL_MSGFMT@
+INTLTOOL_MSGMERGE = @INTLTOOL_MSGMERGE@
+INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@
+INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@
+INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@
+INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@
+INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@
+INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@
+INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@
+INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@
+INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@
+INTLTOOL_XGETTEXT = @INTLTOOL_XGETTEXT@
+INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@
+INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@
+KDE_CONFIG = @KDE_CONFIG@
+KDE_PREFIX = @KDE_PREFIX@
+LDFLAGS = @LDFLAGS@
+LIBBEAGLE_CFLAGS = @LIBBEAGLE_CFLAGS@
+LIBBEAGLE_LIBS = @LIBBEAGLE_LIBS@
+LIBBEAGLE_VERSION_INFO = @LIBBEAGLE_VERSION_INFO@
+LIBEXIF_API_CHECK_CFLAGS = @LIBEXIF_API_CHECK_CFLAGS@
+LIBEXIF_API_CHECK_LIBS = @LIBEXIF_API_CHECK_LIBS@
+LIBEXIF_CFLAGS = @LIBEXIF_CFLAGS@
+LIBEXIF_LIBS = @LIBEXIF_LIBS@
+LIBEXIF_VERSION_CHECK_CFLAGS = @LIBEXIF_VERSION_CHECK_CFLAGS@
+LIBEXIF_VERSION_CHECK_LIBS = @LIBEXIF_VERSION_CHECK_LIBS@
+LIBGLIB_REQUIRED = @LIBGLIB_REQUIRED@
+LIBGTK_REQUIRED = @LIBGTK_REQUIRED@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTRAYICON_CFLAGS = @LIBTRAYICON_CFLAGS@
+LIBTRAYICON_LIBS = @LIBTRAYICON_LIBS@
+LIBXML_REQUIRED = @LIBXML_REQUIRED@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MCS = @MCS@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MONO = @MONO@
+MONO_CFLAGS = @MONO_CFLAGS@
+MONO_LIBS = @MONO_LIBS@
+MSGFMT = @MSGFMT@
+OBJEXT = @OBJEXT@
+OPEN_WITH_CFLAGS = @OPEN_WITH_CFLAGS@
+OPEN_WITH_LIBS = @OPEN_WITH_LIBS@
+OS_FREEBSD_FALSE = @OS_FREEBSD_FALSE@
+OS_FREEBSD_TRUE = @OS_FREEBSD_TRUE@
+OS_LINUX_FALSE = @OS_LINUX_FALSE@
+OS_LINUX_TRUE = @OS_LINUX_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYBEAGLE_CFLAGS = @PYBEAGLE_CFLAGS@
+PYBEAGLE_LIBS = @PYBEAGLE_LIBS@
+PYGTK_CODEGEN = @PYGTK_CODEGEN@
+PYGTK_DEFSDIR = @PYGTK_DEFSDIR@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHARPZIPLIB_LIBS = @SHARPZIPLIB_LIBS@
+SHELL = @SHELL@
+SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
+SQLITE_CFLAGS = @SQLITE_CFLAGS@
+SQLITE_LIBS = @SQLITE_LIBS@
+SQLITE_MAJ_VER = @SQLITE_MAJ_VER@
+STRIP = @STRIP@
+SYSTEMINFO_GLUE_CFLAGS = @SYSTEMINFO_GLUE_CFLAGS@
+SYSTEMINFO_GLUE_LIBS = @SYSTEMINFO_GLUE_LIBS@
+SYSTEMINFO_GLUE_X_LIBS = @SYSTEMINFO_GLUE_X_LIBS@
+UIGLUE_CFLAGS = @UIGLUE_CFLAGS@
+UIGLUE_LIBS = @UIGLUE_LIBS@
+USE_LOCAL_SQLITE_FALSE = @USE_LOCAL_SQLITE_FALSE@
+USE_LOCAL_SQLITE_TRUE = @USE_LOCAL_SQLITE_TRUE@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WSDL = @WSDL@
+WV1_CFLAGS = @WV1_CFLAGS@
+WV1_LIBS = @WV1_LIBS@
+XGETTEXT = @XGETTEXT@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+ZIP = @ZIP@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+CSC = mcs -debug
+TARGET = ContactViewer.exe
+WRAPPER = beagle-contactviewer
+CSFLAGS = -target:exe
+CSFILES = \
+	$(srcdir)/ContactViewer.cs	\
+	$(srcdir)/ContactWindow.cs
+
+LOCAL_ASSEMBLIES = \
+	../Util/Util.dll		\
+	../images/Images.dll
+
+ASSEMBLIES = \
+	$(BEAGLE_UI_LIBS)		\
+	$(LOCAL_ASSEMBLIES:%=-r:%)	\
+	-r:Mono.Posix
+
+RESOURCEFILES = \
+	$(srcdir)/contactviewer.glade	\
+	$(srcdir)/menu.xml
+
+
+# Makefile-fu to map /path/filename to -resource:/path/filename,filename
+RESOURCES = $(join $(RESOURCEFILES:%=-resource:%,),$(notdir $(RESOURCEFILES)))
+EXTRA_DIST = \
+	$(CSFILES)		\
+	$(WRAPPER).in		\
+	$(RESOURCEFILES)
+
+CLEANFILES = \
+	$(TARGET)	\
+	$(TARGET).mdb	\
+	$(WRAPPER)	
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  ContactViewer/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  ContactViewer/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	$(mkdir_p) $(distdir)/$(srcdir)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-local
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	distclean distclean-generic distclean-libtool distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-data-local install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	uninstall uninstall-am uninstall-info-am uninstall-local
+
+
+$(TARGET): $(CSFILES) $(LOCAL_ASSEMBLIES) $(RESOURCEFILES)
+	$(CSC) -out:$@ $(CSFLAGS) $(CSFILES) $(ASSEMBLIES) $(RESOURCES)
+
+all: $(TARGET) $(WRAPPER)
+
+install-data-local: $(TARGET)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
+	$(INSTALL_DATA) $(TARGET) $(TARGET).mdb $(DESTDIR)$(pkglibdir)
+	sed -e "s|\#installed=1|installed=1|" < $(WRAPPER) > $(WRAPPER).tmp
+	$(INSTALL_SCRIPT) $(WRAPPER).tmp $(DESTDIR)$(bindir)/$(WRAPPER)
+	rm -f $(WRAPPER).tmp
+
+uninstall-local:
+	rm -f $(DESTDIR)$(pkglibdir)/$(TARGET)
+	rm -f $(DESTDIR)$(pkglibdir)/$(TARGET).mdb
+	rm -f $(DESTDIR)$(bindir)/$(WRAPPER)
+
+$(WRAPPER): $(srcdir)/$(WRAPPER).in
+	sed -e "s|\ prefix\@|$(prefix)|g" -e "s|\ pkglibdir\@|$(pkglibdir)|g" -e "s|\ target\@|$(TARGET)|g" -e "s|\ gacprefix\@|$(GAC_PREFIX)|g" < $^ > $@
+	chmod +x $(WRAPPER)
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: ContactViewer/menu.xml
===================================================================
--- ContactViewer/menu.xml	(revision 0)
+++ ContactViewer/menu.xml	(revision 0)
@@ -0,0 +1,12 @@
+<ui>
+ <menubar name="MainMenu">
+  <menu name="FileMenu" action="FileMenuAction">
+   <menuitem name="Open" action="OpenAction" />
+   <separator />
+   <menuitem name="Quit" action="QuitAction" />
+  </menu>
+  <menu name="HelpMenu" action="HelpMenuAction">
+   <menuitem name="About" action="AboutAction" />
+  </menu>
+ </menubar>
+</ui>
Index: ContactViewer/ContactWindow.cs
===================================================================
--- ContactViewer/ContactWindow.cs	(revision 0)
+++ ContactViewer/ContactWindow.cs	(revision 0)
@@ -0,0 +1,446 @@
+//
+// ContactWindow.cs
+//
+// Copyright (C) 2006 Pierre Ã?stlund
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+
+using Gtk;
+using Glade;
+using System;
+using System.Collections;
+using System.Text.RegularExpressions;
+
+using Beagle.Util;
+using Mono.Unix;
+
+namespace ContactViewer {
+
+	public class ContactWindow {
+		private Glade.XML gxml;
+		private UIManager ui_manager;
+		
+		[Widget] Gtk.TreeView ContactList;
+		[Widget] Gtk.ComboBox ListIdentifier;
+		[Widget] Gtk.Statusbar Statusbar;
+		[Widget] Gtk.Window MainWindow;
+		[Widget] Gtk.EventBox MenubarHolder;
+		[Widget] Gtk.EventBox ContactHolder;
+	
+		private ListStore contact_store;
+		private ListStore contact_show_type_store;
+	
+		private Uri uri;
+		private MorkDatabase database;
+		//private ContactManager contact_manager;
+		
+		public ContactWindow (ContactManager contact_manager, Uri uri)
+		{
+			this.uri = uri;
+			//this.contact_manager = contact_manager;
+			
+			ShowWindow ();
+		}
+		
+		public void ShowWindow ()
+		{
+			Application.Init ();
+			
+			gxml = new Glade.XML ("contactviewer.glade", "MainWindow");
+			gxml.Autoconnect (this);
+			
+			ActionEntry[] entries = new ActionEntry [] {
+				new ActionEntry ("FileMenuAction", null, "_File", null, null, null),
+				new ActionEntry ("OpenAction", Gtk.Stock.Open,
+					"_Open", "<control>O", Catalog.GetString ("Open..."), new EventHandler (OnOpenDatabase)),
+				new ActionEntry ("QuitAction", Gtk.Stock.Quit,
+					"_Quit", "<control>Q", Catalog.GetString ("Quit"), new EventHandler (OnQuit)),
+				new ActionEntry ("HelpMenuAction", null, "_Help", null, null, null),
+				new ActionEntry ("AboutAction", Gtk.Stock.About,
+					"_About", null, Catalog.GetString ("About"), new EventHandler (OnAbout))
+			};
+			
+			ActionGroup grp = new ActionGroup ("MainGroup");
+			grp.Add (entries);
+			
+			ui_manager = new UIManager ();
+			ui_manager.InsertActionGroup(grp, 0);
+			ui_manager.AddUiFromResource ("menu.xml");
+			MenubarHolder.Add (ui_manager.GetWidget ("/MainMenu"));
+			
+			// Fix the TreeView that will contain all contacts
+			contact_store = new ListStore (typeof (string), typeof (string));
+			
+			ContactList.Model = contact_store;
+			ContactList.RulesHint = true;
+			ContactList.AppendColumn (Catalog.GetString ("Contacts"), new CellRendererText (), "text", 1);
+			ContactList.ButtonReleaseEvent += OnContactSelected;
+			
+			// This ListStore will let the user choose what to see in the contact list
+			contact_show_type_store = new ListStore (typeof (string), typeof (string));
+			contact_show_type_store.AppendValues ("DisplayName", Catalog.GetString ("Display name"));
+			contact_show_type_store.AppendValues ("PrimaryEmail", Catalog.GetString ("Primary E-mail"));
+			contact_show_type_store.AppendValues ("SecondEmail", Catalog.GetString ("Secondary E-mail"));
+			contact_show_type_store.AppendValues ("NickName", Catalog.GetString ("Nickname"));
+			
+			CellRendererText cell = new CellRendererText ();
+			ListIdentifier.PackStart (cell, false);
+			ListIdentifier.AddAttribute (cell, "text", 1);
+			ListIdentifier.Model = contact_show_type_store;
+			ListIdentifier.Active = 0;
+			ListIdentifier.Changed += OnContactListTypeChanged;
+			
+			MainWindow.Icon = Beagle.Images.GetPixbuf ("contact-icon.png");
+			MainWindow.DeleteEvent += OnDeleteEvent;
+			
+			LoadDatabase ();
+			Application.Run ();
+		}
+
+		public void LoadDatabase ()
+		{
+			// Load the database file
+			try {
+				database = new MorkDatabase (uri.AbsolutePath);
+				database.Read ();
+				database.EnumNamespace = "ns:addrbk:db:row:scope:card:all";
+			} catch (Exception e) {
+				MessageDialog dialog = new MessageDialog (
+					MainWindow,
+					DialogFlags.DestroyWithParent, 
+					MessageType.Error, 
+					ButtonsType.Ok, 
+					false, 
+					String.Format (Catalog.GetString ("Unable to open mork database:\n\n {0}"), e.Message));
+				
+				dialog.Run ();
+				dialog.Destroy ();
+				Environment.Exit (1);
+			}
+			
+			// Populate the gui with nice stuff
+			Clear ();
+			FillContactList ();
+			
+			try {
+				Match m = Regex.Match (uri.Query, @"\?id=(?<id>[0-9A-Fa-f]+)");	
+				ShowContact (m.Result ("${id}"));
+			} catch (Exception e) {
+				Gtk.MessageDialog dialog = new MessageDialog (
+					MainWindow,
+					DialogFlags.DestroyWithParent,
+					MessageType.Warning,
+					ButtonsType.Ok,
+					Catalog.GetString ("The specified ID does not exist in this database!"));
+				
+				dialog.Run ();
+				dialog.Destroy ();
+			}
+		}
+		
+		public void FillContactList ()
+		{
+			TreeIter iter;
+			int count = 0;
+			
+			if (!ListIdentifier.GetActiveIter (out iter)) 
+				return;
+			
+			contact_store.Clear ();
+			
+			// Add contacts to treeview
+			foreach (string id in database) {
+				Hashtable tbl = database.Compile (id, database.EnumNamespace);
+				
+				if (tbl ["table"] != null && tbl ["table"] as string == "BF") {
+					contact_store.AppendValues (tbl ["id"], tbl [contact_show_type_store.GetValue (iter, 0)]);
+					count++;
+				}
+			}
+			
+			SetStatusMessage (String.Format (Catalog.GetString ("Added {0} contacts"), count));
+		}
+		
+		public void ShowContact (string id)
+		{
+			TreeIter iter;
+			Hashtable tbl = database.Compile (id, database.EnumNamespace);
+			
+			if (ContactHolder.Child != null)
+				ContactHolder.Remove (ContactHolder.Child);
+			
+			ContactHolder.Add (new Contact (tbl));
+			MainWindow.ShowAll ();
+			
+			// Update selection in the contact list as well
+			if (contact_store.GetIterFirst (out iter)) {
+				do {
+					if (contact_store.GetValue (iter, 0) as string == id) {
+						ContactList.Selection.SelectIter (iter);
+						break;
+					}	
+				} while (contact_store.IterNext (ref iter));
+			}
+			
+			SetStatusMessage (String.Format (Catalog.GetString ("Viewing {0}"), 
+				(ContactHolder.Child as Contact).GetString ("DisplayName")));
+		}
+		
+		public void Clear ()
+		{
+			if (ContactHolder.Child != null)
+				ContactHolder.Remove (ContactHolder.Child);
+			
+			contact_store.Clear ();
+		}
+		
+		public void SetStatusMessage (string message)
+		{
+			Statusbar.Pop (0);
+			Statusbar.Push (0, message);
+		}
+
+		protected virtual void OnContactSelected (object o, ButtonReleaseEventArgs args)
+		{
+			TreeIter iter;
+			TreeModel model;
+			
+			if (!ContactList.Selection.GetSelected (out model, out iter))
+				return;
+			
+			ShowContact ((string) model.GetValue (iter, 0));
+		}
+		
+		protected virtual void OnContactListTypeChanged (object o, EventArgs args)
+		{
+			FillContactList ();
+		}
+		
+		protected virtual void OnOpenDatabase (object o, EventArgs args)
+		{
+			Uri uri;
+			ResponseType response;
+			FileChooserDialog chooser;
+			
+			chooser = new FileChooserDialog (Catalog.GetString ("Select a mork database file"), 
+				MainWindow, FileChooserAction.Open);
+			chooser.LocalOnly = true;
+			chooser.AddButton (Gtk.Stock.Cancel, ResponseType.Cancel);
+			chooser.AddButton (Gtk.Stock.Ok, ResponseType.Ok);
+			
+			response = (ResponseType) chooser.Run ();
+			uri = new Uri (chooser.Uri);
+			chooser.Destroy ();
+			
+			if (response == ResponseType.Ok) {
+				this.uri = uri;
+				LoadDatabase ();
+			}
+		}
+		
+		protected virtual void OnAbout (object o, EventArgs args)
+		{
+			AboutDialog about = new AboutDialog();
+			about.Authors = (new string[] { "Pierre \u00D6stlund" });
+			about.Name = "Contact Viewer";
+			about.Version = "0.1";
+			about.Website = "http://www.beagle-project.org";;
+			about.Logo = Beagle.Images.GetPixbuf ("system-search.png");
+			about.Icon = Beagle.Images.GetPixbuf ("icon-search.png");
+			
+			about.Run();
+			about.Destroy();
+		}
+		
+		protected virtual void OnQuit (object o, EventArgs args)
+		{
+			Application.Quit ();
+		}
+		
+		protected virtual void OnDeleteEvent (object o, DeleteEventArgs args)
+		{
+			Application.Quit ();
+		}
+	}
+	
+	public class Contact : VBox {
+		private Hashtable contact;
+	
+		public Contact (Hashtable contact) :
+			base (false, 10)
+		{
+			HBox hbox;
+			Table table;
+			Button button;
+			HButtonBox hbuttonbox;
+			
+			this.contact = contact;
+			
+			// Create header containing an icon and display name
+			hbox = new HBox ();
+			hbox.Spacing = 10;
+			hbox.PackStart (Beagle.Images.GetWidget ("person.png"), false, false, 0);
+			hbox.PackStart (new VLabel (String.Format ("<b><span size='large'>{0} \"{1}\" {2}</span></b>", 
+				GetString ("FirstName"), GetString ("NickName"), GetString ("LastName")), false));
+			PackStart (hbox, false, false, 0);
+			PackStart (new HSeparator (), false, false, 0);
+			
+			// Create a table containing some user information
+			table = new Table (5, 2, false);
+			PackStart (table, false, false, 0);
+			
+			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Primary E-Mail:")), false), 
+				0, 1, 0, 1, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
+			table.Attach (new VLabel (GetString ("PrimaryEmail"), true), 1, 2, 0, 1);
+				
+			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Screen name:")), false), 
+				0, 1, 1, 2, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
+			table.Attach (new VLabel (GetString ("_AimScreenName"), true), 1, 2, 1, 2);
+				
+			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Home phone:")), false), 
+				0, 1, 2, 3, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
+			table.Attach (new VLabel (GetString ("HomePhone"), true), 1, 2, 2, 3);
+				
+			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Mobile phone:")), false), 
+				0, 1, 3, 4, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
+			table.Attach (new VLabel (GetString ("CellularNumber"), true), 1, 2, 3, 4);
+				
+			table.Attach (new VLabel (String.Format ("<b>{0}</b>", Catalog.GetString ("Web page:")), false), 
+				0, 1, 4, 5, AttachOptions.Shrink | AttachOptions.Fill, AttachOptions.Shrink, 10, 0);
+			table.Attach (new VLabel (GetString ("WebPage2"), true), 1, 2, 4, 5);
+					
+			// Add a button row with some informational buttons
+			hbuttonbox = new HButtonBox ();
+			hbuttonbox.Layout = ButtonBoxStyle.End;
+			PackEnd (hbuttonbox, false, false, 0);
+			
+			button = new Button (Catalog.GetString ("Send E-Mail"));
+			button.Clicked += OnSendEmail;
+			hbuttonbox.Add (button);
+			
+			button = new Button (Catalog.GetString ("Details..."));
+			button.Clicked += OnDetails;
+			hbuttonbox.Add (button);
+		}
+		
+		public string GetString (string str)
+		{
+			if (!contact.ContainsKey (str))
+				return "N/A";
+			
+			return contact [str] as string;
+		}
+		
+		protected virtual void OnSendEmail (object o, EventArgs args)
+		{
+			string mail = null;
+			SafeProcess process;
+			
+			if (contact ["PrimaryEmail"] != null)
+				mail = contact ["PrimaryEmail"] as string;
+			else if (contact ["SecondEmail"] != null)
+				mail = contact ["SecondMail"] as string;
+			else {
+				MessageDialog dialog = new MessageDialog (
+					null,
+					DialogFlags.DestroyWithParent, 
+					MessageType.Warning,
+					ButtonsType.Ok, 
+					Catalog.GetString ("Could not find a valid E-mail address!"));
+				
+				dialog.Run ();
+				dialog.Destroy ();
+				return;
+			}
+			
+			process = new SafeProcess ();
+			process.Arguments = new string [2];
+			process.Arguments [0] = "thunderbird";
+			process.Arguments [1] = String.Format ("mailto:{0}";, mail);
+			process.Start ();
+		}
+		
+		protected virtual void OnDetails (object o, EventArgs args)
+		{
+			new DetailedWindow (contact);
+		}
+
+		public class VLabel : Label {
+			
+			public VLabel (string label, bool selectable) :
+				base (label)
+			{
+				Xalign = 0.0f;
+				UseMarkup = true;
+				Selectable = selectable;
+			}
+		}
+		
+	}
+	
+	public class DetailedWindow {
+		private Glade.XML gxml;
+		
+		[Widget] Gtk.Button Close;
+		[Widget ("DetailedWindow")] Gtk.Window Window;
+		[Widget] Gtk.TextView Notes;
+		[Widget] Gtk.ComboBox PreferredType;
+		
+		string[] widget_names = new string[] {"FirstName", "LastName", "DisplayName", 
+			"NickName", "PrimaryEmail", "SecondEmail", "_AimScreenName", "WorkPhone",
+			"HomePhone", "FaxNumber", "PagerNumber", "CellularNumber", "HomeAddress",
+			"HomeAddress2", "HomeCity", "HomeCountry", "WebPage2", "HomeZipCode",
+			"HomeState", "WorkState", "WorkZipCode", "JobTitle", "Department", "Company",
+			"WorkAddress", "WorkAddress2", "WorkCity", "WorkCountry", "WebPage1",
+			"Custom1", "Custom2", "Custom3", "Custom4"};
+		
+		public DetailedWindow (Hashtable contact)
+		{
+			gxml = new Glade.XML (null, "contactviewer.glade", "DetailedWindow", null);
+			gxml.Autoconnect (this);
+			
+			// Fill all Entry-boxes with information
+			foreach (string name in widget_names)
+				(gxml.GetWidget (name) as Gtk.Entry).Text = (contact [name] != null ? (contact [name] as string) : "");;
+			
+			// Also fill the special cases
+			Notes.Buffer.Text = (contact ["Notes"] != null ? (contact ["Notes"] as string) : "");
+			
+			try {
+				int tmp = Convert.ToInt32 (contact ["PreferMailFormat"]);
+				PreferredType.Active = (tmp >= 0 && tmp <= 2 ? tmp : 0);
+			} catch (Exception e) {
+				PreferredType.Active = 0;
+			}
+			
+			Close.Clicked += OnClose;
+			
+			Window.Icon = Beagle.Images.GetPixbuf ("contact-icon.png");
+			Window.Show ();
+		}
+		
+		protected virtual void OnClose (object o, EventArgs args)
+		{
+			Window.Hide ();
+		}
+	}
+}
Index: ContactViewer/contactviewer.glade
===================================================================
--- ContactViewer/contactviewer.glade	(revision 0)
+++ ContactViewer/contactviewer.glade	(revision 0)
@@ -0,0 +1,2399 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd";>
+
+<glade-interface>
+
+<widget class="GtkWindow" id="MainWindow">
+  <property name="width_request">630</property>
+  <property name="height_request">380</property>
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Contact Viewer</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+
+  <child>
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+	<widget class="GtkEventBox" id="MenubarHolder">
+	  <property name="visible">True</property>
+	  <property name="visible_window">True</property>
+	  <property name="above_child">False</property>
+
+	  <child>
+	    <placeholder/>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHPaned" id="hpaned1">
+	  <property name="border_width">5</property>
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="position">200</property>
+
+	  <child>
+	    <widget class="GtkVBox" id="vbox2">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">5</property>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow1">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="shadow_type">GTK_SHADOW_IN</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTreeView" id="ContactList">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="headers_visible">True</property>
+		      <property name="rules_hint">False</property>
+		      <property name="reorderable">False</property>
+		      <property name="enable_search">True</property>
+		      <property name="fixed_height_mode">False</property>
+		      <property name="hover_selection">False</property>
+		      <property name="hover_expand">False</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkComboBox" id="ListIdentifier">
+		  <property name="visible">True</property>
+		  <property name="add_tearoffs">False</property>
+		  <property name="focus_on_click">True</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="shrink">True</property>
+	      <property name="resize">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkEventBox" id="ContactHolder">
+	      <property name="border_width">5</property>
+	      <property name="visible">True</property>
+	      <property name="visible_window">True</property>
+	      <property name="above_child">False</property>
+
+	      <child>
+		<placeholder/>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="shrink">True</property>
+	      <property name="resize">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkStatusbar" id="Statusbar">
+	  <property name="visible">True</property>
+	  <property name="has_resize_grip">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkWindow" id="DetailedWindow">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Detailed view</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+
+  <child>
+    <widget class="GtkVBox" id="vbox3">
+      <property name="border_width">10</property>
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">10</property>
+
+      <child>
+	<widget class="GtkNotebook" id="notebook1">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="show_tabs">True</property>
+	  <property name="show_border">True</property>
+	  <property name="tab_pos">GTK_POS_TOP</property>
+	  <property name="scrollable">False</property>
+	  <property name="enable_popup">False</property>
+
+	  <child>
+	    <widget class="GtkVBox" id="vbox4">
+	      <property name="border_width">10</property>
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">10</property>
+
+	      <child>
+		<widget class="GtkFrame" id="frame1">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment1">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="table1">
+			  <property name="visible">True</property>
+			  <property name="n_rows">4</property>
+			  <property name="n_columns">2</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">0</property>
+			  <property name="column_spacing">0</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="FirstNameLabel">
+			      <property name="width_request">130</property>
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">First:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="LastNameLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Last:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="DisplayNameLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Display:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="NicknameLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Nickname:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="FirstName">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="LastName">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="DisplayName">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="NickName">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="NameTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Name&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkFrame" id="frame2">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment2">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="table2">
+			  <property name="visible">True</property>
+			  <property name="n_rows">4</property>
+			  <property name="n_columns">2</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">0</property>
+			  <property name="column_spacing">0</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="PrimaryEmailLabel">
+			      <property name="width_request">130</property>
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">E-Mail:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="SecondaryEmailLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Additional E-Mail:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="PreferredFormatLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Preferred format:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="ScreenNameLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Screen name:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="PrimaryEmail">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="SecondEmail">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="_AimScreenName">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkComboBox" id="PreferredType">
+			      <property name="visible">True</property>
+			      <property name="items" translatable="yes">Unknown
+Plain text
+HTML</property>
+			      <property name="add_tearoffs">False</property>
+			      <property name="focus_on_click">True</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options">fill</property>
+			    </packing>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="InternetTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Internet&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkFrame" id="frame3">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment3">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="table3">
+			  <property name="visible">True</property>
+			  <property name="n_rows">5</property>
+			  <property name="n_columns">2</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">0</property>
+			  <property name="column_spacing">0</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkPhoneLabel">
+			      <property name="width_request">130</property>
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Work:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="HomePhoneLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Home:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="FaxPhoneLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Fax:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="PagerPhoneLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Pager:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="MobilePhoneLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Mobile:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">4</property>
+			      <property name="bottom_attach">5</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkPhone">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomePhone">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="FaxNumber">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="PagerNumber">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="CellularNumber">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">4</property>
+			      <property name="bottom_attach">5</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="PhonesTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Phones&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label5">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Contact</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkVBox" id="vbox5">
+	      <property name="border_width">10</property>
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">10</property>
+
+	      <child>
+		<widget class="GtkFrame" id="frame4">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment4">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="table4">
+			  <property name="visible">True</property>
+			  <property name="n_rows">6</property>
+			  <property name="n_columns">4</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">0</property>
+			  <property name="column_spacing">0</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="HomeAddressLabel">
+			      <property name="width_request">130</property>
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Address:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="HomeCityLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">City:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="StateHomeLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">State/Province:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="CountryHomeLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Country:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">4</property>
+			      <property name="bottom_attach">5</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WebPageHomeLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Web Page:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">5</property>
+			      <property name="bottom_attach">6</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomeAddress">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomeAddress2">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomeCity">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomeCountry">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">4</property>
+			      <property name="bottom_attach">5</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WebPage2">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">5</property>
+			      <property name="bottom_attach">6</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="HomePostalLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">ZIP/Postal Code</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">1</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">2</property>
+			      <property name="right_attach">3</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomeZipCode">
+			      <property name="width_request">70</property>
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">3</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="HomeState">
+			      <property name="width_request">70</property>
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="HomeTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Home&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkFrame" id="frame5">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment5">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="table5">
+			  <property name="visible">True</property>
+			  <property name="n_rows">9</property>
+			  <property name="n_columns">4</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">0</property>
+			  <property name="column_spacing">0</property>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkState">
+			      <property name="width_request">70</property>
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">6</property>
+			      <property name="bottom_attach">7</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkZipCode">
+			      <property name="width_request">70</property>
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">3</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">6</property>
+			      <property name="bottom_attach">7</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkTitleLabel">
+			      <property name="width_request">130</property>
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Title:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkDepartmentLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Department:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkOrganizationLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Organization:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkAddressLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Address:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkCityLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">City:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">5</property>
+			      <property name="bottom_attach">6</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkStateLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">State/Province</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">6</property>
+			      <property name="bottom_attach">7</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkCountryLabel">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Country:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">7</property>
+			      <property name="bottom_attach">8</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="WorkWebPage">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Web Page:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">8</property>
+			      <property name="bottom_attach">9</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="label42">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">ZIP/Postal Code:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">1</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">2</property>
+			      <property name="right_attach">3</property>
+			      <property name="top_attach">6</property>
+			      <property name="bottom_attach">7</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="JobTitle">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="Department">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="Company">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkAddress">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkAddress2">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">4</property>
+			      <property name="bottom_attach">5</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkCity">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">5</property>
+			      <property name="bottom_attach">6</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WorkCountry">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">7</property>
+			      <property name="bottom_attach">8</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="WebPage1">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">4</property>
+			      <property name="top_attach">8</property>
+			      <property name="bottom_attach">9</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="WorkTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Work&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label6">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Address</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkVBox" id="vbox6">
+	      <property name="border_width">10</property>
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">10</property>
+
+	      <child>
+		<widget class="GtkFrame" id="frame6">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment6">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="table6">
+			  <property name="visible">True</property>
+			  <property name="n_rows">4</property>
+			  <property name="n_columns">2</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">0</property>
+			  <property name="column_spacing">0</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="Custom1Label">
+			      <property name="width_request">130</property>
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Custom 1:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="Custom2Label">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Custom 2:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="Custom3Label">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Custom 3:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="Custom4Label">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Custom 4:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="Custom1">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="Custom2">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="Custom3">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">2</property>
+			      <property name="bottom_attach">3</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkEntry" id="Custom4">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">0</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">â??</property>
+			      <property name="activates_default">False</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">3</property>
+			      <property name="bottom_attach">4</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="CustomTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Custom fields&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkFrame" id="frame7">
+		  <property name="visible">True</property>
+		  <property name="label_xalign">0</property>
+		  <property name="label_yalign">0.5</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+		  <child>
+		    <widget class="GtkAlignment" id="alignment7">
+		      <property name="visible">True</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xscale">1</property>
+		      <property name="yscale">1</property>
+		      <property name="top_padding">5</property>
+		      <property name="bottom_padding">0</property>
+		      <property name="left_padding">12</property>
+		      <property name="right_padding">0</property>
+
+		      <child>
+			<widget class="GtkScrolledWindow" id="scrolledwindow2">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+			  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+			  <property name="shadow_type">GTK_SHADOW_IN</property>
+			  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+			  <child>
+			    <widget class="GtkTextView" id="Notes">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">False</property>
+			      <property name="overwrite">False</property>
+			      <property name="accepts_tab">True</property>
+			      <property name="justification">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap_mode">GTK_WRAP_NONE</property>
+			      <property name="cursor_visible">True</property>
+			      <property name="pixels_above_lines">0</property>
+			      <property name="pixels_below_lines">0</property>
+			      <property name="pixels_inside_wrap">0</property>
+			      <property name="left_margin">0</property>
+			      <property name="right_margin">0</property>
+			      <property name="indent">0</property>
+			      <property name="text" translatable="yes"></property>
+			    </widget>
+			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="NoteTopicLabel">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Notes&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="type">label_item</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label7">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Other</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHButtonBox" id="hbuttonbox2">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkButton" id="Close">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-close</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
Index: ContactViewer/Makefile.am
===================================================================
--- ContactViewer/Makefile.am	(revision 0)
+++ ContactViewer/Makefile.am	(revision 0)
@@ -0,0 +1,59 @@
+
+CSC = mcs -debug
+
+TARGET = ContactViewer.exe
+WRAPPER = beagle-contactviewer
+
+CSFLAGS = -target:exe
+
+CSFILES =				\
+	$(srcdir)/ContactViewer.cs	\
+	$(srcdir)/ContactWindow.cs
+
+LOCAL_ASSEMBLIES =			\
+	../Util/Util.dll		\
+	../images/Images.dll
+
+ASSEMBLIES =				\
+	$(BEAGLE_UI_LIBS)		\
+	$(LOCAL_ASSEMBLIES:%=-r:%)	\
+	-r:Mono.Posix
+
+RESOURCEFILES =				\
+	$(srcdir)/contactviewer.glade	\
+	$(srcdir)/menu.xml
+
+# Makefile-fu to map /path/filename to -resource:/path/filename,filename
+RESOURCES = $(join $(RESOURCEFILES:%=-resource:%,),$(notdir $(RESOURCEFILES)))
+
+$(TARGET): $(CSFILES) $(LOCAL_ASSEMBLIES) $(RESOURCEFILES)
+	$(CSC) -out:$@ $(CSFLAGS) $(CSFILES) $(ASSEMBLIES) $(RESOURCES)
+
+all: $(TARGET) $(WRAPPER)
+
+install-data-local: $(TARGET)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
+	$(INSTALL_DATA) $(TARGET) $(TARGET).mdb $(DESTDIR)$(pkglibdir)
+	sed -e "s|\#installed=1|installed=1|" < $(WRAPPER) > $(WRAPPER).tmp
+	$(INSTALL_SCRIPT) $(WRAPPER).tmp $(DESTDIR)$(bindir)/$(WRAPPER)
+	rm -f $(WRAPPER).tmp
+
+uninstall-local:
+	rm -f $(DESTDIR)$(pkglibdir)/$(TARGET)
+	rm -f $(DESTDIR)$(pkglibdir)/$(TARGET).mdb
+	rm -f $(DESTDIR)$(bindir)/$(WRAPPER)
+
+$(WRAPPER): $(srcdir)/$(WRAPPER).in
+	sed -e "s|\ prefix\@|$(prefix)|g" -e "s|\ pkglibdir\@|$(pkglibdir)|g" -e "s|\ target\@|$(TARGET)|g" -e "s|\ gacprefix\@|$(GAC_PREFIX)|g" < $^ > $@
+	chmod +x $(WRAPPER)
+
+EXTRA_DIST =			\
+	$(CSFILES)		\
+	$(WRAPPER).in		\
+	$(RESOURCEFILES)
+
+CLEANFILES =		\
+	$(TARGET)	\
+	$(TARGET).mdb	\
+	$(WRAPPER)	
Index: ContactViewer/beagle-contactviewer
===================================================================
--- ContactViewer/beagle-contactviewer	(revision 0)
+++ ContactViewer/beagle-contactviewer	(revision 0)
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# This line will be automatically uncommented when you "make install"
+#installed=1
+
+if [ -z $installed ] ; then
+    echo "*** Running uninstalled ContactViewer.exe ***"
+    THIS_PATH="../Util:../images:../Lucene.Net"
+    THIS_EXE="./ContactViewer.exe"
+    export LD_LIBRARY_PATH="../glue/.libs${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
+else
+    THIS_PATH="/usr/lib/beagle"
+    THIS_EXE="/usr/lib/beagle/ContactViewer.exe"
+    export LD_LIBRARY_PATH="/usr/lib/beagle${LD_LIBRARY_PATH+:$LD_LIBRARY_PATH}"
+fi
+
+MONO_GAC_PREFIX="/usr${MONO_GAC_PREFIX+:$MONO_GAC_PREFIX}" MONO_PATH="$THIS_PATH${MONO_PATH+:$MONO_PATH}" exec -a beagle-contactviewer mono $MONO_EXTRA_ARGS --debug $THIS_EXE "$@"
+
Index: ContactViewer/Makefile
===================================================================
--- ContactViewer/Makefile	(revision 0)
+++ ContactViewer/Makefile	(revision 0)
@@ -0,0 +1,545 @@
+# Makefile.in generated by automake 1.8.5 from Makefile.am.
+# ContactViewer/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+srcdir = .
+top_srcdir = ..
+
+pkgdatadir = $(datadir)/beagle
+pkglibdir = $(libdir)/beagle
+pkgincludedir = $(includedir)/beagle
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+target_triplet = i686-pc-linux-gnu
+subdir = ContactViewer
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+	$(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/kjk38/src/beagle/missing --run aclocal-1.8
+ALL_LINGUAS = bg ca cs da de el en_CA en_GB es fi fr gl he hi hu it ja ka ko lt lv mk nb nl pa pl pt_BR ru sv tr uk vi zh_CN zh_HK zh_TW
+AMDEP_FALSE = #
+AMDEP_TRUE = 
+AMTAR = ${SHELL} /home/kjk38/src/beagle/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /home/kjk38/src/beagle/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/kjk38/src/beagle/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/kjk38/src/beagle/missing --run automake-1.8
+AWK = gawk
+BASH = /bin/sh
+BEAGLED_CFLAGS = -I:/usr/lib/pkgconfig/../../share/gapi-2.0/pango-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/atk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gdk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gtk-api.xml  
+BEAGLED_LIBS = -r:/usr/lib/mono/gmime-sharp/gmime-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/pango-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/atk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gdk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gtk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/glib-sharp.dll   -r:/usr/lib/mono/gtk-sharp/gsf-sharp.dll  
+BEAGLE_DEFINES = 
+BEAGLE_UI_CFLAGS = -I:/usr/lib/pkgconfig/../../share/gapi-2.0/pango-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/atk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gdk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gtk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gnome-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/art-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gnome-vfs-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/glade-api.xml  
+BEAGLE_UI_LIBS = -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/pango-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/atk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gdk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gtk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/glib-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gconf-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gconf-sharp-peditors.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gnome-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/art-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gnome-vfs-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/glade-sharp.dll -r:/usr/lib/mono/gmime-sharp/gmime-sharp.dll  
+CATALOGS =  bg.gmo ca.gmo cs.gmo da.gmo de.gmo el.gmo en_CA.gmo en_GB.gmo es.gmo fi.gmo fr.gmo gl.gmo he.gmo hi.gmo hu.gmo it.gmo ja.gmo ka.gmo ko.gmo lt.gmo lv.gmo mk.gmo nb.gmo nl.gmo pa.gmo pl.gmo pt_BR.gmo ru.gmo sv.gmo tr.gmo uk.gmo vi.gmo zh_CN.gmo zh_HK.gmo zh_TW.gmo
+CATOBJEXT = .gmo
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS = 
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DATADIRNAME = share
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DESKTOP_LAUNCH = no
+ECHO = echo
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = grep -E
+ENABLE_BLUDGEON_FALSE = #
+ENABLE_BLUDGEON_TRUE = 
+ENABLE_DESKTOP_LAUNCH_FALSE = 
+ENABLE_DESKTOP_LAUNCH_TRUE = #
+ENABLE_EPIPHANY_EXTENSION_FALSE = 
+ENABLE_EPIPHANY_EXTENSION_TRUE = #
+ENABLE_EVOLUTION_FALSE = #
+ENABLE_EVOLUTION_TRUE = 
+ENABLE_GALAGO_FALSE = 
+ENABLE_GALAGO_TRUE = #
+ENABLE_GOOGLEDRIVER_FALSE = 
+ENABLE_GOOGLEDRIVER_TRUE = #
+ENABLE_GSF_SHARP_FALSE = #
+ENABLE_GSF_SHARP_TRUE = 
+ENABLE_GTK_DOC_FALSE = 
+ENABLE_GTK_DOC_TRUE = #
+ENABLE_GUI_FALSE = #
+ENABLE_GUI_TRUE = 
+ENABLE_INOTIFY_FALSE = #
+ENABLE_INOTIFY_TRUE = 
+ENABLE_LIBBEAGLE_FALSE = #
+ENABLE_LIBBEAGLE_TRUE = 
+ENABLE_OPEN_WITH_FALSE = #
+ENABLE_OPEN_WITH_TRUE = 
+ENABLE_PYTHON_FALSE = #
+ENABLE_PYTHON_TRUE = 
+ENABLE_THUNDERBIRD_FALSE = #
+ENABLE_THUNDERBIRD_TRUE = 
+ENABLE_WEBSERVICES_FALSE = 
+ENABLE_WEBSERVICES_TRUE = #
+ENABLE_WV1_FALSE = #
+ENABLE_WV1_TRUE = 
+EPIPHANY_DEPENDENCY_CFLAGS = 
+EPIPHANY_DEPENDENCY_LIBS = 
+EPIPHANY_EXTENSIONS_DIR = 
+EPIPHANY_PREFIX = 
+EPIPHANY_REQUIRED = 
+EVO_CFLAGS = -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gnome-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/pango-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/atk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gdk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gtk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/art-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gnome-vfs-api.xml  
+EVO_LIBDIR = /usr/lib/evolution/2.6
+EVO_LIBS = -r:/usr/lib/evolution-sharp/evolution-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gconf-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gconf-sharp-peditors.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gnome-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/pango-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/atk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gdk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gtk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/art-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gnome-vfs-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/glib-sharp.dll -r:/usr/lib/mono/gmime-sharp/gmime-sharp.dll  
+EXEEXT = 
+EXIF_SOVERSION = 12
+F77 = 
+FFLAGS = 
+GAC_PREFIX = /usr
+GALAGO_CFLAGS = 
+GALAGO_LIBS = 
+GETTEXT_PACKAGE = beagle
+GMOFILES =  bg.gmo ca.gmo cs.gmo da.gmo de.gmo el.gmo en_CA.gmo en_GB.gmo es.gmo fi.gmo fr.gmo gl.gmo he.gmo hi.gmo hu.gmo it.gmo ja.gmo ka.gmo ko.gmo lt.gmo lv.gmo mk.gmo nb.gmo nl.gmo pa.gmo pl.gmo pt_BR.gmo ru.gmo sv.gmo tr.gmo uk.gmo vi.gmo zh_CN.gmo zh_HK.gmo zh_TW.gmo
+GMSGFMT = /usr/bin/msgfmt
+GNOME_PREFIX = /usr
+GNOME_VFS_CFLAGS = -pthread -DORBIT2=1 -I/usr/include/gnome-vfs-2.0 -I/usr/lib/gnome-vfs-2.0/include -I/usr/include/bonobo-activation-2.0 -I/usr/include/libbonobo-2.0 -I/usr/include/gconf/2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/orbit-2.0 -I/usr/include/libgnome-2.0  
+GNOME_VFS_LIBS = -pthread -lgnome-2 -lpopt -lgnomevfs-2 -lbonobo-2 -lgconf-2 -lgobject-2.0 -lbonobo-activation -lORBit-2 -lm -lgmodule-2.0 -ldl -lgthread-2.0 -lglib-2.0  
+GSF_SHARP_CFLAGS =  
+GSF_SHARP_LIBS = -r:/usr/lib/mono/gtk-sharp/gsf-sharp.dll  
+GTK_BINARY_VERSION = 2.4.0
+GTK_DOC_USE_LIBTOOL_FALSE = #
+GTK_DOC_USE_LIBTOOL_TRUE = 
+HAS_LIBCHM_FALSE = 
+HAS_LIBCHM_TRUE = #
+HAS_LIBXSS_FALSE = #
+HAS_LIBXSS_TRUE = 
+HTML_DIR = ${datadir}/gtk-doc/html
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_EPIPHANY_EXTENSION_FALSE = #
+INSTALL_EPIPHANY_EXTENSION_TRUE = 
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+INSTOBJEXT = .mo
+INTLLIBS = 
+INTLTOOL_CAVES_RULE = %.caves:     %.caves.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_DESKTOP_RULE = %.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_DIRECTORY_RULE = %.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_EXTRACT = $(top_builddir)/intltool-extract
+INTLTOOL_ICONV = /usr/bin/iconv
+INTLTOOL_KBD_RULE = %.kbd:       %.kbd.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_KEYS_RULE = %.keys:      %.keys.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_MERGE = $(top_builddir)/intltool-merge
+INTLTOOL_MSGFMT = /usr/bin/msgfmt
+INTLTOOL_MSGMERGE = /usr/bin/msgmerge
+INTLTOOL_OAF_RULE = %.oaf:       %.oaf.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< $@
+INTLTOOL_PERL = /usr/bin/perl
+INTLTOOL_PONG_RULE = %.pong:      %.pong.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_PROP_RULE = %.prop:      %.prop.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SCHEMAS_RULE = %.schemas:   %.schemas.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SERVER_RULE = %.server:    %.server.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SERVICE_RULE = %.service: %.service.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SHEET_RULE = %.sheet:     %.sheet.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_SOUNDLIST_RULE = %.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_THEME_RULE = %.theme:     %.theme.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_UI_RULE = %.ui:        %.ui.in        $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_UPDATE = $(top_builddir)/intltool-update
+INTLTOOL_XAM_RULE = %.xam:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+INTLTOOL_XGETTEXT = /usr/bin/xgettext
+INTLTOOL_XML_NOMERGE_RULE = %.xml:       %.xml.in       $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@
+INTLTOOL_XML_RULE = %.xml:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+KDE_CONFIG = /usr/bin/kde-config
+KDE_PREFIX = /usr
+LDFLAGS = 
+LIBBEAGLE_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2  
+LIBBEAGLE_LIBS = -lgobject-2.0 -lglib-2.0 -lxml2 -lz -lm  
+LIBBEAGLE_VERSION_INFO = 0:0:0
+LIBEXIF_API_CHECK_CFLAGS = -I/usr/include/libexif  
+LIBEXIF_API_CHECK_LIBS = -lexif -lm  
+LIBEXIF_CFLAGS = -I/usr/include/libexif  
+LIBEXIF_LIBS = -lexif -lm  
+LIBEXIF_VERSION_CHECK_CFLAGS = -I/usr/include/libexif  
+LIBEXIF_VERSION_CHECK_LIBS = -lexif -lm  
+LIBGLIB_REQUIRED = 
+LIBGTK_REQUIRED = 
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIBTRAYICON_CFLAGS = -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/cairo -I/usr/include/atk-1.0  
+LIBTRAYICON_LIBS = -lgdk-x11-2.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 -latk-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0  
+LIBXML_REQUIRED = 
+LN_S = ln -s
+LTLIBOBJS = 
+MAINT = 
+MAINTAINER_MODE_FALSE = #
+MAINTAINER_MODE_TRUE = 
+MAKEINFO = ${SHELL} /home/kjk38/src/beagle/missing --run makeinfo
+MCS = /usr/bin/mcs
+MKINSTALLDIRS = ./mkinstalldirs
+MONO = /usr/bin/mono
+MONO_CFLAGS = -D_REENTRANT -pthread -I/usr/lib/pkgconfig/../../include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include  
+MONO_LIBS = -Wl,--export-dynamic -pthread -L/usr/lib/pkgconfig/../../lib -lmono -lpthread -lm -lgmodule-2.0 -ldl -lgthread-2.0 -lglib-2.0  
+MSGFMT = /usr/bin/msgfmt
+OBJEXT = o
+OPEN_WITH_CFLAGS = -I:/usr/lib/pkgconfig/../../share/gapi-2.0/pango-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/atk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gdk-api.xml -I:/usr/lib/pkgconfig/../../share/gapi-2.0/gtk-api.xml  
+OPEN_WITH_LIBS = -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/pango-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/atk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gdk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/gtk-sharp.dll -r:/usr/lib/pkgconfig/../../lib/mono/gtk-sharp-2.0/glib-sharp.dll  
+OS_FREEBSD_FALSE = 
+OS_FREEBSD_TRUE = #
+OS_LINUX_FALSE = #
+OS_LINUX_TRUE = 
+PACKAGE = beagle
+PACKAGE_BUGREPORT = 
+PACKAGE_NAME = 
+PACKAGE_STRING = 
+PACKAGE_TARNAME = 
+PACKAGE_VERSION = 
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+POFILES =  bg.po ca.po cs.po da.po de.po el.po en_CA.po en_GB.po es.po fi.po fr.po gl.po he.po hi.po hu.po it.po ja.po ka.po ko.po lt.po lv.po mk.po nb.po nl.po pa.po pl.po pt_BR.po ru.po sv.po tr.po uk.po vi.po zh_CN.po zh_HK.po zh_TW.po
+POSUB = po
+PO_IN_DATADIR_FALSE = 
+PO_IN_DATADIR_TRUE = 
+PYBEAGLE_CFLAGS = -I/usr/include/pygtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include  
+PYBEAGLE_LIBS = -lgobject-2.0 -lglib-2.0  
+PYGTK_CODEGEN = /usr/bin/pygtk-codegen-2.0
+PYGTK_DEFSDIR = /usr/share/pygtk/2.0/defs
+PYTHON = /usr/bin/python
+PYTHON_EXEC_PREFIX = ${exec_prefix}
+PYTHON_INCLUDES = -I/usr/include/python2.4
+PYTHON_PLATFORM = linux2
+PYTHON_PREFIX = ${prefix}
+PYTHON_VERSION = 2.4
+RANLIB = ranlib
+SET_MAKE = 
+SHARPZIPLIB_LIBS = -r:/usr/lib/pkgconfig/../../lib/mono/compat-1.0/ICSharpCode.SharpZipLib.dll
+SHELL = /bin/sh
+SQLITE3_CFLAGS = 
+SQLITE3_LIBS = 
+SQLITE_CFLAGS =  
+SQLITE_LIBS = -lsqlite  
+SQLITE_MAJ_VER = 2
+STRIP = strip
+SYSTEMINFO_GLUE_CFLAGS = -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/cairo  
+SYSTEMINFO_GLUE_LIBS = -lgdk-x11-2.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -lX11  
+SYSTEMINFO_GLUE_X_LIBS =  -lSM -lICE  -L/usr/X11R6/lib -lX11 -lXss 
+UIGLUE_CFLAGS = -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/librsvg-2  
+UIGLUE_LIBS = -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lpangocairo-1.0 -lfontconfig -lXext -lXrender -lXinerama -lXi -lXrandr -lXcursor -lXfixes -lpango-1.0 -lcairo -lX11 -lrsvg-2 -lgdk_pixbuf-2.0 -lm -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0  
+USE_LOCAL_SQLITE_FALSE = #
+USE_LOCAL_SQLITE_TRUE = 
+USE_NLS = yes
+VERSION = 0.2.7
+WSDL = 
+WV1_CFLAGS = -I/usr/include/wv -I/usr/include/libgsf-1 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2  
+WV1_LIBS = -lwv -lgsf-1 -lgobject-2.0 -lxml2 -lglib-2.0 -lpng -lz -lm  
+XGETTEXT = /usr/bin/xgettext
+X_CFLAGS = 
+X_EXTRA_LIBS = 
+X_LIBS =  -L/usr/X11R6/lib
+X_PRE_LIBS =  -lSM -lICE
+ZIP = /usr/bin/zip
+ac_ct_AR = ar
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 = 
+ac_ct_RANLIB = ranlib
+ac_ct_STRIP = strip
+ac_pt_PKG_CONFIG = 
+am__fastdepCC_FALSE = #
+am__fastdepCC_TRUE = 
+am__fastdepCXX_FALSE = #
+am__fastdepCXX_TRUE = 
+am__include = include
+am__leading_dot = .
+am__quote = 
+bindir = ${exec_prefix}/bin
+build = i686-pc-linux-gnu
+build_alias = 
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = pc
+datadir = ${prefix}/share
+exec_prefix = ${prefix}
+host = i686-pc-linux-gnu
+host_alias = 
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = pc
+includedir = ${prefix}/include
+infodir = ${prefix}/info
+install_sh = /home/kjk38/src/beagle/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localstatedir = ${prefix}/var
+mandir = ${prefix}/man
+mkdir_p = mkdir -p -- .
+oldincludedir = /usr/include
+pkgpyexecdir = ${pyexecdir}/beagle
+pkgpythondir = ${pythondir}/beagle
+prefix = /usr
+program_transform_name = s,x,x,
+pyexecdir = ${exec_prefix}/lib/python2.4/site-packages
+pythondir = ${prefix}/lib/python2.4/site-packages
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+sysconfdir = ${prefix}/etc
+target = i686-pc-linux-gnu
+target_alias = 
+target_cpu = i686
+target_os = linux-gnu
+target_vendor = pc
+CSC = mcs -debug
+TARGET = ContactViewer.exe
+WRAPPER = beagle-contactviewer
+CSFLAGS = -target:exe
+CSFILES = \
+	$(srcdir)/ContactViewer.cs	\
+	$(srcdir)/ContactWindow.cs
+
+LOCAL_ASSEMBLIES = \
+	../Util/Util.dll		\
+	../images/Images.dll
+
+ASSEMBLIES = \
+	$(BEAGLE_UI_LIBS)		\
+	$(LOCAL_ASSEMBLIES:%=-r:%)	\
+	-r:Mono.Posix
+
+RESOURCEFILES = \
+	$(srcdir)/contactviewer.glade	\
+	$(srcdir)/menu.xml
+
+
+# Makefile-fu to map /path/filename to -resource:/path/filename,filename
+RESOURCES = $(join $(RESOURCEFILES:%=-resource:%,),$(notdir $(RESOURCEFILES)))
+EXTRA_DIST = \
+	$(CSFILES)		\
+	$(WRAPPER).in		\
+	$(RESOURCEFILES)
+
+CLEANFILES = \
+	$(TARGET)	\
+	$(TARGET).mdb	\
+	$(WRAPPER)	
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  ContactViewer/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  ContactViewer/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+	$(mkdir_p) $(distdir)/$(srcdir)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-local
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+	distclean distclean-generic distclean-libtool distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-data-local install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	uninstall uninstall-am uninstall-info-am uninstall-local
+
+
+$(TARGET): $(CSFILES) $(LOCAL_ASSEMBLIES) $(RESOURCEFILES)
+	$(CSC) -out:$@ $(CSFLAGS) $(CSFILES) $(ASSEMBLIES) $(RESOURCES)
+
+all: $(TARGET) $(WRAPPER)
+
+install-data-local: $(TARGET)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
+	$(INSTALL_DATA) $(TARGET) $(TARGET).mdb $(DESTDIR)$(pkglibdir)
+	sed -e "s|\#installed=1|installed=1|" < $(WRAPPER) > $(WRAPPER).tmp
+	$(INSTALL_SCRIPT) $(WRAPPER).tmp $(DESTDIR)$(bindir)/$(WRAPPER)
+	rm -f $(WRAPPER).tmp
+
+uninstall-local:
+	rm -f $(DESTDIR)$(pkglibdir)/$(TARGET)
+	rm -f $(DESTDIR)$(pkglibdir)/$(TARGET).mdb
+	rm -f $(DESTDIR)$(bindir)/$(WRAPPER)
+
+$(WRAPPER): $(srcdir)/$(WRAPPER).in
+	sed -e "s|\ prefix\@|$(prefix)|g" -e "s|\ pkglibdir\@|$(pkglibdir)|g" -e "s|\ target\@|$(TARGET)|g" -e "s|\ gacprefix\@|$(GAC_PREFIX)|g" < $^ > $@
+	chmod +x $(WRAPPER)
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]