Feature freeze break request: small addition to Tomboy note synchronization (FTP support)



Release team,

I would like to apply the patch in bug #463440 [1], which adds support
for FTP as a note synchronization backend to Tomboy.  We always
intended to support at least WebDAV and FTP in addition to arbitrary
file system paths, but somehow we forgot to add this simple support
earlier.

The impact of this change is extremely small.  The configuration UI is
identical to the WebDAV UI, it does not add any dependencies
(curlftpfs is detected at runtime), and the code itself is minimal.
It adds a few small strings.  All in all, a very low-impact change.

We believe it justifies breaking feature freeze because it is more
likely for a user to have access to an FTP server than to a WebDAV
server, and curlftpfs is more widely deployed/packaged than wdfs (the
WebDAV FUSE filesystem).

I apologize for the inconvenience, and for forgetting to add this
support last month when I intended to.  :-)

Thanks,
Sandy
Tomboy Co-Maintainer

[1] http://bugzilla.gnome.org/show_bug.cgi?id=463440
Index: configure.in
===================================================================
--- configure.in	(revision 1385)
+++ configure.in	(working copy)
@@ -207,6 +207,7 @@
 Tomboy/Addins/PrintNotes/Makefile
 Tomboy/Addins/StickyNoteImport/Makefile
 Tomboy/Addins/FileSystemSyncService/Makefile
+Tomboy/Addins/FtpSyncService/Makefile
 Tomboy/Addins/WebDavSyncService/Makefile
 Tomboy/Addins/SshSyncService/Makefile
 test/Makefile
Index: Tomboy.mdp
===================================================================
--- Tomboy.mdp	(revision 1385)
+++ Tomboy.mdp	(working copy)
@@ -181,6 +181,8 @@
     <File name="./Tomboy/Synchronization/TomboySyncClient.cs" subtype="Code" buildaction="Compile" />
     <File name="./Tomboy/Synchronization/FileSystemSyncServer.cs" subtype="Code" buildaction="Compile" />
     <File name="./Tomboy/Synchronization/SyncServiceAddin.cs" subtype="Code" buildaction="Compile" />
+    <File name="./Tomboy/Addins/FtpSyncService" subtype="Directory" buildaction="Compile" />
+    <File name="./Tomboy/Addins/FtpSyncService/FtpSyncServiceAddin.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />

Property changes on: Tomboy/Addins/FtpSyncService
___________________________________________________________________
Name: svn:ignore
   + Makefile
Makefile.in
*.dll
*.dll.mdb


