beagle r4660 - in trunk/beagle: . Util beagled conf-data conf-data/config-files



Author: dbera
Date: Sun Apr  6 16:51:30 2008
New Revision: 4660
URL: http://svn.gnome.org/viewvc/beagle?rev=4660&view=rev

Log:
Add a GMail live search backend
* very simple, uses IMAP search protocol
* account information is stored in the config files ($ beagle-config GoogleBackends)
* password can be stored as plaintext in the config-file or in KDE keyring as "Password" in a folder called "beagle" (gnome-keyring not yet supported since we dont want to depend on Gnome or X)
* KdeUtils.cs: Add a mathod to get password from KDE Wallet; this could be useful in the future too when we deal with other protected resources
* These are plugins so GoogleBackends.dll and GoogleBackends.xml can be packaged separately and just dropped in the right places.
* Fully backward compatible till 0.3.0 (except the KDE wallet feature, which needs the current Util.dll)


Added:
   trunk/beagle/beagled/GMailSearchDriver.cs   (contents, props changed)
   trunk/beagle/conf-data/config-files/GoogleBackends.xml
Modified:
   trunk/beagle/Util/KdeUtils.cs
   trunk/beagle/beagled/Makefile.am
   trunk/beagle/conf-data/Makefile.am
   trunk/beagle/configure.in

Modified: trunk/beagle/Util/KdeUtils.cs
==============================================================================
--- trunk/beagle/Util/KdeUtils.cs	(original)
+++ trunk/beagle/Util/KdeUtils.cs	Sun Apr  6 16:51:30 2008
@@ -2,6 +2,7 @@
 // KdeUtils.cs
 //
 // Copyright (C) 2005 Novell, Inc.
+// Copyright (C) 2008 D Bera <dbera web gmail com>
 //
 
 //
@@ -30,10 +31,7 @@
 using System.Text;
 
 namespace Beagle.Util {
-	public class KdeUtils {
-
-		// No instantiation
-		private KdeUtils () { }
+	public static class KdeUtils {
 
 		private static string [] icon_sizes = { "128x128", "64x64", "48x48", "32x32", "22x22", "16x16" };
 		private static string [] kde_locations = { ExternalStringsHack.KdePrefix, Environment.GetEnvironmentVariable ("KDEDIR"), "/opt/kde3", "/usr" };
@@ -110,6 +108,62 @@
 			return null;
 		}
 
+		public static string ReadPasswordKDEWallet (string folder, string username)
+		{
+			if (String.IsNullOrEmpty (folder) || String.IsNullOrEmpty (username))
+				throw new ArgumentException ("folder, username", "cannot be empty");
+
+			// Get name of the local wallet
+			SafeProcess pc = new SafeProcess ();
+			pc.Arguments = new string[] { "dcop", "kded", "kwalletd", "localWallet" };
+			pc.RedirectStandardOutput = true;
+			pc.RedirectStandardError = false;
+			pc.UseLangC = true;
+
+			pc.Start ();
+			string localWallet = null;
+			using (StreamReader pout = new StreamReader (pc.StandardOutput))
+				localWallet = pout.ReadLine ();
+			pc.Close ();
+
+			if (String.IsNullOrEmpty (localWallet) || localWallet == "-1")
+				throw new ArgumentException ("kwalletd", "Unable to reach local KDE wallet");
+
+			// Open local wallet
+			pc = new SafeProcess ();
+			pc.Arguments = new string[] {"dcop", "kded", "kwalletd", "open", localWallet, "K" };
+			pc.RedirectStandardOutput = true;
+			pc.RedirectStandardError = false;
+			pc.UseLangC = true;
+
+			pc.Start ();
+			string wallet_id = null;
+			using (StreamReader pout = new StreamReader (pc.StandardOutput))
+				wallet_id = pout.ReadLine ();
+			pc.Close ();
+
+			if (String.IsNullOrEmpty (wallet_id) || wallet_id == "-1")
+				throw new ArgumentException ("kwalletd", "Unable to open local KDE wallet");
+
+			// Read password from the given folder and for the given username
+			pc = new SafeProcess ();
+			pc.Arguments = new string[] {"dcop", "kded", "kwalletd", "readPassword", wallet_id, folder, username };
+			pc.RedirectStandardOutput = true;
+			pc.RedirectStandardError = false;
+			pc.UseLangC = true;
+
+			pc.Start ();
+			string password = null;
+			using (StreamReader pout = new StreamReader (pc.StandardOutput))
+				password = pout.ReadLine ();
+			pc.Close ();
+
+			if (String.IsNullOrEmpty (password))
+				throw new ArgumentException ("kwalletd", "Unable to read password.");
+
+			return password;
+		}
+
 	}
 }
 

