Re: Beagle Thunderbird Patch
- From: Kevin Kubasik <kevin kubasik net>
- To: Pierre Östlund <pierre ostlund gmail com>
- Cc: Dashboard <dashboard-hackers gnome org>
- Subject: Re: Beagle Thunderbird Patch
- Date: Sun, 16 Jul 2006 14:21:44 -0000
-----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"><b>Name</b></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"><b>Internet</b></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"><b>Phones</b></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"><b>Home</b></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"><b>Work</b></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"><b>Custom fields</b></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"><b>Notes</b></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]