Index: Tomboy/Addins/FtpSyncService/FtpSyncService.addin.xml
===================================================================
--- Tomboy/Addins/FtpSyncService/FtpSyncService.addin.xml	(revision 0)
+++ Tomboy/Addins/FtpSyncService/FtpSyncService.addin.xml	(revision 0)
@@ -0,0 +1,21 @@
+<Addin id="FtpSyncServiceAddin"
+	namespace="Tomboy"
+	name="FTP Sync Service Add-in"
+	author="Tomboy Project"
+	description="Synchronize Tomboy Notes to an FTP URL"
+	category="Synchronization"
+	defaultEnabled="true"
+	version="0.1">
+
+	<Runtime>
+		<Import assembly="FtpSyncService.dll" />
+	</Runtime>
+
+	<Dependencies>
+		<Addin id="Tomboy" version="0.7" />
+	</Dependencies>
+
+	<Extension path="/Tomboy/SyncServiceAddins">
+		<SyncServiceAddin type="Tomboy.Sync.FtpSyncServiceAddin" />
+	</Extension>
+</Addin>
Index: Tomboy/Addins/FtpSyncService/Makefile.am
===================================================================
--- Tomboy/Addins/FtpSyncService/Makefile.am	(revision 0)
+++ Tomboy/Addins/FtpSyncService/Makefile.am	(revision 0)
@@ -0,0 +1,39 @@
+include $(top_srcdir)/Makefile.include
+
+CSFLAGS = 		\
+	-debug 		\
+	-define:DEBUG 	\
+	-target:library
+
+ASSEMBLIES = 					\
+	$(LINK_TOMBOY_EXE)			\
+	$(TOMBOY_LIBS) 				\
+	$(LINK_MONO_ADDINS)			\
+	-r:Mono.Posix
+
+#
+# FTP Sync Service Addin
+#
+
+TARGET = FtpSyncService.dll
+CSFILES = \
+	$(srcdir)/FtpSyncServiceAddin.cs
+RESOURCES = \
+	-resource:$(srcdir)/FtpSyncService.addin.xml
+
+$(TARGET): $(CSFILES) $(top_builddir)/Tomboy/Tomboy.exe
+	$(CSC) -out:$@ $(CSFLAGS) $(ASSEMBLIES) $(CSFILES) $(RESOURCES)
+
+
+addinsdir = $(pkglibdir)/addins
+addins_DATA = 			\
+	$(TARGET)
+
+EXTRA_DIST =            	\
+	$(CSFILES) \
+	$(srcdir)/FtpSyncService.addin.xml
+
+CLEANFILES =				\
+	$(TARGET).mdb \
+	$(TARGET)
+
Index: Tomboy/Addins/FtpSyncService/FtpSyncServiceAddin.cs
===================================================================
--- Tomboy/Addins/FtpSyncService/FtpSyncServiceAddin.cs	(revision 0)
+++ Tomboy/Addins/FtpSyncService/FtpSyncServiceAddin.cs	(revision 0)
@@ -0,0 +1,260 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+
+using Gtk;
+
+using Mono.Unix;
+
+using Tomboy;
+using Gnome.Keyring;
+
+namespace Tomboy.Sync
+{
+	public class FtpSyncServiceAddin : FuseSyncServiceAddin
+	{
+		private Entry urlEntry;
+		private Entry usernameEntry;
+		private Entry passwordEntry;
+		
+		private const string keyring_item_name = "Tomboy sync FTP account";
+		private static Hashtable request_attributes = new Hashtable();
+		
+		static FtpSyncServiceAddin ()
+		{
+			request_attributes ["name"] = keyring_item_name;
+		}
+		
+		/// <summary>
+		/// Creates a Gtk.Widget that's used to configure the service.  This
+		/// will be used in the Synchronization Preferences.  Preferences should
+		/// not automatically be saved by a GConf Property Editor.  Preferences
+		/// should be saved when SaveConfiguration () is called.
+		/// </summary>
+		public override Gtk.Widget CreatePreferencesControl ()
+		{
+			Gtk.Table table = new Gtk.Table (3, 2, false);
+			
+			// Read settings out of gconf
+			string url, username, password;			
+			GetConfigSettings (out url, out username, out password);
+			
+			if (url == null)
+				url = string.Empty;
+			if (username == null)
+				username = string.Empty;
+			if (password == null)
+				password = string.Empty;
+			
+			bool activeSyncService = url != string.Empty || username != string.Empty ||
+				password != string.Empty;
+			
+			Label l = new Label (Catalog.GetString ("URL:"));
+			l.Xalign = 1;
+			l.Show ();
+			table.Attach (l, 0, 1, 0, 1);
+			
+			urlEntry = new Entry ();
+			urlEntry.Text = url;
+			urlEntry.Show ();
+			table.Attach (urlEntry, 1, 2, 0, 1);
+			
+			l = new Label (Catalog.GetString ("Username:"));
+			l.Xalign = 1;
+			l.Show ();
+			table.Attach (l, 0, 1, 1, 2);
+			
+			usernameEntry = new Entry ();
+			usernameEntry.Text = username;
+			usernameEntry.Show ();
+			table.Attach (usernameEntry, 1, 2, 1, 2);
+			
+			l = new Label (Catalog.GetString ("Password:"));
+			l.Xalign = 1;
+			l.Show ();
+			table.Attach (l, 0, 1, 2, 3);
+			
+			passwordEntry = new Entry ();
+			passwordEntry.Text = password;
+			passwordEntry.Visibility = false;
+			passwordEntry.Show ();
+			table.Attach (passwordEntry, 1, 2, 2, 3);
+			
+			table.Sensitive = !activeSyncService;
+			table.Show ();
+			return table;
+		}
+		
+		protected override bool VerifyConfiguration ()
+		{
+			string url, username, password;
+			
+			if (!GetPrefWidgetSettings (out url, out username, out password)) {
+				// TODO: Figure out a way to send the error back to the client
+				Logger.Debug ("One of url, username, or password was empty");
+				return false;
+			}
+			
+			return true;
+		}
+		
+		protected override void SaveConfigurationValues ()
+		{
+			string url, username, password;
+			GetPrefWidgetSettings (out url, out username, out password);
+			
+			SaveConfigSettings (url, username, password);
+		}
+
+		/// <summary>
+		/// Reset the configuration so that IsConfigured will return false.
+		/// </summary>
+		protected override void ResetConfigurationValues ()
+		{
+			SaveConfigSettings (string.Empty, string.Empty, string.Empty);
+			
+			// TODO: Unmount the FUSE mount!
+		}
+		
+		/// <summary>
+		/// Returns whether the addin is configured enough to actually be used.
+		/// </summary>
+		public override bool IsConfigured
+		{
+			get {
+				string url, username, password;				
+				return GetConfigSettings (out url, out username, out password);
+			}
+		}
+		
+		/// <summary>
+		/// The name that will be shown in the preferences to distinguish
+		/// between this and other SyncServiceAddins.
+		/// </summary>
+		public override string Name
+		{
+			get {
+				return Mono.Unix.Catalog.GetString ("FTP (curlftpfs FUSE)");
+			}
+		}
+
+		/// <summary>
+		/// Specifies a unique identifier for this addin.  This will be used to
+		/// set the service in preferences.
+		/// </summary>
+		public override string Id
+		{
+			get {
+				return "ftp";
+			}
+		}
+		
+		protected override string GetFuseMountExeArgs (string mountPath, bool fromStoredValues)
+		{
+			string url, username, password;
+			if (fromStoredValues)
+				GetConfigSettings (out url, out username, out password);
+			else
+				GetPrefWidgetSettings (out url, out username, out password);
+			return string.Format ("-o user={0}:{1} {2} {3}",
+			                      username,
+			                      password,
+			                      url,
+			                      mountPath);
+		}
+
+		protected override string FuseMountExeName {
+			get { return "curlftpfs"; }
+		}
+		
+		#region Private Methods
+		/// <summary>
+		/// Get config settings
+		/// </summary>
+		private bool GetConfigSettings (out string url, out string username, out string password)
+		{
+			// Retrieve configuration from the GNOME Keyring
+			url = null;
+			username = null;
+			password = null;
+			
+			try {
+				foreach (ItemData result in Ring.Find (ItemType.NetworkPassword, request_attributes)) {
+					if (result.Attributes ["name"] as string != keyring_item_name)
+						continue;
+
+					username = ((string) result.Attributes ["user"]).Trim ();
+					url = ((string) result.Attributes ["url"]).Trim ();
+					password = result.Secret.Trim ();
+				}
+			} catch (KeyringException ke) {
+				Logger.Warn ("Getting configuration from the GNOME " +
+				              "keyring failed with the following message: " +
+				              ke.Message);
+				// TODO: If the following fails, retrieve all but password from GConf,
+				//       and prompt user for password. (some password caching would be nice, too)
+				// Retrieve configuration from GConf
+				//url = Preferences.Get ("/apps/tomboy/sync_wdfs_url") as String;
+				//username = Preferences.Get ("/apps/tomboy/sync_wdfs_username") as String;
+				//password = null; // TODO: Prompt user for password
+				//throw;
+			}
+			
+			return !string.IsNullOrEmpty (url)
+					&& !string.IsNullOrEmpty (username)
+					&& !string.IsNullOrEmpty (password);
+		}
+		
+		/// <summary>
+		/// Save config settings
+		/// </summary>
+		private void SaveConfigSettings (string url, string username, string password)
+		{
+			// Save configuration into the GNOME Keyring
+			try {
+				Hashtable update_request_attributes = request_attributes.Clone () as Hashtable;
+				update_request_attributes ["user"] = username;
+				update_request_attributes ["url"] = url;
+
+				ItemData [] items = Ring.Find (ItemType.NetworkPassword, request_attributes);
+				string keyring = Ring.GetDefaultKeyring ();
+
+				if (items.Length == 0)
+					Ring.CreateItem (keyring, ItemType.NetworkPassword, keyring_item_name, 
+					                update_request_attributes, password, true);
+				else {
+					Ring.SetItemInfo (keyring, items [0].ItemID, ItemType.NetworkPassword, 
+					                 keyring_item_name, password);
+					Ring.SetItemAttributes (keyring, items [0].ItemID, update_request_attributes);
+				}
+			} catch (KeyringException ke) {
+				Logger.Warn ("Saving configuration to the GNOME " +
+				              "keyring failed with the following message: " +
+				              ke.Message);
+				// TODO: If the above fails (no keyring daemon), save all but password
+				//       to GConf, and notify user.
+				// Save configuration into GConf
+				//Preferences.Set ("/apps/tomboy/sync_wdfs_url", url ?? string.Empty);
+				//Preferences.Set ("/apps/tomboy/sync_wdfs_username", username ?? string.Empty);
+				//throw;
+			}
+		}
+		
+		/// <summary>
+		/// Get config settings
+		/// </summary>
+		private bool GetPrefWidgetSettings (out string url, out string username, out string password)
+		{
+			url = urlEntry.Text.Trim ();
+			username = usernameEntry.Text.Trim ();
+			password = passwordEntry.Text.Trim ();
+				
+			return !string.IsNullOrEmpty (url)
+					&& !string.IsNullOrEmpty (username)
+					&& !string.IsNullOrEmpty (password);
+		}
+		#endregion // Private Methods
+	}
+}
Index: Tomboy/Addins/Makefile.am
===================================================================
--- Tomboy/Addins/Makefile.am	(revision 1385)
+++ Tomboy/Addins/Makefile.am	(working copy)
@@ -9,6 +9,7 @@
 	PrintNotes			\
 	StickyNoteImport	\
 	FileSystemSyncService	\
+	FtpSyncService		\
 	WebDavSyncService	\
 	SshSyncService
 
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 1385)
+++ po/POTFILES.in	(working copy)
@@ -23,6 +23,8 @@
 Tomboy/Addins/FileSystemSyncService/FileSystemSyncService.addin.xml
 Tomboy/Addins/FixedWidth/FixedWidthMenuItem.cs
 Tomboy/Addins/FixedWidth/FixedWidth.addin.xml
+Tomboy/Addins/FtpSyncService/FtpSyncServiceAddin.cs
+Tomboy/Addins/FtpSyncService/FtpSyncService.addin.xml
 Tomboy/Addins/GalagoPresence/GalagoPresenceNoteAddin.cs
 Tomboy/Addins/GalagoPresence/GalagoPresence.addin.xml
 Tomboy/Addins/NoteOfTheDay/NoteOfTheDay.cs


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