Added: trunk/beagle/beagled/GMailSearchDriver.cs
==============================================================================
--- (empty file)
+++ trunk/beagle/beagled/GMailSearchDriver.cs	Sun Apr  6 16:51:30 2008
@@ -0,0 +1,348 @@
+//
+// GMailSearchDriver.cs
+//
+// A basic gmail email search driver. Search is performed in realtime
+// using imap search functionality.
+//
+// Copyright (C) 2008 D Bera <dbera web gmail com>
+//
+//
+//
+// 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 System.Net.Imap;
+using System.Text;
+
+using Beagle.Util;
+
+[assembly: Beagle.Daemon.IQueryableTypes (typeof (Beagle.Daemon.GoogleBackend.GMailSearchDriver))]
+
+namespace Beagle.Daemon.GoogleBackend {
+
+	[QueryableFlavor (Name="GMailSearch", Domain=QueryDomain.Global, RequireInotify=false)]
+	public class GMailSearchDriver : IQueryable {
+
+		// Bunch of const strings
+		const string GMailServer = "imap.gmail.com";
+		const string AuthMethod = "LOGIN";
+		const int Port = 993;
+		const bool UseSSL = true;
+
+		private string username = null;
+		private string password = null;
+		private string search_folder = null;
+		private bool valid_account = false;
+
+		private ImapClient imap_client = null;
+
+		public GMailSearchDriver ()
+		{
+		}
+
+		public void Start ()
+		{
+			try {
+				GMime.Global.Init ();
+			} catch (Exception e) {
+				Log.Error (e, "Unable to initialize GMime");
+				return;
+			}
+
+			Config config = Conf.Get ("GoogleBackends");
+			ReadConf (config);
+			Conf.WatchForUpdates ();
+			Conf.Subscribe ("GoogleBackends", delegate (Config new_config) {
+								ReadConf (new_config);
+							    });
+		}
+
+		private void ReadConf (Config config)
+		{
+			if (config == null || config.Name != "GoogleBackends")
+				return;
+
+			bool enabled = config.GetOption ("GMailSearchEnabled", false);
+			username = config.GetOption ("GMailUsername", null);
+			search_folder = config.GetOption ("GMailSearchFolder", null);
+
+			string password_source = config.GetOption ("GMailPasswordSource", "conf-data");
+			password_source = password_source.ToLower ();
+			switch (password_source) {
+			case "conf-file":
+				password = config.GetOption ("GMailPassword", null);
+				break;
+
+			case "gnome-keyring":
+				Log.Error ("GMailPasswordSource: gnome-keyring is not supported yet");
+				break;
+
+			case "kdewallet":
+				try {
+					password = KdeUtils.ReadPasswordKDEWallet ("beagle", username);
+				} catch (Exception e) {
+					Log.Error (e, "Error in reading password in KDE wallet");
+				}
+				break;
+
+			default:
+				Log.Error ("GMailPasswordSource should be one of 'kdewallet,gnome-keyring,conf-file");
+				break;
+
+			}
+
+			valid_account = (enabled &&
+				! String.IsNullOrEmpty (username) &&
+				! String.IsNullOrEmpty (password) &&
+				! String.IsNullOrEmpty (search_folder));
+
+			if (! valid_account)
+				Log.Warn ("GMail account information not set. Search is disabled.");
+			else
+				Log.Debug ("GMail account information successfully read.");
+		}
+
+		public bool AcceptQuery (Query query)
+		{
+			if (! valid_account)
+				return false;
+
+			bool has_text = false;
+			foreach (QueryPart qp in query.Parts)
+				if (qp is QueryPart_Text)
+					has_text = true;
+
+			if (! has_text) {
+				Log.Error ("GMailSearchDriver can only search for text and does not support 'OR', 'NOT' queries.");
+				return false;
+			}
+			    
+			return Connect ();
+		}
+
+		public void DoQuery (Query query,
+				     IQueryResult result,
+				     IQueryableChangeData changeData)
+		{
+			// Program semantics guarantee that imap_client != null
+
+			StringBuilder sb = new StringBuilder ();
+			foreach (QueryPart qp in query.Parts) {
+				if (qp is QueryPart_Text) {
+					if (sb.Length > 0)
+						sb.Append (' ');
+					sb.Append (((QueryPart_Text) qp).Text);
+				}
+			}
+
+			// IMAP SEARCH protocol
+			sb.Insert (0, "TEXT \"");
+			sb.Append ("\"");
+			string imap_query = sb.ToString ();
+
+			try {
+				DoGMailQuery (sb.ToString (), query.MaxHits, result);
+			} catch {
+				Log.Error ("GMailSearchDriver IMAP error :{0}", imap_client.LastError);
+			} finally {
+				imap_client.Disconnect ();
+			}
+		}
+
+		public int DoCountMatchQuery (Query query)
+		{
+			// FIXME: Implement this
+			return -1;
+		}
+
+		public ISnippetReader GetSnippet (string[] query_terms, Hit hit, bool full_text, int context_length, int snippet_length)
+		{
+			return null;
+		}
+
+		public QueryableStatus GetQueryableStatus ()
+		{
+			QueryableStatus status = new QueryableStatus ();
+			status.Name = "GMailSearch";
+			// FIXME: Get number of emails from GMail
+			return status;
+		}
+
+		///////////////////////////////////////////////////
+
+		private bool Connect ()
+		{
+			if (imap_client != null)
+				imap_client.Disconnect ();
+			imap_client = null;
+			bool success = false;
+
+			try {
+				imap_client = new ImapClient ();
+				imap_client.AuthMethod = AuthMethod;
+				imap_client.Port = Port;
+				imap_client.Ssl = UseSSL;
+				imap_client.Connect (GMailServer);
+
+				success = imap_client.Login (username, password);
+
+				if (! success) {
+					Log.Error ("IMAP connection unsuccessful: {0}", imap_client.LastError);
+				} else {
+					Mailbox search_mailbox = imap_client.SelectMailbox (search_folder);
+					success = (search_mailbox != null);
+					if (! success)
+						Log.Error ("Selection folder unsuccessful: {0}", imap_client.LastError);
+				}
+			} catch (Exception e) {
+				Log.Error (e, "GMailSearchDriver: Error in connecting to {0} with username {1}", username, GMailServer);
+			}
+
+			if (! success && imap_client != null)
+				imap_client.Disconnect ();
+
+			return success;
+		}
+
+		private void DoGMailQuery (string query, int maxhits, IQueryResult result)
+		{
+			Log.Debug ("GMailSearchDriver: Searching for [{0}]", query);
+			MessageSet results = imap_client.Search (query, false);
+			if (results == null) {
+				return;
+			}
+
+			Log.Debug ("Recvd {0} messages", results.Messages.Count);
+
+			// Get the messages in reverse order; latest first
+			ArrayList matched_ids = new ArrayList (results.Messages);
+			matched_ids.Reverse ();
+
+			const int MAX_QUEUED_HITS = 25;
+			int left = Math.Min (maxhits, matched_ids.Count);
+			ArrayList result_batch = new ArrayList (MAX_QUEUED_HITS);
+
+			MailCollection emails;
+			GMime.StreamMem stream;
+			GMime.Parser parser;
+			GMime.Message message;
+			Hit hit;
+
+			foreach (string id in matched_ids) {
+				if (left -- == 0)
+					break;
+				Log.Debug ("Fetching headers for message id {0}", id);
+
+				emails = imap_client.FetchMessages (id, id, false,true,false);
+				if (emails == null || emails.Count == 0) {
+					Log.Error ("IMAP error: {0}", imap_client.LastError);
+					continue;
+				}
+
+				foreach (Mail m in emails) {
+					hit = null;
+
+					using (stream = new GMime.StreamMem (m.Header))
+					using (parser = new GMime.Parser (stream))
+					using (message = parser.ConstructMessage ())
+						hit = MessageToHit (message);
+
+					if (hit == null) {
+						Log.Error ("Bad IMAP email {0}: no msg-id", id);
+						continue;
+					} else {
+						result_batch.Add (hit);
+					}
+				}
+
+				if (result_batch.Count >= MAX_QUEUED_HITS) {
+					result.Add (result_batch);
+					result_batch.Clear ();
+				}
+			}
+
+			result.Add (result_batch, matched_ids.Count);
+		}
+
+		// Copied from FilterMail.cs:DoPullProperties
+		private Hit MessageToHit (GMime.Message message)
+		{
+			string msgid = message.GetHeader ("Message-Id");
+			if (msgid == null)
+				return null;
+
+			msgid = GMime.Utils.DecodeMessageId (msgid);
+			Hit hit = new Hit ();
+			hit.Uri = new Uri (String.Format ("http://mail.google.com/mail/#search/{0}";, msgid));
+                        hit.AddProperty (Property.NewUnsearched ("beagle:HitType", "MailMessage"));
+                        hit.AddProperty (Property.NewUnsearched ("beagle:MimeType", "text/html"));
+                        hit.AddProperty (Property.NewUnsearched ("beagle:Source", "GMailSearch"));
+			hit.Score = 1.0;
+
+			hit.AddProperty (Property.NewUnsearched ("fixme:msgid", msgid));
+
+			string subject = GMime.Utils.HeaderDecodePhrase (message.Subject);
+			hit.AddProperty (Property.New ("dc:title", subject));
+			hit.Timestamp = message.Date.ToUniversalTime ();
+
+			GMime.InternetAddressList addrs;
+			addrs = message.GetRecipients (GMime.Message.RecipientType.To);
+			foreach (GMime.InternetAddress ia in addrs) {
+				hit.AddProperty (Property.NewUnsearched ("fixme:to", ia.ToString (false)));
+				if (ia.AddressType != GMime.InternetAddressType.Group)
+					hit.AddProperty (Property.New ("fixme:to_address", ia.Addr));
+
+				hit.AddProperty (Property.New ("fixme:to_name", ia.Name));
+			}
+			addrs.Dispose ();
+
+			addrs = message.GetRecipients (GMime.Message.RecipientType.Cc);
+			foreach (GMime.InternetAddress ia in addrs) {
+				hit.AddProperty (Property.NewUnsearched ("fixme:cc", ia.ToString (false)));
+				if (ia.AddressType != GMime.InternetAddressType.Group)
+					hit.AddProperty (Property.New ("fixme:cc_address", ia.Addr));
+
+				hit.AddProperty (Property.New ("fixme:cc_name", ia.Name));
+			}
+			addrs.Dispose ();
+
+			addrs = GMime.InternetAddressList.ParseString (GMime.Utils.HeaderDecodePhrase (message.Sender));
+			foreach (GMime.InternetAddress ia in addrs) {
+				hit.AddProperty (Property.NewUnsearched ("fixme:from", ia.ToString (false)));
+				if (ia.AddressType != GMime.InternetAddressType.Group)
+					hit.AddProperty (Property.New ("fixme:from_address", ia.Addr));
+
+				hit.AddProperty (Property.New ("fixme:from_name", ia.Name));
+			}
+			addrs.Dispose ();
+
+			foreach (GMime.References refs in message.References)
+				hit.AddProperty (Property.NewUnsearched ("fixme:reference", refs.Msgid));
+
+			string list_id = message.GetHeader ("List-Id");
+			if (list_id != null)
+				hit.AddProperty (Property.New ("fixme:mlist", GMime.Utils.HeaderDecodePhrase (list_id)));
+
+			return hit;
+		}
+	}
+}
+

