beagle r4660 - in trunk/beagle: . Util beagled conf-data conf-data/config-files
- From: dbera svn gnome org
- To: svn-commits-list gnome org
- Subject: beagle r4660 - in trunk/beagle: . Util beagled conf-data conf-data/config-files
- Date: Sun, 6 Apr 2008 16:51:31 +0100 (BST)
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]