Modified: trunk/beagle/beagled/Makefile.am
==============================================================================
--- trunk/beagle/beagled/Makefile.am	(original)
+++ trunk/beagle/beagled/Makefile.am	Sun Apr  6 16:51:30 2008
@@ -399,6 +399,40 @@
 
 ############################################################
 
+### GMail and other Google backends
+
+XEMAIL_DIR = $(srcdir)/xemail-net/src
+
+XEMAIL_CSFILES = 				\
+	$(XEMAIL_DIR)/Attachment.cs		\
+	$(XEMAIL_DIR)/AttachmentCollections.cs	\
+	$(XEMAIL_DIR)/Flag.cs			\
+	$(XEMAIL_DIR)/FlagCollection.cs		\
+	$(XEMAIL_DIR)/HMACMD5.cs		\
+	$(XEMAIL_DIR)/ImapClient.cs		\
+	$(XEMAIL_DIR)/Mail.cs			\
+	$(XEMAIL_DIR)/MailCollection.cs		\
+	$(XEMAIL_DIR)/Mailbox.cs		\
+	$(XEMAIL_DIR)/MailboxCollection.cs	\
+	$(XEMAIL_DIR)/MessageSet.cs		\
+	$(XEMAIL_DIR)/Namespace.cs		\
+	$(XEMAIL_DIR)/Quota.cs
+
+XEMAIL_ASSEMBLIES = -r:System.Web -r:Mono.Security
+
+XEMAIL_CSFLAGS = -d:MONO
+
+GOOGLE_BACKEND_TARGET = GoogleBackends.dll
+
+GOOGLE_BACKEND_LOCAL_CSFILES = GMailSearchDriver.cs
+
+GOOGLE_BACKEND_CSFILES = $(GOOGLE_BACKEND_LOCAL_CSFILES) $(XEMAIL_CSFILES)
+
+$(GOOGLE_BACKEND_TARGET): $(GOOGLE_BACKEND_CSFILES)  $(BACKEND_LOCAL_ASSEMBLIES)
+	$(CSC) -out:$@ $(GOOGLE_BACKEND_CSFILES) $(XEMAIL_CSFLAGS) $(XEMAIL_ASSEMBLIES) $(BACKEND_CSFLAGS) $(BACKEND_ASSEMBLIES) $(BEAGLED_LIBS)
+
+############################################################
+
 DAEMON_WRAPPER = beagled
 DAEMON_WRAPPER_IN = beagled.in
 DAEMON_TARGET = BeagleDaemon.exe
@@ -704,6 +738,10 @@
 	$(EVO_DLL_TARGET)
 endif
 
+if ENABLE_GOOGLEBACKENDS
+ALL_TARGETS += $(GOOGLE_BACKEND_TARGET)
+endif
+
 man_MANS = 				\
 	beagled.1			\
 	beagle-build-index.8		\
@@ -761,6 +799,9 @@
 	$(INSTALL_DATA) $(THUNDERBIRD_TARGET)                 $(DESTDIR)$(BACKENDDIR)
 	$(INSTALL_DATA) $(THUNDERBIRD_TARGET).mdb             $(DESTDIR)$(BACKENDDIR)
 endif
+if ENABLE_GOOGLEBACKENDS
+	$(INSTALL_DATA) $(GOOGLE_BACKEND_TARGET) $(GOOGLE_BACKEND_TARGET).mdb $(DESTDIR)$(BACKENDDIR)
+endif
 
 uninstall-local:
 if ENABLE_THUNDERBIRD
@@ -771,6 +812,10 @@
 	rm -f $(DESTDIR)$(BACKENDDIR)/$(EVO_DLL_TARGET)
 	rm -f $(DESTDIR)$(BACKENDDIR)/$(EVO_DLL_TARGET).mdb
 endif
+if ENABLE_GOOGLEBACKENDS
+	rm -f $(DESTDIR)$(BACKENDDIR)/$(GOOGLE_BACKEND_TARGET)
+	rm -f $(DESTDIR)$(BACKENDDIR)/$(GOOGLE_BACKEND_TARGET).mdb
+endif
 
 	@for i in $(BIN_WRAPPERS); do				\
 		echo "rm -f $(DESTDIR)$(bindir)/$$i";		\
@@ -829,6 +874,7 @@
 	$(DAEMON_CSFILES)			\
 	$(EVO_DLL_CSFILES)			\
 	$(THUNDERBIRD_CSFILES)			\
+	$(GOOGLE_BACKEND_CSFILES)		\
 	$(EXTRACT_CONTENT_CSFILES)		\
 	$(DUMP_INDEX_CSFILES)			\
 	$(SNIPPET_TEST_CSFILES)			\
@@ -870,4 +916,6 @@
 	$(BUILD_INDEX_WRAPPER)			\
 	$(THUNDERBIRD_TARGET)			\
 	$(THUNDERBIRD_TARGET).mdb		\
+	$(GOOGLE_BACKEND_TARGET)		\
+	$(GOOGLE_BACKEND_TARGET).mdb		\
 	$(WEBINTERFACE_INDEX_XML)

Modified: trunk/beagle/conf-data/Makefile.am
==============================================================================
--- trunk/beagle/conf-data/Makefile.am	(original)
+++ trunk/beagle/conf-data/Makefile.am	Sun Apr  6 16:51:30 2008
@@ -15,6 +15,10 @@
 	$(srcdir)/config-files/FilesQueryable.xml	\
 	$(srcdir)/config-files/Networking.xml
 
+if ENABLE_GOOGLEBACKENDS
+GLOBAL_CONFIG_FILES += $(srcdir)/config-files/GoogleBackends.xml
+endif
+
 global_config_filesdir = $(sysconfdir)/beagle/config-files
 global_config_files_DATA = $(GLOBAL_CONFIG_FILES)
 

Added: trunk/beagle/conf-data/config-files/GoogleBackends.xml
==============================================================================
--- (empty file)
+++ trunk/beagle/conf-data/config-files/GoogleBackends.xml	Sun Apr  6 16:51:30 2008
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-16"?>
+<!-- Distributions and packagers, DO NOT remove or add any BoolOption, StringOption or ListOption.
+     Also do not change the Name, Description, Params and Separator attributes.
+ -->
+<BeagleConf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns:xsd="http://www.w3.org/2001/XMLSchema"; Name="GoogleBackends">
+    <BoolOption Name="GMailSearchEnabled" Description="Enable live GMail search">false</BoolOption>
+    <StringOption Name="GMailUsername" Description="Username for GMail. Generally the full email address."></StringOption>
+    <StringOption Name="GMailPasswordSource" Description="Password obtained from:kdewallet/gnome-keyring/conf-file">conf-file</StringOption>
+    <StringOption Name="GMailPassword" Description="Password for GMail stored in plaintext. WARNING!"></StringOption>
+    <StringOption Name="GMailSearchFolder" Description="Search this folder for GMail live search.">INBOX</StringOption>
+</BeagleConf>
+

Modified: trunk/beagle/configure.in
==============================================================================
--- trunk/beagle/configure.in	(original)
+++ trunk/beagle/configure.in	Sun Apr  6 16:51:30 2008
@@ -188,6 +188,24 @@
         enable_tbird=yes)
 AM_CONDITIONAL(ENABLE_THUNDERBIRD, test "x$enable_tbird" = "xyes")
 
+dnl ----------------------------------------------
+
+AC_ARG_ENABLE([googlebackends],
+        AC_HELP_STRING([--disable-googlebackends], [Disable GMail and other Google backends (default yes)]),
+        enable_google=$enableval,
+        enable_google=no)
+AM_CONDITIONAL(ENABLE_GOOGLEBACKENDS, test "x$enable_google" = "xyes")
+
+if test "x$enable_google" = "xyes"; then
+  i="System.Security"
+  AC_MSG_CHECKING([for $i.dll (needed by Google backends)])
+  if test ! -e `$PKG_CONFIG --variable=prefix mono`/lib/mono/2.0/$i.dll; then
+    AC_MSG_ERROR([missing required mono DLL: $i.dll])
+  else
+    AC_MSG_RESULT([found])
+  fi
+fi
+
 dnl -------------------------------------------------------
 
 AC_ARG_ENABLE([gui],
@@ -672,6 +690,7 @@
 	Firefox Extension?	  yes
 	Epiphany Extension?	  ${enable_epiphany_extension}
 	Thunderbird Extension? 	  ${enable_tbird}
+	Google Backends?          ${enable_google}
 
 	Local taglib-sharp?       ${enable_internal_taglib}
 



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