[f-spot] Add SafeUri to replace broken System.Uri.



commit 03e0774fae0e49ba5a1be0d463b655577a0b5fdb
Author: Ruben Vermeersch <ruben savanne be>
Date:   Wed May 26 00:23:35 2010 +0200

    Add SafeUri to replace broken System.Uri.
    
    System.Uri is broken because it cannot represent URIs like
    gphoto2://[usb:002,014]/, which is a valid GVFS URI.

 configure.ac                                       |    1 +
 extensions/Exporters/FolderExport/FolderExport.cs  |    4 +-
 .../Exporters/PicasaWebExport/PicasaWebExport.cs   |    3 +-
 extensions/Exporters/TabbloExport/TabbloExport.cs  |    2 +-
 extensions/Services/DBusService/DBusProxy.cs       |    3 +-
 .../ChangePhotoPath/ChangePhotoPathController.cs   |    4 +-
 extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs  |    6 +-
 extensions/Tools/MergeDb/MergeDb.cs                |    9 +-
 extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs        |    3 +-
 src/.gitignore                                     |    1 +
 src/CameraFileSelectionDialog.cs                   |   11 +-
 src/Core/App.cs                                    |   13 +-
 src/Core/IBrowsableItemExtensions.cs               |    5 +-
 src/Core/IBrowsableItemVersion.cs                  |    8 +-
 src/Core/Photo.cs                                  |   73 ++++----
 src/Core/PhotoVersion.cs                           |   62 ++----
 src/Core/SafeUri.cs                                |  208 ++++++++++++++++++++
 src/Core/SafeUriExtensions.cs                      |   31 +++
 src/FSpot.Core.dll.config.in                       |    4 +
 src/FileBrowsableItem.cs                           |   13 +-
 src/FileImportBackend.cs                           |   40 ++--
 src/Filters/ChmodFilter.cs                         |    2 +-
 src/Filters/FilterRequest.cs                       |   25 +--
 src/Filters/OrientationFilter.cs                   |    2 +-
 src/Filters/ResizeFilter.cs                        |    2 +-
 src/Filters/SharpFilter.cs                         |    2 +-
 src/Filters/UniqueNameFilter.cs                    |   10 +-
 src/FolderQueryWidget.cs                           |    7 +-
 src/ImageLoaderThread.cs                           |   19 +-
 src/Imaging/Ciff.cs                                |    3 +-
 src/Imaging/DCRawFile.cs                           |    5 +-
 src/Imaging/ImageFile.cs                           |   25 ++-
 src/Imaging/JpegFile.cs                            |    3 +-
 src/Imaging/MrwFile.cs                             |    3 +-
 src/Imaging/PngFile.cs                             |    3 +-
 src/Imaging/PnmFile.cs                             |    3 +-
 src/Imaging/RafFile.cs                             |    3 +-
 src/Imaging/SvgFile.cs                             |    3 +-
 src/Imaging/Tiff.cs                                |    9 +-
 src/Imaging/X3fFile.cs                             |    3 +-
 src/ImportCommand.cs                               |   33 ++--
 src/Loaders/GdkImageLoader.cs                      |    3 +-
 src/Loaders/IImageLoader.cs                        |    3 +-
 src/Loaders/ImageLoader.cs                         |    3 +-
 src/MainWindow.cs                                  |    5 +-
 src/Makefile.am                                    |    9 +-
 src/PhotoImageView.cs                              |    3 +-
 src/PhotoLoader.cs                                 |    3 +-
 src/PhotoStore.cs                                  |   69 ++++---
 src/PixbufCache.cs                                 |   23 ++-
 src/PixbufUtils.cs                                 |   13 +-
 src/Platform/Gnome/ThumbnailFactory.cs             |   29 ++--
 src/Platform/Null/ThumbnailFactory.cs              |   23 ++-
 src/Query/FolderSet.cs                             |   11 +-
 src/QueryWidget.cs                                 |    4 +-
 src/RotateCommand.cs                               |    3 +-
 src/SendEmail.cs                                   |    3 +-
 src/SingleView.cs                                  |   17 +-
 src/TagSelectionWidget.cs                          |    2 +-
 src/ThumbnailCache.cs                              |    9 +-
 src/ThumbnailGenerator.cs                          |   21 +--
 src/UI.Dialog/EditTagIconDialog.cs                 |    3 +-
 src/UriCollection.cs                               |   25 ++--
 src/Util.cs                                        |   33 ++--
 src/Utils/PixbufUtils.cs                           |   25 ---
 src/Utils/RecursiveFileEnumerator.cs               |    8 +-
 src/Widgets/Filmstrip.cs                           |    9 +-
 src/Widgets/FolderTreeView.cs                      |    3 +-
 src/Widgets/IconView.cs                            |    4 +-
 src/Widgets/ImageInfo.cs                           |    3 +-
 src/XmpTagsImporter.cs                             |    3 +-
 71 files changed, 640 insertions(+), 401 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index abe4dee..f81715e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -370,6 +370,7 @@ src/Core/Defines.cs
 src/AssemblyInfo.cs
 src/f-spot.exe.config
 src/Cms.dll.config
+src/FSpot.Core.dll.config
 src/FSpot.Widgets.dll.config
 src/Makefile
 extensions/Makefile
diff --git a/extensions/Exporters/FolderExport/FolderExport.cs b/extensions/Exporters/FolderExport/FolderExport.cs
index a965e21..97ec4b6 100644
--- a/extensions/Exporters/FolderExport/FolderExport.cs
+++ b/extensions/Exporters/FolderExport/FolderExport.cs
@@ -24,6 +24,8 @@ using System.IO;
 using System.Runtime.InteropServices;
 using System.Collections;
 
+using Hyena;
+
 using Mono.Unix;
 
 using ICSharpCode.SharpZipLib.Checksums;
@@ -210,7 +212,7 @@ namespace FSpotFolderExport {
 				else if (rotate)
 					filter_set.Add (new OrientationFilter ());
 				filter_set.Add (new ChmodFilter ());
-				filter_set.Add (new UniqueNameFilter (gallery_path));
+				filter_set.Add (new UniqueNameFilter (new SafeUri (gallery_path)));
 
 				for (int photo_index = 0; photo_index < selection.Count; photo_index++)
 				{
diff --git a/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs b/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs
index ecd8842..e1359fe 100644
--- a/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs
+++ b/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs
@@ -15,6 +15,7 @@ using System.Collections;
 using System.Collections.Specialized;
 using System.Web;
 using Mono.Unix;
+using Hyena;
 
 using FSpot;
 using FSpot.Filters;
@@ -285,7 +286,7 @@ namespace FSpotGoogleExport {
 
 			if (show_captcha) {
 				try {
-					using  (ImageFile img = ImageFile.Create(new Uri(captcha_exception.CaptchaUrl))) {
+					using  (ImageFile img = ImageFile.Create(new SafeUri(captcha_exception.CaptchaUrl))) {
 						captcha_image.Pixbuf = img.Load();
 						token = captcha_exception.Token;
 					}
diff --git a/extensions/Exporters/TabbloExport/TabbloExport.cs b/extensions/Exporters/TabbloExport/TabbloExport.cs
index 3c14deb..8017c19 100644
--- a/extensions/Exporters/TabbloExport/TabbloExport.cs
+++ b/extensions/Exporters/TabbloExport/TabbloExport.cs
@@ -399,7 +399,7 @@ namespace FSpotTabbloExport {
 							QueryInfo ("standard::content-type", GLib.FileQueryInfoFlags.None, null).ContentType;
 
 				pictures [i] = new Picture (items [i].Name,
-						items [i].DefaultVersion.Uri,
+						new Uri (items [i].DefaultVersion.Uri.AbsoluteUri),
 						mime_type,
 						model.Privacy);
 			}
diff --git a/extensions/Services/DBusService/DBusProxy.cs b/extensions/Services/DBusService/DBusProxy.cs
index aa8e586..6604414 100644
--- a/extensions/Services/DBusService/DBusProxy.cs
+++ b/extensions/Services/DBusService/DBusProxy.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Text;
 
+using Hyena;
 using FSpot;
 using FSpot.Query;
 using FSpot.Utils;
@@ -419,7 +420,7 @@ namespace DBusService {
 				string new_path = path;
 
 				if (copy)
-					new_path = FileImportBackend.ChooseLocation (UriUtils.PathToFileUri (path)).AbsolutePath;
+					new_path = FileImportBackend.ChooseLocation (new SafeUri (path)).AbsolutePath;
 
 				if (new_path != path)
 					System.IO.File.Copy (path, new_path);
diff --git a/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs b/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs
index 87a9268..811a32d 100644
--- a/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs
+++ b/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs
@@ -14,6 +14,7 @@ using System;
 using System.IO;
 using System.Collections;
 using System.Collections.Specialized;
+using Hyena;
 
 /*
 	Need to
@@ -182,7 +183,8 @@ namespace ChangePhotoPath
 			if (photo == null)
 				photo = photo_store.Get ( (uint) photo_id_array[index]) as Photo;
 			PhotoVersion version = photo.GetVersion ( (uint) version_id_array[index]) as PhotoVersion;
-			version.Uri = new System.Uri ( path );
+			version.BaseUri = new SafeUri ( path ).GetBaseUri ();
+			version.Filename = new SafeUri ( path ).GetFilename ();
 			photo.Changes.UriChanged = true;
 			photo.Changes.ChangeVersion ( (uint) version_id_array[index] );
 		}
diff --git a/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs b/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs
index a8c2bcf..6e67a0c 100644
--- a/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs
+++ b/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs
@@ -12,6 +12,7 @@ using System.IO;
 
 using Mono.Unix;
 
+using Hyena;
 using FSpot;
 using FSpot.Utils;
 using FSpot.Extensions;
@@ -148,7 +149,7 @@ namespace DevelopInUFRawExtension
 				File.Move (Path.ChangeExtension (developed.LocalPath, ".ufraw"), Path.ChangeExtension (raw.Uri.LocalPath, ".ufraw"));
 			}
 
-			p.DefaultVersionId = p.AddVersion (developed, name, true);
+			p.DefaultVersionId = p.AddVersion (new SafeUri (developed).GetBaseUri (),new SafeUri (developed).GetFilename (), name, true);
 			p.Changes.DataChanged = true;
 			App.Instance.Database.Photos.Commit (p);
 		}
@@ -176,8 +177,7 @@ namespace DevelopInUFRawExtension
 
 		private static string DirectoryPath (Photo p)
 		{
-			System.Uri uri = p.VersionUri (Photo.OriginalVersionId);
-			return uri.Scheme + "://" + uri.Host + System.IO.Path.GetDirectoryName (uri.AbsolutePath);
+			return p.VersionUri (Photo.OriginalVersionId).GetBaseUri ();
 		}
 
 		void LoadPreference (string key)
diff --git a/extensions/Tools/MergeDb/MergeDb.cs b/extensions/Tools/MergeDb/MergeDb.cs
index 4651b46..afc09bb 100644
--- a/extensions/Tools/MergeDb/MergeDb.cs
+++ b/extensions/Tools/MergeDb/MergeDb.cs
@@ -19,6 +19,7 @@ using FSpot.Utils;
 using FSpot.Query;
 using FSpot.UI.Dialog;
 using Mono.Unix;
+using Hyena;
 
 namespace MergeDbExtension
 {
@@ -232,17 +233,17 @@ namespace MergeDbExtension
 			Photo newp;
 
 			if (copy)
-				destination = FileImportBackend.ChooseLocation (UriUtils.PathToFileUri (photo_path)).AbsolutePath;
+				destination = FileImportBackend.ChooseLocation (new SafeUri (photo_path)).AbsolutePath;
 			else
 				destination = photo_path;
 
 			// Don't copy if we are already home
 			if (photo_path == destination)
-				newp = to_store.Create (UriUtils.PathToFileUri (destination), roll_map [photo.RollId]);
+				newp = to_store.Create (new SafeUri (destination), roll_map [photo.RollId]);
 			else {
 				System.IO.File.Copy (photo_path, destination);
 
-				newp = to_store.Create (UriUtils.PathToFileUri (destination), UriUtils.PathToFileUri (photo_path), roll_map [photo.RollId]);
+				newp = to_store.Create (new SafeUri (destination), new SafeUri (photo_path), roll_map [photo.RollId]);
 				try {
 					File.SetAttributes (destination, File.GetAttributes (destination) & ~FileAttributes.ReadOnly);
 					DateTime create = File.GetCreationTime (photo_path);
@@ -265,7 +266,7 @@ namespace MergeDbExtension
 			foreach (uint version_id in photo.VersionIds)
 				if (version_id != Photo.OriginalVersionId) {
 					PhotoVersion version = photo.GetVersion (version_id) as PhotoVersion;
-					uint newv = newp.AddVersion (version.Uri, version.Name, version.IsProtected);
+					uint newv = newp.AddVersion (version.BaseUri, version.Filename, version.Name, version.IsProtected);
 					if (version_id == photo.DefaultVersionId)
 						newp.DefaultVersionId = newv;
 				}
diff --git a/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs b/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs
index 4077fb1..6d12009 100644
--- a/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs
+++ b/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs
@@ -74,8 +74,7 @@ namespace RawPlusJpegExtension
 
 		private static string DirectoryPath (Photo p)
 		{
-			System.Uri uri = p.VersionUri (Photo.OriginalVersionId);
-			return uri.Scheme + "://" + uri.Host + System.IO.Path.GetDirectoryName (uri.AbsolutePath);
+			return p.VersionUri (Photo.OriginalVersionId).GetBaseUri ();
 		}
 
 		class MergeRequest
diff --git a/src/.gitignore b/src/.gitignore
index f4fcdfe..35235b4 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -5,6 +5,7 @@
 /Core/Defines.cs
 /FSpot.Core.dll
 /FSpot.Core.dll.mdb
+/FSpot.Core.dll.config
 /FSpot.JobScheduler.dll
 /FSpot.JobScheduler.dll.mdb
 /FSpot.Query.dll
diff --git a/src/CameraFileSelectionDialog.cs b/src/CameraFileSelectionDialog.cs
index d1c3387..894577f 100644
--- a/src/CameraFileSelectionDialog.cs
+++ b/src/CameraFileSelectionDialog.cs
@@ -18,6 +18,7 @@ using GPhoto2;
 using Mono.Unix;
 using FSpot.Utils;
 using FSpot.UI.Dialog;
+using Hyena;
 
 namespace FSpot {
 	public class CameraFileSelectionDialog : GladeDialog
@@ -42,7 +43,7 @@ namespace FSpot {
 		ThreadProgressDialog progress_dialog;
 		System.Collections.ArrayList index_list;
 		
-		Uri[] saved_files;
+		SafeUri[] saved_files;
 		Tag[] selected_tags;
 		
 		System.Threading.Thread command_thread;
@@ -214,7 +215,7 @@ namespace FSpot {
 		private void Download ()
 		{
 			lock (camera) {
-				List<Uri> saved = new List<Uri> ();
+				List<SafeUri> saved = new List<SafeUri> ();
 					
 				for (int i = 0; i < index_list.Count; i++) {
 					try {
@@ -226,7 +227,7 @@ namespace FSpot {
 						SaveResult result = SaveFile ((int)(index_list [i]));
 
 						if (!result.IsDuplicate)
-						 	saved.Add (UriUtils.PathToFileUri(result.Path));
+							saved.Add (new SafeUri(result.Path));
 
 						progress_dialog.Fraction = (i + 1)/(double)index_list.Count;
 					}
@@ -272,12 +273,12 @@ namespace FSpot {
 			
 			camera.SaveFile (index, path);
 
-			if (duplicate_check.Active && db.Photos.CheckForDuplicate (FSpot.Utils.UriUtils.PathToFileUri (path)) != null) {
+			if (duplicate_check.Active && db.Photos.CheckForDuplicate (new SafeUri (path)) != null) {
 			 	System.IO.File.Delete (path);
 
 				return new SaveResult (path, true);
 			} else {
-				Uri dest = FileImportBackend.ChooseLocation (UriUtils.PathToFileUri (path));
+				var dest = FileImportBackend.ChooseLocation (new SafeUri (path));
 				System.IO.File.Move (path, dest.AbsolutePath);
 
 				return new SaveResult (dest.AbsolutePath, false);
diff --git a/src/Core/App.cs b/src/Core/App.cs
index bfac4c3..5f3729a 100644
--- a/src/Core/App.cs
+++ b/src/Core/App.cs
@@ -18,6 +18,7 @@ using Unique;
 
 using Mono.Unix;
 
+using Hyena;
 using FSpot.Utils;
 
 namespace FSpot
@@ -104,12 +105,12 @@ namespace FSpot
 			HandleSlideshow (tagname);
 		}
 
-		public void View (Uri uri)
+		public void View (SafeUri uri)
 		{
-			View (new Uri[] {uri});
+			View (new SafeUri[] {uri});
 		}
 
-		public void View (IEnumerable<Uri> uris)
+		public void View (IEnumerable<SafeUri> uris)
 		{
 			var uri_s = from uri in uris select uri.ToString ();
 			View (uri_s);
@@ -205,7 +206,7 @@ namespace FSpot
 			if (path != null && path.StartsWith ("gphoto2:"))
 				Organizer.ImportCamera (path);
 			else
-				Organizer.ImportFile (path == null ? null : new Uri(path));
+				Organizer.ImportFile (path == null ? null : new SafeUri (path));
 		}
 
 		void HandleOrganize ()
@@ -311,9 +312,9 @@ namespace FSpot
 
 		void HandleView (string[] uris)
 		{
-			List<Uri> ul = new List<Uri> ();
+			List<SafeUri> ul = new List<SafeUri> ();
 			foreach (var u in uris)
-				ul.Add (new Uri (u));
+				ul.Add (new SafeUri (u));
 			try {
 				Register (new FSpot.SingleView (ul.ToArray ()).Window);
 			} catch (System.Exception e) {
diff --git a/src/Core/IBrowsableItemExtensions.cs b/src/Core/IBrowsableItemExtensions.cs
index ae88c0f..6a1624d 100644
--- a/src/Core/IBrowsableItemExtensions.cs
+++ b/src/Core/IBrowsableItemExtensions.cs
@@ -1,4 +1,5 @@
 using System;
+using System.IO;
 
 namespace FSpot
 {
@@ -28,7 +29,9 @@ namespace FSpot
 
 		public static int CompareDefaultVersionUri (this IBrowsableItem photo1, IBrowsableItem photo2)
 		{
-			return string.Compare (photo1.DefaultVersion.Uri.ToString (), photo2.DefaultVersion.Uri.ToString ());
+			var photo1_uri = Path.Combine (photo1.DefaultVersion.BaseUri, photo1.DefaultVersion.Filename);
+			var photo2_uri = Path.Combine (photo2.DefaultVersion.BaseUri, photo2.DefaultVersion.Filename);
+			return string.Compare (photo1_uri, photo2_uri);
 		}
 	}
 }
diff --git a/src/Core/IBrowsableItemVersion.cs b/src/Core/IBrowsableItemVersion.cs
index a4de7e4..a0006f9 100644
--- a/src/Core/IBrowsableItemVersion.cs
+++ b/src/Core/IBrowsableItemVersion.cs
@@ -1,10 +1,14 @@
-using System;
+using Hyena;
 
 namespace FSpot
 {
     public interface IBrowsableItemVersion {
         string Name { get; }
         bool IsProtected { get; }
-        Uri Uri { get; }
+        SafeUri BaseUri { get; }
+        string Filename { get; }
+
+        // For convenience
+        SafeUri Uri { get; }
     }
 }
diff --git a/src/Core/Photo.cs b/src/Core/Photo.cs
index 7d72e02..3fa423d 100644
--- a/src/Core/Photo.cs
+++ b/src/Core/Photo.cs
@@ -9,6 +9,8 @@
  * This is free software. See COPYING for details.
  */
 
+using Hyena;
+
 using System;
 using System.IO;
 using System.Linq;
@@ -50,17 +52,6 @@ namespace FSpot
 			get { return Uri.UnescapeDataString (System.IO.Path.GetFileName (VersionUri (OriginalVersionId).AbsolutePath)); }
 		}
 	
-		//This property no longer keeps a 'directory' path, but the logical container for the image, like:
-		// file:///home/bob/Photos/2007/08/23 or
-		// http://www.google.com/logos
-		[Obsolete ("MARKED FOR REMOVAL. no longer makes sense with versions in different Directories. Any way to get rid of this ?")]
-		public string DirectoryPath {
-			get { 
-				System.Uri uri = VersionUri (OriginalVersionId);
-				return uri.Scheme + "://" + uri.Host + System.IO.Path.GetDirectoryName (uri.AbsolutePath);
-			}
-		}
-	
 		private ArrayList tags;
 		public Tag [] Tags {
 			get {
@@ -173,39 +164,40 @@ namespace FSpot
 	
 		// This doesn't check if a version of that name already exists, 
 		// it's supposed to be used only within the Photo and PhotoStore classes.
-		internal void AddVersionUnsafely (uint version_id, System.Uri uri, string md5_sum, string name, bool is_protected)
+		internal void AddVersionUnsafely (uint version_id, SafeUri base_uri, string filename, string md5_sum, string name, bool is_protected)
 		{
-			versions [version_id] = new PhotoVersion (this, version_id, uri, md5_sum, name, is_protected);
+			versions [version_id] = new PhotoVersion (this, version_id, base_uri, filename, md5_sum, name, is_protected);
 	
 			highest_version_id = Math.Max (version_id, highest_version_id);
 			changes.AddVersion (version_id);
 		}
 	
-		public uint AddVersion (System.Uri uri, string name)
+		public uint AddVersion (SafeUri base_uri, string filename, string name)
 		{
-			return AddVersion (uri, name, false);
+			return AddVersion (base_uri, filename, name, false);
 		}
 	
-		public uint AddVersion (System.Uri uri, string name, bool is_protected)
+		public uint AddVersion (SafeUri base_uri, string filename, string name, bool is_protected)
 		{
 			if (VersionNameExists (name))
 				throw new ApplicationException ("A version with that name already exists");
 			highest_version_id ++;
-			string md5_sum = GenerateMD5 (uri);
+			string md5_sum = GenerateMD5 (base_uri.Append (filename));
 
-			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, uri, md5_sum, name, is_protected);
+			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, base_uri, filename, md5_sum, name, is_protected);
 
 			changes.AddVersion (highest_version_id);
 			return highest_version_id;
 		}
 	
 		//FIXME: store versions next to originals. will crash on ro locations.
-		private System.Uri GetUriForVersionName (string version_name, string extension)
+		private string GetFilenameForVersionName (string version_name, string extension)
 		{
 			string name_without_extension = System.IO.Path.GetFileNameWithoutExtension (Name);
 	
-			return new System.Uri (System.IO.Path.Combine (DirectoryPath,  name_without_extension 
-						       + " (" + UriUtils.EscapeString (version_name, true, true, true) + ")" + extension));
+			return name_without_extension + " (" +
+				UriUtils.EscapeString (version_name, true, true, true)
+				+ ")" + extension;
 		}
 	
 		public bool VersionNameExists (string version_name)
@@ -213,7 +205,7 @@ namespace FSpot
             return Versions.Where ((v) => v.Name == version_name).Any ();
 		}
 
-		public System.Uri VersionUri (uint version_id)
+		public SafeUri VersionUri (uint version_id)
 		{
 			if (!versions.ContainsKey (version_id))
 				return null;
@@ -248,7 +240,7 @@ namespace FSpot
 					version = CreateDefaultModifiedVersion (DefaultVersionId, false);
 	
 				try {
-					Uri versionUri = VersionUri (version);
+					var versionUri = VersionUri (version);
 
 					using (Stream stream = System.IO.File.OpenWrite (versionUri.LocalPath)) {
 						img.Save (buffer, stream);
@@ -283,7 +275,7 @@ namespace FSpot
 			if (version_id == OriginalVersionId && !remove_original)
 				throw new Exception ("Cannot delete original version");
 	
-			System.Uri uri =  VersionUri (version_id);
+			SafeUri uri =  VersionUri (version_id);
 	
 			if (!keep_file) {
 				GLib.File file = GLib.FileFactory.NewForUri (uri);
@@ -325,8 +317,10 @@ namespace FSpot
 		private uint CreateVersion (string name, string extension, uint base_version_id, bool create, bool is_protected)
 		{
 			extension = extension ?? System.IO.Path.GetExtension (VersionUri (base_version_id).AbsolutePath);
-			System.Uri new_uri = GetUriForVersionName (name, extension);
-			System.Uri original_uri = VersionUri (base_version_id);
+			SafeUri new_base_uri = DefaultVersion.BaseUri;
+			string filename = GetFilenameForVersionName (name, extension);
+			SafeUri original_uri = VersionUri (base_version_id);
+			SafeUri new_uri = new_base_uri.Append (filename);
 			string md5_sum = MD5Sum;
 	
 			if (VersionNameExists (name))
@@ -335,7 +329,7 @@ namespace FSpot
 			if (create) {
 				GLib.File destination = GLib.FileFactory.NewForUri (new_uri);
 				if (destination.Exists)
-					throw new Exception (String.Format ("An object at this uri {0} already exists", new_uri.ToString ()));
+					throw new Exception (String.Format ("An object at this uri {0} already exists", new_uri));
 	
 		//FIXME. or better, fix the copy api !
 				GLib.File source = GLib.FileFactory.NewForUri (original_uri);
@@ -345,7 +339,7 @@ namespace FSpot
 			}
 			highest_version_id ++;
 
-			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, new_uri, md5_sum, name, is_protected);
+			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, new_base_uri, filename, md5_sum, name, is_protected);
 
 			changes.AddVersion (highest_version_id);
 	
@@ -372,7 +366,7 @@ namespace FSpot
 				name = String.Format (name, num);
 			}
 			highest_version_id ++;
-			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, version.Uri, version.MD5Sum, name, is_protected);
+			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, version.BaseUri, version.Filename, version.MD5Sum, name, is_protected);
 
 			changes.AddVersion (highest_version_id);
 
@@ -388,7 +382,9 @@ namespace FSpot
 									 "Modified ({0})", 
 									 num);
 				name = String.Format (name, num);
-				System.Uri uri = GetUriForVersionName (name, System.IO.Path.GetExtension (VersionUri(base_version_id).GetFilename()));
+				//SafeUri uri = GetUriForVersionName (name, System.IO.Path.GetExtension (VersionUri(base_version_id).GetFilename()));
+				string filename = GetFilenameForVersionName (name, System.IO.Path.GetExtension (versions[base_version_id].Filename));
+				SafeUri uri = DefaultVersion.BaseUri.Append (filename);
 				GLib.File file = GLib.FileFactory.NewForUri (uri);
 	
 				if (! VersionNameExists (name) && ! file.Exists)
@@ -408,7 +404,8 @@ namespace FSpot
 						(num == 1) ? Catalog.GetString ("Modified in {1}") : Catalog.GetString ("Modified in {1} ({0})"),
 						num, name);
 	
-				System.Uri uri = GetUriForVersionName (final_name, System.IO.Path.GetExtension (VersionUri(base_version_id).GetFilename()));
+				string filename = GetFilenameForVersionName (name, System.IO.Path.GetExtension (versions[base_version_id].Filename));
+				SafeUri uri = DefaultVersion.BaseUri.Append (filename);
 				GLib.File file = GLib.FileFactory.NewForUri (uri);
 
 				if (! VersionNameExists (final_name) && ! file.Exists)
@@ -526,14 +523,14 @@ namespace FSpot
 			} 
 		}
 
-		private static IDictionary<System.Uri, string> md5_cache = new Dictionary<System.Uri, string> ();
+		private static IDictionary<SafeUri, string> md5_cache = new Dictionary<SafeUri, string> ();
 
 		public static void ResetMD5Cache () {
 			if (md5_cache != null)	
 				md5_cache.Clear (); 
 		}
 
-		public static string GenerateMD5 (System.Uri uri)
+		public static string GenerateMD5 (SafeUri uri)
 		{
 		 	try {
 			 	if (md5_cache.ContainsKey (uri))
@@ -557,11 +554,13 @@ namespace FSpot
 
 
 		// Constructor
-		public Photo (uint id, long unix_time, System.Uri uri, string md5_sum)
+		public Photo (uint id, long unix_time, SafeUri base_uri, string filename, string md5_sum)
 			: base (id)
 		{
-			if (uri == null)
-				throw new System.ArgumentNullException ("uri");
+			if (base_uri == null)
+				throw new System.ArgumentNullException ("base_uri");
+			if (filename == String.Empty)
+				throw new System.ArgumentNullException ("filename");
 	
 			time = DbUtils.DateTimeFromUnixTime (unix_time);
 	
@@ -571,7 +570,7 @@ namespace FSpot
 	
 			// Note that the original version is never stored in the photo_versions table in the
 			// database.
-			AddVersionUnsafely (OriginalVersionId, uri, md5_sum, Catalog.GetString ("Original"), true);
+			AddVersionUnsafely (OriginalVersionId, base_uri, filename, md5_sum, Catalog.GetString ("Original"), true);
 		}
 
 #region IComparable implementation
diff --git a/src/Core/PhotoVersion.cs b/src/Core/PhotoVersion.cs
index 8593b02..f5cdd82 100644
--- a/src/Core/PhotoVersion.cs
+++ b/src/Core/PhotoVersion.cs
@@ -10,56 +10,30 @@
  * This is free software. See COPYING for details.
  */
 
+using Hyena;
+
 namespace FSpot
 {
 	public class PhotoVersion : IBrowsableItemVersion
 	{
-		IBrowsableItem photo;
-		uint version_id;
-		System.Uri uri;
-		string md5_sum;
-		string name;
-		bool is_protected;
-	
-		public string Name {
-			get { return name; }
-			set { name = value; }
-		}
-	
-		public IBrowsableItem Photo {
-			get { return photo; }
-		}
-	
-		public System.Uri Uri {
-			get { return uri; }
-			set { 
-				if (value == null)
-					throw new System.ArgumentNullException ("uri");
-				uri = value;
-			}
-		}
-
-		public string MD5Sum {
-			get { return md5_sum; } 
-			internal set { md5_sum = value; }
-		}
-	
-		public uint VersionId {
-			get { return version_id; }
-		}
-	
-		public bool IsProtected {
-			get { return is_protected; }
-		}
+		public string Name { get; set; }
+		public IBrowsableItem Photo { get; private set; }
+		public SafeUri BaseUri { get; set; }
+        public string Filename { get; set; }
+        public SafeUri Uri { get { return BaseUri.Append (Filename); } }
+		public string MD5Sum { get; internal set; }
+		public uint VersionId { get; private set; }
+		public bool IsProtected { get; private set; }
 	
-		public PhotoVersion (IBrowsableItem photo, uint version_id, System.Uri uri, string md5_sum, string name, bool is_protected)
+		public PhotoVersion (IBrowsableItem photo, uint version_id, SafeUri base_uri, string filename, string md5_sum, string name, bool is_protected)
 		{
-			this.photo = photo;
-			this.version_id = version_id;
-			this.uri = uri;
-			this.md5_sum = md5_sum;
-			this.name = name;
-			this.is_protected = is_protected;
+			Photo = photo;
+			VersionId = version_id;
+			BaseUri = base_uri;
+            Filename = filename;
+			MD5Sum = md5_sum;
+			Name = name;
+			IsProtected = is_protected;
 		}
 	}
 }
diff --git a/src/Core/SafeUri.cs b/src/Core/SafeUri.cs
new file mode 100644
index 0000000..880147f
--- /dev/null
+++ b/src/Core/SafeUri.cs
@@ -0,0 +1,208 @@
+/***************************************************************************
+ *  SafeUri.cs
+ *
+ *  Copyright (C) 2006 Novell, Inc.
+ *  Written by Aaron Bockover <aaron abock org>
+ ****************************************************************************/
+
+/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
+ *
+ *  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.Runtime.InteropServices;
+
+namespace Hyena
+{
+    public class SafeUri
+    {
+        private enum LocalPathCheck {
+            NotPerformed,
+            Yes,
+            No
+        }
+
+        private static int MAX_SCHEME_LENGTH = 6;
+
+        private string uri;
+        private string local_path;
+        private string scheme;
+        private LocalPathCheck local_path_check = LocalPathCheck.NotPerformed;
+
+        public SafeUri (string uri)
+        {
+            int scheme_delimit_index = uri.IndexOf ("://");
+            if (scheme_delimit_index > 0 && scheme_delimit_index <= MAX_SCHEME_LENGTH) {
+                this.uri = uri;
+            } else {
+                this.uri = FilenameToUri (uri);
+            }
+        }
+
+        public SafeUri (string uri, bool isUri)
+        {
+            if (isUri) {
+                this.uri = uri;
+            } else {
+                this.uri = FilenameToUri (uri);
+            }
+        }
+
+        public SafeUri (Uri uri)
+        {
+            this.uri = uri.AbsoluteUri;
+        }
+
+        public static string FilenameToUri (string localPath)
+        {
+            // TODO: replace with managed conversion to avoid marshalling
+            IntPtr path_ptr = GLib.Marshaller.StringToPtrGStrdup (localPath);
+
+#if WIN32
+            IntPtr uri_ptr = g_filename_to_uri_utf8 (path_ptr, IntPtr.Zero, IntPtr.Zero);
+#else
+            IntPtr uri_ptr = g_filename_to_uri (path_ptr, IntPtr.Zero, IntPtr.Zero);
+#endif
+            GLib.Marshaller.Free (path_ptr);
+
+            if (uri_ptr == IntPtr.Zero) {
+                throw new ApplicationException ("Filename path must be absolute");
+            }
+
+            string uri = GLib.Marshaller.Utf8PtrToString (uri_ptr);
+            GLib.Marshaller.Free (uri_ptr);
+
+            return uri;
+        }
+
+        public static string UriToFilename (string uri)
+        {
+            // TODO: replace with managed conversion to avoid marshalling
+            IntPtr uri_ptr = GLib.Marshaller.StringToPtrGStrdup (uri);
+#if WIN32
+            IntPtr path_ptr = g_filename_from_uri_utf8 (uri_ptr, IntPtr.Zero, IntPtr.Zero);
+#else
+            IntPtr path_ptr = g_filename_from_uri (uri_ptr, IntPtr.Zero, IntPtr.Zero);
+#endif
+
+            GLib.Marshaller.Free (uri_ptr);
+
+            if (path_ptr == IntPtr.Zero) {
+                throw new ApplicationException ("URI could not be converted to local file location");
+            }
+
+            string path = GLib.Marshaller.Utf8PtrToString (path_ptr);
+            GLib.Marshaller.Free (path_ptr);
+
+            return path;
+        }
+
+        public static string UriToFilename (SafeUri uri)
+        {
+            return UriToFilename (uri.AbsoluteUri);
+        }
+
+        public override string ToString ()
+        {
+            return AbsoluteUri;
+        }
+
+        public static implicit operator string(SafeUri s)
+        {
+            return s.ToString ();
+        }
+
+        public override bool Equals (object o)
+        {
+            if (!(o is SafeUri)) {
+                return false;
+            }
+
+            return (o as SafeUri).AbsoluteUri == AbsoluteUri;
+        }
+
+        public override int GetHashCode ()
+        {
+            return AbsoluteUri.GetHashCode ();
+        }
+
+        public string AbsoluteUri {
+            get { return uri; }
+        }
+
+        public bool IsLocalPath {
+            get {
+                if (local_path_check == LocalPathCheck.NotPerformed) {
+                    if (IsFile) {
+                        local_path_check = LocalPathCheck.Yes;
+                        return true;
+                    } else {
+                        local_path_check = LocalPathCheck.No;
+                        return false;
+                    }
+                }
+
+                return local_path_check == LocalPathCheck.Yes;
+            }
+        }
+
+        public string AbsolutePath {
+            get {
+                if (local_path == null && IsLocalPath) {
+                    local_path = UriToFilename (uri);
+                }
+
+                return local_path;
+            }
+        }
+
+        public string LocalPath {
+            get { return AbsolutePath; }
+        }
+
+        public string Scheme {
+            get {
+                if (scheme == null) {
+                    scheme = uri.Substring (0, uri.IndexOf ("://"));
+                }
+
+                return scheme;
+            }
+        }
+
+        public bool IsFile {
+            get { return Scheme == System.Uri.UriSchemeFile; }
+        }
+
+#if WIN32
+        [DllImport ("libglib-2.0-0.dll")]
+        private static extern IntPtr g_filename_to_uri_utf8 (IntPtr filename, IntPtr hostname, IntPtr error);
+
+        [DllImport ("libglib-2.0-0.dll")]
+        private static extern IntPtr g_filename_from_uri_utf8 (IntPtr uri, IntPtr hostname, IntPtr error);
+#else
+        [DllImport ("libglib-2.0-0.dll")]
+        private static extern IntPtr g_filename_to_uri (IntPtr filename, IntPtr hostname, IntPtr error);
+
+        [DllImport ("libglib-2.0-0.dll")]
+        private static extern IntPtr g_filename_from_uri (IntPtr uri, IntPtr hostname, IntPtr error);
+#endif
+    }
+}
diff --git a/src/Core/SafeUriExtensions.cs b/src/Core/SafeUriExtensions.cs
new file mode 100644
index 0000000..a913fd6
--- /dev/null
+++ b/src/Core/SafeUriExtensions.cs
@@ -0,0 +1,31 @@
+using Hyena;
+
+namespace FSpot
+{
+    public static class SafeUriExtensions
+    {
+        public static SafeUri Append (this SafeUri base_uri, string filename)
+        {
+            return new SafeUri (base_uri.AbsoluteUri + (base_uri.AbsoluteUri.EndsWith ("/") ? "" : "/") + filename);
+        }
+
+        public static SafeUri GetBaseUri (this SafeUri uri)
+        {
+            var abs_uri = uri.AbsoluteUri;
+            return new SafeUri (abs_uri.Substring (0, abs_uri.LastIndexOf ('/')));
+        }
+
+        public static string GetFilename (this SafeUri uri)
+        {
+            var abs_uri = uri.AbsoluteUri;
+            return abs_uri.Substring (abs_uri.LastIndexOf ('/') + 1);
+        }
+
+        public static string GetFilenameWithoutExtension (this SafeUri uri)
+        {
+            var name = uri.GetFilename ();
+            var index = name.LastIndexOf ('.');
+            return index > -1 ? name.Substring (0, index) : name;
+        }
+    }
+}
diff --git a/src/FSpot.Core.dll.config.in b/src/FSpot.Core.dll.config.in
new file mode 100644
index 0000000..cb3fab2
--- /dev/null
+++ b/src/FSpot.Core.dll.config.in
@@ -0,0 +1,4 @@
+<configuration>
+  <dllmap dll="libglib-2.0-0.dll" target="libglib-2.0.so.0" os="!windows,osx"/>
+  <dllmap dll="libglib-2.0-0.dll" target="libglib-2.0.dylib" os="osx"/>
+</configuration>
diff --git a/src/FileBrowsableItem.cs b/src/FileBrowsableItem.cs
index e5f9500..ee1e336 100644
--- a/src/FileBrowsableItem.cs
+++ b/src/FileBrowsableItem.cs
@@ -14,24 +14,22 @@ using System.IO;
 using System.Collections;
 using System.Xml;
 
+using Hyena;
 using FSpot.Utils;
+
 namespace FSpot {
 	public class FileBrowsableItem : IBrowsableItem, IDisposable
 	{
 		ImageFile img;
 		bool attempted;
 
-		public FileBrowsableItem (Uri uri)
+		public FileBrowsableItem (SafeUri uri)
 		{
 			DefaultVersion = new FileBrowsableItemVersion () {
                 Uri = uri
             };
 		}
 
-		public FileBrowsableItem (string path) : this (UriUtils.PathToFileUri (path))
-		{
-		}
-
 		protected ImageFile Image {
 			get {
 				if (!attempted) {
@@ -92,7 +90,10 @@ namespace FSpot {
 		private class FileBrowsableItemVersion : IBrowsableItemVersion {
 			public string Name { get { return String.Empty; } }
 			public bool IsProtected { get { return true; } }
-			public Uri Uri { get; set; }
+
+			public SafeUri BaseUri { get { return Uri.GetBaseUri (); } }
+			public string Filename { get { return Uri.GetFilename (); } }
+			public SafeUri Uri { get; set; }
 		}
 	}
 }
diff --git a/src/FileImportBackend.cs b/src/FileImportBackend.cs
index 93446e2..19650a7 100644
--- a/src/FileImportBackend.cs
+++ b/src/FileImportBackend.cs
@@ -9,6 +9,7 @@ using FSpot.Xmp;
 using FSpot.UI.Dialog;
 using System.IO;
 using Mono.Unix;
+using Hyena;
 
 public class ImportException : System.Exception {
 	public ImportException (string msg) : base (msg)
@@ -23,7 +24,7 @@ public class FileImportBackend : ImportBackend {
 	bool recurse;
 	bool copy;
 	bool detect_duplicates;
-	Uri [] base_paths;
+	SafeUri [] base_paths;
 	Tag [] tags;
 	Gtk.Window parent;
 
@@ -36,10 +37,11 @@ public class FileImportBackend : ImportBackend {
 	Stack directories;
 
 	private class ImportInfo : IBrowsableItem {
-		public ImportInfo (Uri original)
+		public ImportInfo (SafeUri original)
 		{
 			DefaultVersion = new ImportInfoVersion () {
-				Uri = original
+				BaseUri = original.GetBaseUri (),
+				Filename = original.GetFilename ()
 			};
 
 			try {
@@ -52,7 +54,7 @@ public class FileImportBackend : ImportBackend {
 		}
 
 		public IBrowsableItemVersion DefaultVersion { get; private set; }
-		public System.Uri DestinationUri { get; set; }
+		public SafeUri DestinationUri { get; set; }
 
 		public System.DateTime Time { get; private set; }
         
@@ -67,7 +69,10 @@ public class FileImportBackend : ImportBackend {
 	private class ImportInfoVersion : IBrowsableItemVersion {
 		public string Name { get { return String.Empty; } }
 		public bool IsProtected { get { return true; } }
-		public Uri Uri { get; set; }
+		public SafeUri BaseUri { get; set; }
+		public string Filename { get; set; }
+
+		public SafeUri Uri { get { return BaseUri.Append (Filename); } }
 	}
 
 	public override List<IBrowsableItem> Prepare ()
@@ -77,11 +82,11 @@ public class FileImportBackend : ImportBackend {
 
 		import_info = new List<IBrowsableItem> ();
 
-		foreach (Uri uri in base_paths) {
+		foreach (var uri in base_paths) {
 			var enumerator = new RecursiveFileEnumerator (uri, recurse, true);
 			foreach (var file in enumerator) {
 				if (FSpot.ImageFile.HasLoader (file.Uri))
-					import_info.Add (new ImportInfo (file.Uri));
+					import_info.Add (new ImportInfo (new SafeUri(file.Uri)));
 			}
 		}	
 
@@ -95,7 +100,7 @@ public class FileImportBackend : ImportBackend {
 	}
 	
 
-	public static Uri UniqueName (string path, string filename)
+	public static SafeUri UniqueName (string path, string filename)
 	{
 		int i = 1;
 		string dest = System.IO.Path.Combine (path, filename);
@@ -109,18 +114,17 @@ public class FileImportBackend : ImportBackend {
 			dest = System.IO.Path.Combine (path, numbered_name);
 		}
 		
-		return new Uri ("file://"+dest);
+		return new SafeUri ("file://"+dest);
 	}
 	
-	public static Uri ChooseLocation (Uri uri)
+	public static SafeUri ChooseLocation (SafeUri uri)
 	{
 		return ChooseLocation (uri, null);
 	}
 
-	private static Uri ChooseLocation (Uri uri, Stack created_directories)
+	private static SafeUri ChooseLocation (SafeUri uri, Stack created_directories)
 	{
-		var segments = uri.Segments;
-		string name = segments [segments.Length - 1];
+		string name = uri.GetFilename ();
 		DateTime time;
 		using (FSpot.ImageFile img = FSpot.ImageFile.Create (uri)) {
 			time = img.Date;
@@ -161,7 +165,7 @@ public class FileImportBackend : ImportBackend {
 		if ("file://" + Path.Combine (dest_dir, name) == uri.ToString ())
 			return uri;
 		 
-		Uri dest = UniqueName (dest_dir, name);
+		var dest = UniqueName (dest_dir, name);
 		
 		return dest;
 	}
@@ -182,7 +186,7 @@ public class FileImportBackend : ImportBackend {
 		bool needs_commit = false;
 		bool abort = false;
 		try {
-			Uri destination = info.DefaultVersion.Uri;
+			var destination = info.DefaultVersion.Uri;
 			if (copy)
 				destination = ChooseLocation (info.DefaultVersion.Uri, directories);
 
@@ -329,11 +333,11 @@ public class FileImportBackend : ImportBackend {
 		//rolls.EndImport();    // Clean up the imported session.
 	}
 
-	public FileImportBackend (PhotoStore store, Uri [] base_paths, bool recurse, Gtk.Window parent) : this (store, base_paths, false, recurse, false, null, parent) {}
+	public FileImportBackend (PhotoStore store, SafeUri [] base_paths, bool recurse, Gtk.Window parent) : this (store, base_paths, false, recurse, false, null, parent) {}
 
-	public FileImportBackend (PhotoStore store, Uri [] base_paths, bool copy, bool recurse, Tag [] tags, Gtk.Window parent) : this (store, base_paths, copy, recurse, false, null, parent) {}
+	public FileImportBackend (PhotoStore store, SafeUri [] base_paths, bool copy, bool recurse, Tag [] tags, Gtk.Window parent) : this (store, base_paths, copy, recurse, false, null, parent) {}
 
-	public FileImportBackend (PhotoStore store, Uri [] base_paths, bool copy, bool recurse, bool detect_duplicates, Tag [] tags, Gtk.Window parent)
+	public FileImportBackend (PhotoStore store, SafeUri [] base_paths, bool copy, bool recurse, bool detect_duplicates, Tag [] tags, Gtk.Window parent)
 	{
 		this.store = store;
 		this.copy = copy;
diff --git a/src/Filters/ChmodFilter.cs b/src/Filters/ChmodFilter.cs
index 6b756c1..622bb5b 100644
--- a/src/Filters/ChmodFilter.cs
+++ b/src/Filters/ChmodFilter.cs
@@ -30,7 +30,7 @@ namespace FSpot.Filters {
 		public bool Convert (FilterRequest req)
 		{
 			if (req.Current == req.Source) {
-				System.Uri uri = req.TempUri ();
+				var uri = req.TempUri ();
 				System.IO.File.Copy (req.Current.LocalPath, uri.LocalPath, true);
 				req.Current = uri;
 			}
diff --git a/src/Filters/FilterRequest.cs b/src/Filters/FilterRequest.cs
index 26d4b09..274d2ad 100644
--- a/src/Filters/FilterRequest.cs
+++ b/src/Filters/FilterRequest.cs
@@ -12,38 +12,35 @@
 using System;
 using System.Collections;
 
+using Hyena;
 using FSpot.Utils;
 
 namespace FSpot.Filters {
 
 	public class FilterRequest : IDisposable
 	{
-		Uri source;
-		Uri current;
+		SafeUri source;
+		SafeUri current;
 
 		ArrayList temp_uris;
 
-		public FilterRequest (Uri source)
+		public FilterRequest (SafeUri source)
 		{
 			this.source = source;
 			this.current = source;
 			temp_uris = new ArrayList ();
 		}
 
-		public FilterRequest (string path) : this (UriUtils.PathToFileUri (path))
-		{
-		}
-
 		~FilterRequest ()
 		{
 			Close ();
 		}
 
-		public Uri Source {
+		public SafeUri Source {
 			get { return source; }
 		}
 
-		public Uri Current {
+		public SafeUri Current {
 			get { return current; }
 			set { 
 				if (!value.Equals (source) && !temp_uris.Contains (value))
@@ -54,7 +51,7 @@ namespace FSpot.Filters {
 
 		public virtual void Close ()
 		{
-			foreach (Uri uri in temp_uris) {
+			foreach (SafeUri uri in temp_uris) {
 				try {
 					System.IO.File.Delete (uri.LocalPath);
 				} catch (System.IO.IOException e) {
@@ -70,12 +67,12 @@ namespace FSpot.Filters {
 			System.GC.SuppressFinalize (this);
 		}
 		
-		public Uri TempUri ()
+		public SafeUri TempUri ()
 		{
 			return TempUri (null);
 		}
 		
-		public Uri TempUri (string extension)
+		public SafeUri TempUri (string extension)
 		{
 			string imgtemp;
 			if (extension != null) {
@@ -85,13 +82,13 @@ namespace FSpot.Filters {
 			} else
 				imgtemp = System.IO.Path.GetTempFileName ();
 
-			Uri uri = UriUtils.PathToFileUri (imgtemp);
+			SafeUri uri = new SafeUri (imgtemp);
 			if (!temp_uris.Contains (uri))
 				temp_uris.Add (uri);
 			return uri;
 		}
 
-		public void Preserve (Uri uri)
+		public void Preserve (SafeUri uri)
 		{
 			temp_uris.Remove (uri);
 		}
diff --git a/src/Filters/OrientationFilter.cs b/src/Filters/OrientationFilter.cs
index 0b5154d..fef3886 100644
--- a/src/Filters/OrientationFilter.cs
+++ b/src/Filters/OrientationFilter.cs
@@ -16,7 +16,7 @@ namespace FSpot.Filters {
 		public bool Convert (FilterRequest req)
 		{
 			string source = req.Current.LocalPath;
-			System.Uri dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
+			var dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
 			string dest = dest_uri.LocalPath;
 
 			using (ImageFile img = ImageFile.Create (req.Current)) {
diff --git a/src/Filters/ResizeFilter.cs b/src/Filters/ResizeFilter.cs
index 55f42e7..1a4945d 100644
--- a/src/Filters/ResizeFilter.cs
+++ b/src/Filters/ResizeFilter.cs
@@ -40,7 +40,7 @@ namespace FSpot.Filters {
 		public bool Convert (FilterRequest req)
 		{
 			string source = req.Current.LocalPath;
-			System.Uri dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
+			var dest_uri = req.TempUri (System.IO.Path.GetExtension (source));
 			string dest = dest_uri.LocalPath;
 
 			using (ImageFile img = ImageFile.Create (req.Current)) {
diff --git a/src/Filters/SharpFilter.cs b/src/Filters/SharpFilter.cs
index 64ac496..f103d7e 100644
--- a/src/Filters/SharpFilter.cs
+++ b/src/Filters/SharpFilter.cs
@@ -28,7 +28,7 @@ namespace FSpot.Filters {
 
 		public bool Convert (FilterRequest req)
 		{
-			Uri dest_uri = req.TempUri (System.IO.Path.GetExtension (req.Current.LocalPath));
+			var dest_uri = req.TempUri (System.IO.Path.GetExtension (req.Current.LocalPath));
 
 			using (ImageFile img = ImageFile.Create (req.Current)) {
 				using (Pixbuf in_pixbuf = img.Load ()) {
diff --git a/src/Filters/UniqueNameFilter.cs b/src/Filters/UniqueNameFilter.cs
index a8ea8e6..01261c1 100644
--- a/src/Filters/UniqueNameFilter.cs
+++ b/src/Filters/UniqueNameFilter.cs
@@ -10,16 +10,14 @@
 
 using System;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot.Filters {
 	public class UniqueNameFilter : IFilter
 	{
-		Uri destination;
+		SafeUri destination;
 
-		public UniqueNameFilter (string destination) : this (UriUtils.PathToFileUri (destination))
-		{}
-
-		public UniqueNameFilter (Uri destination)
+		public UniqueNameFilter (SafeUri destination)
 		{
 			this.destination = destination;
 		}
@@ -40,7 +38,7 @@ namespace FSpot.Filters {
 			}
 			
 			System.IO.File.Copy (request.Current.LocalPath, dest);
-			request.Current = UriUtils.PathToFileUri (dest); 
+			request.Current = new SafeUri (dest);
 			return true;
 		}
 	}
diff --git a/src/FolderQueryWidget.cs b/src/FolderQueryWidget.cs
index 5a446d9..b08f50f 100644
--- a/src/FolderQueryWidget.cs
+++ b/src/FolderQueryWidget.cs
@@ -14,6 +14,7 @@ using System.Collections.Generic;
 using System.Linq;
 
 using Gtk;
+using Hyena;
 
 using FSpot;
 using FSpot.Utils;
@@ -52,7 +53,7 @@ namespace FSpot
 			
 			if (length < 4) {
 				
-				foreach (Uri uri in folder_set.Folders) {
+				foreach (var uri in folder_set.Folders) {
 					Image image = new Image ("gtk-directory", IconSize.Button);
 					image.TooltipText = uri.ToString ();
 					PackStart (image);
@@ -70,7 +71,7 @@ namespace FSpot
 				PackStart (image);
 				
 				StringBuilder builder = new StringBuilder ();
-				foreach (Uri uri in folder_set.Folders) {
+				foreach (var uri in folder_set.Folders) {
 					if (builder.Length > 0)
 						builder.AppendLine ();
 					
@@ -83,7 +84,7 @@ namespace FSpot
 			ShowAll ();
 		}
 		
-		public void SetFolders (IEnumerable<Uri> uris)
+		public void SetFolders (IEnumerable<SafeUri> uris)
 		{
 			folder_set.Folders = uris;
 			
diff --git a/src/ImageLoaderThread.cs b/src/ImageLoaderThread.cs
index 148c7da..121fc74 100644
--- a/src/ImageLoaderThread.cs
+++ b/src/ImageLoaderThread.cs
@@ -14,6 +14,7 @@ using System.Collections.Generic;
 using System.Threading;
 using System;
 
+using Hyena;
 using FSpot.Utils;
 
 public class ImageLoaderThread {
@@ -22,7 +23,7 @@ public class ImageLoaderThread {
 
 	protected class RequestItem {
 		/* The path to the image.  */
-		public Uri uri;
+		public SafeUri uri;
 
 		/* Order value; requests with a lower value get performed first.  */
 		public int order;
@@ -34,7 +35,7 @@ public class ImageLoaderThread {
 		public int width;
 		public int height;
 
-		public RequestItem (Uri uri, int order, int width, int height) {
+		public RequestItem (SafeUri uri, int order, int width, int height) {
 			this.uri = uri;
 			this.order = order;
 			this.width = width;
@@ -57,7 +58,7 @@ public class ImageLoaderThread {
 
 	/* A dict of all the requests; note that the current request
 	   isn't in the dict.  */
-	Dictionary<Uri, RequestItem> requests_by_uri;
+	Dictionary<SafeUri, RequestItem> requests_by_uri;
 //	private Hashtable requests_by_path;
 
 	/* Current request.  Request currently being handled by the
@@ -79,13 +80,13 @@ public class ImageLoaderThread {
 
 	// Public API.
 
-	public delegate void PixbufLoadedHandler (ImageLoaderThread loader, Uri uri, int order, Pixbuf result);
+	public delegate void PixbufLoadedHandler (ImageLoaderThread loader, SafeUri uri, int order, Pixbuf result);
 	public event PixbufLoadedHandler OnPixbufLoaded;
 
 	public ImageLoaderThread ()
 	{
 		queue = new ArrayList ();
-		requests_by_uri = new Dictionary<Uri, RequestItem> ();
+		requests_by_uri = new Dictionary<SafeUri, RequestItem> ();
 //		requests_by_path = Hashtable.Synchronized (new Hashtable ());
 		processed_requests = new Queue ();
 		
@@ -119,12 +120,12 @@ public class ImageLoaderThread {
 			t.Abort ();
 	}
 
-	public void Request (Uri uri, int order)
+	public void Request (SafeUri uri, int order)
 	{
 		Request (uri, order, 0, 0);
 	}
 
-	public virtual void Request (Uri uri, int order, int width, int height)
+	public virtual void Request (SafeUri uri, int order, int width, int height)
 	{
 		lock (queue) {
 			if (InsertRequest (uri, order, width, height))
@@ -132,7 +133,7 @@ public class ImageLoaderThread {
 		}
 	}
 
-	public void Cancel (Uri uri)
+	public void Cancel (SafeUri uri)
 	{
 		lock (queue) {
 			RequestItem r = requests_by_uri [uri];
@@ -170,7 +171,7 @@ public class ImageLoaderThread {
 	/* Insert the request in the queue, return TRUE if the queue actually grew.
 	   NOTE: Lock the queue before calling.  */
 
-	private bool InsertRequest (Uri uri, int order, int width, int height)
+	private bool InsertRequest (SafeUri uri, int order, int width, int height)
 	{
 		/* Check if this is the same as the request currently being processed.  */
 		lock(processed_requests) {
diff --git a/src/Imaging/Ciff.cs b/src/Imaging/Ciff.cs
index 34c6071..c8e2250 100644
--- a/src/Imaging/Ciff.cs
+++ b/src/Imaging/Ciff.cs
@@ -1,5 +1,6 @@
 using System;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot.Ciff {
 	public enum Tag {
@@ -334,7 +335,7 @@ namespace FSpot.Ciff {
 			}
 		}
 
-		public CiffFile (Uri uri) : base (uri)
+		public CiffFile (SafeUri uri) : base (uri)
 		{
 		}
 
diff --git a/src/Imaging/DCRawFile.cs b/src/Imaging/DCRawFile.cs
index be4ba35..f65eab9 100644
--- a/src/Imaging/DCRawFile.cs
+++ b/src/Imaging/DCRawFile.cs
@@ -1,6 +1,7 @@
 using System.Diagnostics;
 using System.IO;
 using System;
+using Hyena;
 
 namespace FSpot {
 	public class Pipe : System.IO.Stream {
@@ -78,7 +79,7 @@ namespace FSpot {
 		{
 		}
 
-		public DCRawFile (Uri uri) : base (uri)
+		public DCRawFile (SafeUri uri) : base (uri)
 		{
 		}
 
@@ -87,7 +88,7 @@ namespace FSpot {
 			return RawPixbufStream (uri);
 		}
 
-		internal static System.IO.Stream RawPixbufStream (Uri location)
+		internal static System.IO.Stream RawPixbufStream (SafeUri location)
 		{
 			string path = location.LocalPath;
 			string [] args = new string [] { dcraw_command, "-h", "-w", "-c", "-t", "0", path };
diff --git a/src/Imaging/ImageFile.cs b/src/Imaging/ImageFile.cs
index c974c9f..78d1cbc 100644
--- a/src/Imaging/ImageFile.cs
+++ b/src/Imaging/ImageFile.cs
@@ -1,3 +1,5 @@
+using Hyena;
+
 using System;
 using System.IO;
 using System.Collections;
@@ -17,17 +19,18 @@ namespace FSpot {
 	}
 
 	public class ImageFile : IDisposable {
-		protected Uri uri;
+		protected SafeUri uri;
 
 		static Hashtable name_table;
 		internal static Hashtable NameTable { get { return name_table; } }
 
+		[Obsolete("Use ImageFile (SafeUri) instead!")]
 		public ImageFile (string path) 
 		{
-			this.uri = UriUtils.PathToFileUri (path);
+			this.uri = new SafeUri (path);
 		}
 		
-		public ImageFile (Uri uri)
+		public ImageFile (SafeUri uri)
 		{
 			this.uri = uri;
 		}
@@ -104,7 +107,7 @@ namespace FSpot {
 				}
 		}
 
-		public Uri Uri {
+		public SafeUri Uri {
 			get { return this.uri; }
 		}
 
@@ -187,18 +190,18 @@ namespace FSpot {
 			}
 		}
 
-		[Obsolete ("use HasLoader (System.Uri) instead")]
+		[Obsolete ("use HasLoader (Hyena.SafeUri) instead")]
 		public static bool HasLoader (string path)
 		{
-			return HasLoader (UriUtils.PathToFileUri (path));
+			return HasLoader (new SafeUri (path));
 		}
 		
-		public static bool HasLoader (Uri uri)
+		public static bool HasLoader (SafeUri uri)
 		{
 			return GetLoaderType (uri) != null;
 		}
 
-		static Type GetLoaderType (Uri uri)
+		static Type GetLoaderType (SafeUri uri)
 		{
 			string path = uri.AbsolutePath;
 			string extension = System.IO.Path.GetExtension (path).ToLower ();
@@ -217,13 +220,13 @@ namespace FSpot {
 			return t;
 		}
 		
-		[Obsolete ("use Create (System.Uri) instead")]
+		[Obsolete ("use Create (Hyena.SafeUri) instead")]
 		public static ImageFile Create (string path)
 		{
-			return Create (UriUtils.PathToFileUri (path));
+			return Create (new SafeUri (path));
 		}
 
-		public static ImageFile Create (Uri uri)
+		public static ImageFile Create (SafeUri uri)
 		{
 			System.Type t = GetLoaderType (uri);
 			ImageFile img;
diff --git a/src/Imaging/JpegFile.cs b/src/Imaging/JpegFile.cs
index c82e6dc..58fff9e 100644
--- a/src/Imaging/JpegFile.cs
+++ b/src/Imaging/JpegFile.cs
@@ -4,6 +4,7 @@ using System.IO;
 using FSpot.Xmp;
 using FSpot.Tiff;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot {
 	public interface IThumbnailContainer {
@@ -21,7 +22,7 @@ namespace FSpot {
                         get { return false; }
                 }
 		
-		public JpegFile (Uri uri) : base (uri)
+		public JpegFile (SafeUri uri) : base (uri)
 		{
 			try {
 				// Console.WriteLine ("approximate quality = {0}", Header.GuessQuality ());
diff --git a/src/Imaging/MrwFile.cs b/src/Imaging/MrwFile.cs
index b4693df..c0a9fed 100644
--- a/src/Imaging/MrwFile.cs
+++ b/src/Imaging/MrwFile.cs
@@ -1,4 +1,5 @@
 using FSpot.Tiff;
+using Hyena;
 
 namespace FSpot.Mrw {
 	// Minolta raw format
@@ -173,7 +174,7 @@ namespace FSpot.Mrw {
 		MrmBlock mrm;
 		FSpot.Tiff.Header header;
 
-		public MrwFile (System.Uri uri) : base (uri)
+		public MrwFile (SafeUri uri) : base (uri)
 		{
 		}
 
diff --git a/src/Imaging/PngFile.cs b/src/Imaging/PngFile.cs
index cccf6e6..07b5b51 100644
--- a/src/Imaging/PngFile.cs
+++ b/src/Imaging/PngFile.cs
@@ -5,6 +5,7 @@ using System.IO;
 using FSpot.Xmp;
 using System.Collections;
 using System.Reflection;
+using Hyena;
 
 namespace FSpot.Png {
 	public class PngFile : ImageFile, SemWeb.StatementSource {
@@ -31,7 +32,7 @@ namespace FSpot.Png {
 			get { return Header.Chunks; }
 		}
 
-		public PngFile (System.Uri uri) : base (uri)
+		public PngFile (SafeUri uri) : base (uri)
 		{
 		}
 
diff --git a/src/Imaging/PnmFile.cs b/src/Imaging/PnmFile.cs
index fd73f34..ab44ea9 100644
--- a/src/Imaging/PnmFile.cs
+++ b/src/Imaging/PnmFile.cs
@@ -2,6 +2,7 @@ using FSpot.Imaging;
 using SemWeb;
 using System;
 using System.IO;
+using Hyena;
 
 #if ENABLE_NUNIT
 using NUnit.Framework;
@@ -15,7 +16,7 @@ namespace FSpot.Pnm {
                         get { return false; }
                 }
 
-		public PnmFile (Uri uri) : base (uri) 
+		public PnmFile (SafeUri uri) : base (uri)
 		{
 		}
 
diff --git a/src/Imaging/RafFile.cs b/src/Imaging/RafFile.cs
index 5bcb3dd..477abe3 100644
--- a/src/Imaging/RafFile.cs
+++ b/src/Imaging/RafFile.cs
@@ -1,4 +1,5 @@
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot.Raf {
 	// This is reverse engineered from looking at the sample files I have
@@ -28,7 +29,7 @@ namespace FSpot.Raf {
                         get { return false; }
                 }
 
-		public RafFile (System.Uri uri) : base (uri)
+		public RafFile (SafeUri uri) : base (uri)
 		{
 		}
 
diff --git a/src/Imaging/SvgFile.cs b/src/Imaging/SvgFile.cs
index 428758f..69b4e3f 100644
--- a/src/Imaging/SvgFile.cs
+++ b/src/Imaging/SvgFile.cs
@@ -1,4 +1,5 @@
 using System;
+using Hyena;
 
 namespace FSpot.Svg {
 	public class SvgFile : ImageFile // SemWeb.StatementSource 
@@ -10,7 +11,7 @@ namespace FSpot.Svg {
                         get { return false; }
                 }
 
-		public SvgFile (Uri uri) : base (uri)
+		public SvgFile (SafeUri uri) : base (uri)
 		{
 		}
 
diff --git a/src/Imaging/Tiff.cs b/src/Imaging/Tiff.cs
index 083e13e..b21591b 100644
--- a/src/Imaging/Tiff.cs
+++ b/src/Imaging/Tiff.cs
@@ -5,6 +5,7 @@ using SemWeb;
 using System;
 using System.IO;
 using System.Collections.Generic;
+using Hyena;
 
 namespace FSpot.Tiff {
 
@@ -2037,7 +2038,7 @@ namespace FSpot.Tiff {
 			}
 		}
 
-		public TiffFile (Uri uri) : base (uri)
+		public TiffFile (SafeUri uri) : base (uri)
 		{
 			try {
 				using (System.IO.Stream input = Open ()) {
@@ -2134,7 +2135,7 @@ namespace FSpot.Tiff {
 		{
 		}
 
-		public DngFile (System.Uri uri) : base (uri) 
+		public DngFile (SafeUri uri) : base (uri)
 		{
 		}
 
@@ -2218,7 +2219,7 @@ namespace FSpot.Tiff {
 		{
 		}
 
-		public NefFile (Uri uri) : base (uri)
+		public NefFile (SafeUri uri) : base (uri)
 		{
 		}
 
@@ -2282,7 +2283,7 @@ namespace FSpot.Tiff {
 		{
 		}
 
-		public Cr2File (Uri uri) : base (uri)
+		public Cr2File (SafeUri uri) : base (uri)
 		{
 //							Gtk.MessageDialog md = new Gtk.MessageDialog (null, 
 //							                                              Gtk.DialogFlags.DestroyWithParent,
diff --git a/src/Imaging/X3fFile.cs b/src/Imaging/X3fFile.cs
index e152543..ec93821 100644
--- a/src/Imaging/X3fFile.cs
+++ b/src/Imaging/X3fFile.cs
@@ -3,6 +3,7 @@ using System.IO;
 using FSpot;
 using FSpot.Utils;
 using SemWeb;
+using Hyena;
 
 namespace FSpot.X3f {
 	internal class Info {
@@ -93,7 +94,7 @@ namespace FSpot.X3f {
 		{
 		}
 
-		public X3fFile (System.Uri uri) : base (uri)
+		public X3fFile (SafeUri uri) : base (uri)
 		{
 		}
 		
diff --git a/src/ImportCommand.cs b/src/ImportCommand.cs
index 25e4396..3f67087 100644
--- a/src/ImportCommand.cs
+++ b/src/ImportCommand.cs
@@ -19,6 +19,7 @@ using System.Collections;
 using System.IO;
 using System;
 using Mono.Unix;
+using Hyena;
 
 using FSpot;
 using FSpot.Utils;
@@ -58,11 +59,11 @@ public class ImportCommand : GladeDialog
 
 	internal class VfsSource : ImportSource
 	{
-		public Uri uri;
+		public SafeUri uri;
 
-		public VfsSource (Uri uri)
+		public VfsSource (SafeUri uri)
 		{ 
-			string [] components = uri.Segments;
+			string [] components = uri.ToString ().Split ('/');
 			this.Name = components [components.Length - 1];
 			if (this.Name == String.Empty)
 				this.Name = components [components.Length - 2];
@@ -86,12 +87,12 @@ public class ImportCommand : GladeDialog
 			this.Name = mount.Name;
 
 			try {
-				mount_point = mount.Root.Uri.LocalPath;
+				mount_point = mount.Root.Uri;
 			} catch (System.Exception e) {
 				System.Console.WriteLine (e);
 			}
 
-			uri = mount.Root.Uri;
+			uri = new SafeUri (mount.Root.Uri);
 			
 			
 			if (this.IsIPodPhoto)
@@ -257,7 +258,7 @@ public class ImportCommand : GladeDialog
 			return -1;
 		}
 		
-		public int FindItemPosition (Uri uri)
+		public int FindItemPosition (SafeUri uri)
 		{
 			Gtk.Widget [] children = this.Children;
 			System.Console.WriteLine ("looking for {0}", uri);
@@ -307,7 +308,7 @@ public class ImportCommand : GladeDialog
 
 	string loading_string;
 
-	public Uri ImportUri { get; private set; }
+	public SafeUri ImportUri { get; private set; }
 	
 	private SourceItem Source;
 
@@ -328,7 +329,7 @@ public class ImportCommand : GladeDialog
 			return;
 
 		if (item.Source is BrowseSource) {
-			Uri uri = ChooseUri ();
+			var uri = ChooseUri ();
 			
 			if (uri != null) {
 				SourceItem uri_item = new SourceItem (new VfsSource (uri));
@@ -507,9 +508,9 @@ public class ImportCommand : GladeDialog
 		Preferences.Set(Preferences.IMPORT_CHECK_DUPLICATES, duplicate_check.Active);
 	}
 	
-	public Uri ChooseUri ()
+	public SafeUri ChooseUri ()
 	{
-		Uri uri = null;
+		SafeUri uri = null;
 
 		FileChooserDialog file_chooser =
 			new FileChooserDialog (Catalog.GetString ("Import"), this.Dialog,
@@ -528,7 +529,7 @@ public class ImportCommand : GladeDialog
 		int response = file_chooser.Run ();
 
 		if ((ResponseType) response == ResponseType.Ok) {
-			uri = new Uri (file_chooser.Uri);
+			uri = new SafeUri (file_chooser.Uri);
 		}
 
 		file_chooser.Destroy ();
@@ -556,7 +557,7 @@ public class ImportCommand : GladeDialog
 		duplicate_check.Active = Preferences.Get<bool> (Preferences.IMPORT_CHECK_DUPLICATES);
 	}
 
-	public int ImportFromUri (PhotoStore store, Uri uri)
+	public int ImportFromUri (PhotoStore store, SafeUri uri)
 	{
 		this.store = store;
 		this.CreateDialog ("import_dialog");
@@ -733,7 +734,7 @@ public class ImportCommand : GladeDialog
 		if (ImportUri == null)
 			return false;
 
-		Uri [] uriimport =  {ImportUri};
+		SafeUri [] uriimport =  {ImportUri};
 		
 		if (copy_check != null)
 			copy = copy_check.Active;
@@ -763,17 +764,17 @@ public class ImportCommand : GladeDialog
 		return false;
 	}
 
-	public int ImportFromUris (PhotoStore store, Uri [] uris, bool copy)
+	public int ImportFromUris (PhotoStore store, SafeUri [] uris, bool copy)
 	{
 		return ImportFromUris (store, uris, null, copy);
 	}
 	
-	public int ImportFromUris (PhotoStore store, Uri [] uris, Tag [] tags)
+	public int ImportFromUris (PhotoStore store, SafeUri [] uris, Tag [] tags)
 	{
 		return ImportFromUris (store, uris, tags, false);
 	}
 	
-	public int ImportFromUris (PhotoStore store, Uri [] uris, Tag [] tags, bool copy)
+	public int ImportFromUris (PhotoStore store, SafeUri [] uris, Tag [] tags, bool copy)
 	{
 		collection = new FSpot.PhotoList (new Photo [0]);
 		int count = DoImport (new FileImportBackend (store, uris, copy, true, tags, main_window ));
diff --git a/src/Loaders/GdkImageLoader.cs b/src/Loaders/GdkImageLoader.cs
index 3095be3..daf72ac 100644
--- a/src/Loaders/GdkImageLoader.cs
+++ b/src/Loaders/GdkImageLoader.cs
@@ -14,6 +14,7 @@ using System.Threading;
 using Gdk;
 using FSpot.Utils;
 using FSpot.Platform;
+using Hyena;
 
 namespace FSpot.Loaders {
 	public class GdkImageLoader : Gdk.PixbufLoader, IImageLoader
@@ -23,7 +24,7 @@ namespace FSpot.Loaders {
 		{	
 		}
 
-		public void Load (Uri uri)
+		public void Load (SafeUri uri)
 		{
 			if (is_disposed)
 				return;
diff --git a/src/Loaders/IImageLoader.cs b/src/Loaders/IImageLoader.cs
index 84c7408..3934547 100644
--- a/src/Loaders/IImageLoader.cs
+++ b/src/Loaders/IImageLoader.cs
@@ -12,6 +12,7 @@
 using FSpot.Utils;
 using System;
 using Gdk;
+using Hyena;
 
 namespace FSpot.Loaders {
 	public interface IImageLoader : IDisposable {
@@ -21,7 +22,7 @@ namespace FSpot.Loaders {
 		event EventHandler<AreaUpdatedEventArgs> AreaUpdated;
 		event EventHandler Completed;
 
-		void Load (Uri uri);
+		void Load (SafeUri uri);
 
 		Pixbuf Pixbuf { get; }
 		PixbufOrientation PixbufOrientation { get; }
diff --git a/src/Loaders/ImageLoader.cs b/src/Loaders/ImageLoader.cs
index 94b20fb..9bab51f 100644
--- a/src/Loaders/ImageLoader.cs
+++ b/src/Loaders/ImageLoader.cs
@@ -14,6 +14,7 @@ using FSpot.Utils;
 using System;
 using System.Collections.Generic;
 using Gdk;
+using Hyena;
 
 namespace FSpot.Loaders {
 	public static class ImageLoader {
@@ -37,7 +38,7 @@ namespace FSpot.Loaders {
 				}
 		}
 
-		public static IImageLoader Create (Uri uri)
+		public static IImageLoader Create (SafeUri uri)
 		{
 			string path = uri.AbsolutePath;
 			string extension = System.IO.Path.GetExtension (path).ToLower ();
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index a6fef16..8ac4950 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -17,6 +17,7 @@ using Gtk;
 using Mono.Addins;
 using Mono.Unix;
 
+using Hyena;
 using Banshee.Kernel;
 
 using FSpot;
@@ -947,7 +948,7 @@ namespace FSpot
 			}
 		}
 		
-		public void SetFolderQuery (IEnumerable<Uri> uri_list)
+		public void SetFolderQuery (IEnumerable<SafeUri> uri_list)
 		{
 			ShowQueryWidget ();
 			query_widget.SetFolders (uri_list);
@@ -1148,7 +1149,7 @@ namespace FSpot
 			}
 		}
 	
-		public void ImportFile (Uri uri)
+		public void ImportFile (SafeUri uri)
 		{
 			ImportCommand command = new ImportCommand (main_window);
 			if (command.ImportFromUri (Database.Photos, uri) > 0) {
diff --git a/src/Makefile.am b/src/Makefile.am
index b47f0ed..3e3ee9e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,7 +38,9 @@ CORE_CSDISTFILES =				\
 	$(srcdir)/Core/IBrowsableCollection.cs	\
 	$(srcdir)/Core/PhotoChanges.cs		\
 	$(srcdir)/Core/PhotosChanges.cs		\
-	$(srcdir)/Core/Roll.cs
+	$(srcdir)/Core/Roll.cs 				\
+	$(srcdir)/Core/SafeUri.cs 			\
+	$(srcdir)/Core/SafeUriExtensions.cs
 
 QUERY_CSDISTFILES =				\
 	$(srcdir)/Query/DateRange.cs		\
@@ -378,9 +380,11 @@ GNOME_PLATFORM_ASSEMBLIES =			\
 	-pkg:gconf-sharp-2.0			\
 	$(NDESK_DBUS_LIBS)				\
 	-r:Mono.Posix				\
+	-r:FSpot.Core.dll			\
 	-r:FSpot.Utils.dll
 
 NULL_PLATFORM_ASSEMBLIES =			\
+	-r:FSpot.Core.dll			\
 	-r:FSpot.Utils.dll
 
 F_SPOT_ASSEMBLIES = 				\
@@ -452,6 +456,7 @@ fspotlib_DATA = f-spot.exe.config	\
 		FSpot.Query.dll.mdb	\
 		FSpot.Core.dll		\
 		FSpot.Core.dll.mdb	\
+		FSpot.Core.dll.config	\
 		FSpot.JobScheduler.dll	\
 		FSpot.JobScheduler.dll.mdb \
 		FSpot.Bling.dll		\
@@ -550,6 +555,7 @@ EXTRA_DIST =					\
 	$(F_SPOT_DISTRESOURCES)			\
 	f-spot.exe.config.in			\
 	f-spot.in				\
+	FSpot.Core.dll.config			\
 	FSpot.Utils.dll.config			\
 	FSpot.Widgets.dll.config.in		\
 	Cms.dll.config.in
@@ -565,6 +571,7 @@ CLEANFILES =					\
 	FSpot.Utils.dll				\
 	FSpot.Query.dll				\
 	FSpot.Query.dll.mdb			\
+	FSpot.Core.dll.config		\
 	FSpot.Core.dll.mdb			\
 	FSpot.Core.dll				\
 	FSpot.JobScheduler.dll			\
diff --git a/src/PhotoImageView.cs b/src/PhotoImageView.cs
index d916ec1..902ce98 100644
--- a/src/PhotoImageView.cs
+++ b/src/PhotoImageView.cs
@@ -15,6 +15,7 @@ using FSpot.Editors;
 using FSpot.Utils;
 using FSpot.Loaders;
 
+using Hyena;
 using Gdk;
 
 namespace FSpot.Widgets {
@@ -166,7 +167,7 @@ namespace FSpot.Widgets {
 #region loader		
 		uint timer;
 		IImageLoader loader;
-		void Load (Uri uri)
+		void Load (SafeUri uri)
 		{
 			timer = Log.DebugTimerStart ();
 			if (loader != null)
diff --git a/src/PhotoLoader.cs b/src/PhotoLoader.cs
index 82b5156..4636b05 100644
--- a/src/PhotoLoader.cs
+++ b/src/PhotoLoader.cs
@@ -2,6 +2,7 @@ using System;
 
 using FSpot.Platform;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot {
 	[Obsolete ("nuke or rename this")]
@@ -41,7 +42,7 @@ namespace FSpot {
 			return ValidateThumbnail (item.DefaultVersion.Uri, pixbuf);
 		}
 
-		static public Gdk.Pixbuf ValidateThumbnail (System.Uri uri, Gdk.Pixbuf pixbuf)
+		static public Gdk.Pixbuf ValidateThumbnail (SafeUri uri, Gdk.Pixbuf pixbuf)
 		{			
 			using (Gdk.Pixbuf thumbnail = ThumbnailCache.Default.GetThumbnailForUri (uri)) {
 				if (pixbuf != null && thumbnail != null && !ThumbnailFactory.ThumbnailIsValid (thumbnail, uri)) {
diff --git a/src/PhotoStore.cs b/src/PhotoStore.cs
index 89422eb..62f8e74 100644
--- a/src/PhotoStore.cs
+++ b/src/PhotoStore.cs
@@ -26,6 +26,7 @@ using FSpot.Query;
 using FSpot.Utils;
 using FSpot.Platform;
 
+using Hyena;
 using Banshee.Database;
 
 
@@ -98,7 +99,7 @@ public class PhotoStore : DbStore<Photo> {
 		Database.ExecuteNonQuery ("CREATE INDEX idx_photos_roll_id ON photos(roll_id)");
 	}
 
-	public Photo CheckForDuplicate (System.Uri uri) {
+	public Photo CheckForDuplicate (SafeUri uri) {
 		// Here we can go wild in comparing photos,
 		// for now we check on uri and md5
 		Photo found = GetByUri (uri);
@@ -131,14 +132,18 @@ public class PhotoStore : DbStore<Photo> {
 		return null;
 	}
 
-	public Photo Create (System.Uri uri, uint roll_id)
+	public Photo Create (SafeUri uri, uint roll_id)
 	{
 		return Create (uri, uri, roll_id);
 	}
 
-	public Photo Create (System.Uri new_uri, System.Uri orig_uri, uint roll_id)
+	public Photo Create (SafeUri new_uri, SafeUri orig_uri, uint roll_id)
 	{
 		Photo photo;
+
+		var new_base_uri = new_uri.GetBaseUri ();
+		var filename = new_uri.GetFilename ();
+
 		using (FSpot.ImageFile img = FSpot.ImageFile.Create (orig_uri)) {
 			long unix_time = DbUtils.UnixTimeFromDateTime (img.Date);
 			string description = img.Description != null  ? img.Description.Split ('\0') [0] : String.Empty;
@@ -149,8 +154,8 @@ public class PhotoStore : DbStore<Photo> {
 					"INSERT INTO photos (time, base_uri, filename, description, roll_id, default_version_id, rating, md5_sum) "	+
 					"VALUES (:time, :base_uri, :filename, :description, :roll_id, :default_version_id, :rating, :md5_sum)",
 	 				"time", unix_time,
-					"base_uri", new_uri.GetDirectoryUri ().ToString (),
-					"filename", new_uri.GetFilename (),
+					"base_uri", new_base_uri,
+					"filename", filename,
 	 				"description", description,
 					"roll_id", roll_id,
 	 				"default_version_id", Photo.OriginalVersionId,
@@ -159,7 +164,7 @@ public class PhotoStore : DbStore<Photo> {
 				)
 			);
 	
-			photo = new Photo (id, unix_time, new_uri, md5_sum);
+			photo = new Photo (id, unix_time, new_base_uri, filename, md5_sum);
 			photo.Loaded = true;
 			EmitAdded (photo);
 		}
@@ -180,11 +185,12 @@ public class PhotoStore : DbStore<Photo> {
 		while (reader.Read ()) {
 			uint version_id = Convert.ToUInt32 (reader ["version_id"]);
 			string name = reader["name"].ToString ();
-			System.Uri uri = new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ());
+			var base_uri = new SafeUri (reader ["base_uri"].ToString ());
+			var filename = reader ["filename"].ToString ();
 			string md5_sum = reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null;
 			bool is_protected = Convert.ToBoolean (reader["protected"]);
 			                              
-			photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected);
+			photo.AddVersionUnsafely (version_id, base_uri, filename, md5_sum, name, is_protected);
 		}
 		reader.Close();
 	}
@@ -221,11 +227,12 @@ public class PhotoStore : DbStore<Photo> {
 			if (reader ["version_id"] != null) {
 				uint version_id = Convert.ToUInt32 (reader ["version_id"]);
 				string name = reader["name"].ToString ();
-				System.Uri uri = new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ());
+				var base_uri = new SafeUri (reader ["base_uri"].ToString ());
+				var filename = reader ["filename"].ToString ();
 				string md5_sum = reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null;
 				bool is_protected = Convert.ToBoolean (reader["protected"]);
 				
-				photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected);
+				photo.AddVersionUnsafely (version_id, base_uri, filename, md5_sum, name, is_protected);
 			}
 
 			/*
@@ -278,9 +285,11 @@ public class PhotoStore : DbStore<Photo> {
 		);
 
 		if (reader.Read ()) {
+			var base_uri = new SafeUri (reader ["base_uri"].ToString ());
+			var filename = reader ["filename"].ToString ();
 			photo = new Photo (id,
 				Convert.ToInt64 (reader ["time"]),
-			    new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ()),
+			    base_uri, filename,
 				reader["md5_sum"] != null ? reader["md5_sum"].ToString () : null
 			);
 
@@ -301,25 +310,29 @@ public class PhotoStore : DbStore<Photo> {
 		return photo;
 	}
 
-	public Photo GetByUri (System.Uri uri)
+	public Photo GetByUri (SafeUri uri)
 	{
 		Photo photo = null;
 
 		uint timer = Log.DebugTimerStart ();
 
+		var base_uri = uri.GetBaseUri ();
+		var filename = uri.GetFilename ();
+
 		SqliteDataReader reader =
 			Database.Query (new DbCommand ("SELECT id, time, description, roll_id, default_version_id, rating, photos.md5_sum AS md5_sum " +
 			                               " FROM photos " +
 			                               " LEFT JOIN photo_versions AS pv ON photos.id = pv.photo_id" +
 			                               " WHERE (photos.base_uri = :base_uri AND photos.filename = :filename)" +
 			                               " OR (pv.base_uri = :base_uri AND pv.filename = :filename)",
-			                               "base_uri", uri.GetDirectoryUri ().ToString (),
-			                               "filename", uri.GetFilename ()));
+			                               "base_uri", base_uri,
+			                               "filename", filename));
 
 		if (reader.Read ()) {
 			photo = new Photo (Convert.ToUInt32 (reader ["id"]),
 					   Convert.ToInt64 (reader ["time"]),
-					   uri,
+					   base_uri,
+					   filename,
 					   reader["md5_sum"] != null ? reader["md5_sum"].ToString () : null);
 
 			photo.Description = reader["description"].ToString ();
@@ -364,10 +377,12 @@ public class PhotoStore : DbStore<Photo> {
 		);
 
 		while (reader.Read ()) {
+			var base_uri = new SafeUri (reader ["base_uri"].ToString ());
+			var filename = reader ["filename"].ToString ();
 			Photo photo =
 				new Photo (Convert.ToUInt32 (reader ["id"]),
 				           Convert.ToInt64 (reader ["time"]),
-				           new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ()),
+				           base_uri, filename,
 				           md5_sum);
 
 			photo.Description = reader["description"].ToString ();
@@ -478,7 +493,7 @@ public class PhotoStore : DbStore<Photo> {
 					"description", photo.Description,
 					"default_version_id", photo.DefaultVersionId,
 					"time", DbUtils.UnixTimeFromDateTime (photo.Time),
-					"base_uri", photo.VersionUri (Photo.OriginalVersionId).GetDirectoryUri ().ToString (),
+					"base_uri", photo.VersionUri (Photo.OriginalVersionId).GetBaseUri (),
 					"filename", photo.VersionUri (Photo.OriginalVersionId).GetFilename (),
 					"rating", String.Format ("{0}", photo.Rating),
 					"md5_sum", (photo.MD5Sum != String.Empty ? photo.MD5Sum : null),
@@ -519,8 +534,8 @@ public class PhotoStore : DbStore<Photo> {
 					"photo_id", photo.Id,
 					"version_id", version_id,
 					"name", version.Name,
-			        "base_uri", version.Uri.GetDirectoryUri ().ToString (),
-					"filename", version.Uri.GetFilename (),
+			        "base_uri", version.BaseUri,
+					"filename", version.Filename,
 					"is_protected", version.IsProtected,
 					"md5_sum", (version.MD5Sum != String.Empty ? version.MD5Sum : null)));
 			}
@@ -532,8 +547,8 @@ public class PhotoStore : DbStore<Photo> {
 					"base_uri = :base_uri, filename = :filename, protected = :protected, md5_sum = :md5_sum " +
 					"WHERE photo_id = :photo_id AND version_id = :version_id",
 					"name", version.Name,
-					"base_uri", version.Uri.GetDirectoryUri ().ToString (),
-					"filename", version.Uri.GetFilename (),
+					"base_uri", version.BaseUri,
+					"filename", version.Filename,
 					"protected", version.IsProtected,
 					"photo_id", photo.Id,
 					"md5_sum", (version.MD5Sum != String.Empty ? version.MD5Sum : null),
@@ -580,7 +595,7 @@ public class PhotoStore : DbStore<Photo> {
 	public event EventHandler<DbItemEventArgs<Photo>> ItemsRemovedOverDBus;
 
 	public Photo CreateOverDBus (string new_path, string orig_path, uint roll_id)  {
-		Photo photo = Create (UriUtils.PathToFileUri (new_path), UriUtils.PathToFileUri (orig_path), roll_id);
+		Photo photo = Create (new SafeUri (new_path), new SafeUri (orig_path), roll_id);
 		EmitAddedOverDBus (photo);
 
 		return photo;
@@ -840,10 +855,12 @@ public class PhotoStore : DbStore<Photo> {
 			Photo photo = LookupInCache (id);
 
 			if (photo == null) {
+				var base_uri = new SafeUri (reader ["base_uri"].ToString ());
+				var filename = reader ["filename"].ToString ();
 				photo =
 					new Photo (id,
 					           Convert.ToInt64 (reader ["time"]),
-					           new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ()),
+					           base_uri, filename,
 					           reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null
 				);
 				photo.Description = reader["description"].ToString ();
@@ -883,10 +900,10 @@ public class PhotoStore : DbStore<Photo> {
 		return query_result.ToArray ();
 	}
 
-	public Photo [] Query (System.Uri uri)
+	public Photo [] Query (SafeUri uri)
 	{
 		string filename = uri.GetFilename ();
-		
+
 		/* query by file */
 		if ( ! String.IsNullOrEmpty (filename)) {
 			return Query (new DbCommand (
@@ -902,7 +919,7 @@ public class PhotoStore : DbStore<Photo> {
 			"FROM photos " 				+
 			"WHERE base_uri LIKE :base_uri "		+
 			"AND filename LIKE :filename",
-			"base_uri", uri.GetDirectoryUri ().ToString (),
+			"base_uri", uri.GetBaseUri (),
 			"filename", filename));
 		}
 		
diff --git a/src/PixbufCache.cs b/src/PixbufCache.cs
index 81f653b..51f57ef 100644
--- a/src/PixbufCache.cs
+++ b/src/PixbufCache.cs
@@ -10,6 +10,7 @@
 using System;
 using System.Collections;
 using System.Threading;
+using Hyena;
 
 using FSpot.Platform;
 
@@ -36,13 +37,13 @@ namespace FSpot {
 			ThumbnailGenerator.Default.OnPixbufLoaded += HandleThumbnailLoaded;
 		}
 		
-		public void HandleThumbnailLoaded (ImageLoaderThread loader, Uri uri, int order, Gdk.Pixbuf result)
+		public void HandleThumbnailLoaded (ImageLoaderThread loader, SafeUri uri, int order, Gdk.Pixbuf result)
 		{
 			if (result != null)
 				Reload (uri);
 		}
 
-		public void Request (Uri uri, object closure, int width, int height)
+		public void Request (SafeUri uri, object closure, int width, int height)
 		{
 			lock (items) {
 				CacheEntry entry = items[uri] as CacheEntry;
@@ -59,7 +60,7 @@ namespace FSpot {
 			}
 		}
 
-//		public void Update (Uri uri, Gdk.Pixbuf pixbuf)
+//		public void Update (SafeUri uri, Gdk.Pixbuf pixbuf)
 //		{
 //			lock (items) {
 //				CacheEntry entry = (CacheEntry) items [uri];
@@ -89,7 +90,7 @@ namespace FSpot {
 			}
 		}
 
-		public void Reload (Uri uri)
+		public void Reload (SafeUri uri)
 		{
 			CacheEntry entry;
 
@@ -221,7 +222,7 @@ namespace FSpot {
 		}
 		       
 
-		private CacheEntry ULookup (Uri uri)
+		private CacheEntry ULookup (SafeUri uri)
 		{
 			CacheEntry entry = (CacheEntry) items [uri];
 			if (entry != null) {
@@ -230,14 +231,14 @@ namespace FSpot {
 			return (CacheEntry) entry;
 		}
 
-		public CacheEntry Lookup (Uri uri)
+		public CacheEntry Lookup (SafeUri uri)
 		{
 			lock (items) {
 				return ULookup (uri);
 			}
 		}
 
-		private void URemove (Uri uri)
+		private void URemove (SafeUri uri)
 		{
 			CacheEntry entry = (CacheEntry) items [uri];
 			if (entry != null) {
@@ -247,7 +248,7 @@ namespace FSpot {
 			}
 		}
 
-		public void Remove (Uri uri)
+		public void Remove (SafeUri uri)
 		{
 			lock (items) {
 				URemove (uri);
@@ -256,14 +257,14 @@ namespace FSpot {
 
 		public class CacheEntry : System.IDisposable {
 			private Gdk.Pixbuf pixbuf;
-			private Uri uri;
+			private SafeUri uri;
 			private int width;
 			private int height;
 			private object data;
 			private bool reload;
 			private PixbufCache cache;
 			
-			public CacheEntry (PixbufCache cache, Uri uri, object closure, int width, int height)
+			public CacheEntry (PixbufCache cache, SafeUri uri, object closure, int width, int height)
 			{
 				this.uri = uri;
 				this.width = width;
@@ -279,7 +280,7 @@ namespace FSpot {
 				set { reload = value; }
 			}
 
-			public Uri Uri {
+			public SafeUri Uri {
 				get { return uri; }
 			}
 
diff --git a/src/PixbufUtils.cs b/src/PixbufUtils.cs
index 87baa26..63696b4 100644
--- a/src/PixbufUtils.cs
+++ b/src/PixbufUtils.cs
@@ -16,6 +16,7 @@ using System;
 using System.IO;
 using FSpot;
 using FSpot.Utils;
+using Hyena;
 
 public class PixbufUtils {
 	static Pixbuf error_pixbuf = null;
@@ -121,7 +122,6 @@ public class PixbufUtils {
 			Gdk.Pixbuf rotated = FSpot.Utils.PixbufUtils.TransformOrientation (orig, orientation);
 			
 			if (orig != rotated) {
-				FSpot.Utils.PixbufUtils.CopyThumbnailOptions (orig, rotated);
 				orig.Dispose ();
 			}
 			loader.Dispose ();
@@ -147,7 +147,6 @@ public class PixbufUtils {
 		if (pixbuf == null)
 			return null;
 		Pixbuf result = new Pixbuf (pixbuf, 0, 0, pixbuf.Width, pixbuf.Height);
-		FSpot.Utils.PixbufUtils.CopyThumbnailOptions (pixbuf, result);
 		return result;
 	}
 
@@ -168,8 +167,6 @@ public class PixbufUtils {
 		else
 			result = pixbuf.Copy ();
 
-		FSpot.Utils.PixbufUtils.CopyThumbnailOptions (pixbuf, result);
-
 		return result;
 	}
 		
@@ -675,19 +672,17 @@ public class PixbufUtils {
 		return orientation;
 	}
 
-	public static PixbufOrientation GetOrientation (System.Uri uri)
+	public static PixbufOrientation GetOrientation (SafeUri uri)
 	{
 		using (FSpot.ImageFile img = FSpot.ImageFile.Create (uri)) {
 			return img.Orientation;
 		}	
 	}
 	
-	[Obsolete ("Use GetOrientation (System.Uri) instead")]
+	[Obsolete ("Use GetOrientation (SafeUri) instead")]
 	public static PixbufOrientation GetOrientation (string path)
 	{
-		using (FSpot.ImageFile img = FSpot.ImageFile.Create (path)) {
-			return img.Orientation;
-		}
+        return GetOrientation (new SafeUri (path));
 	}
 
 	[DllImport("libgnomeui-2-0.dll")]
diff --git a/src/Platform/Gnome/ThumbnailFactory.cs b/src/Platform/Gnome/ThumbnailFactory.cs
index 816b053..1fa40ee 100644
--- a/src/Platform/Gnome/ThumbnailFactory.cs
+++ b/src/Platform/Gnome/ThumbnailFactory.cs
@@ -9,6 +9,7 @@
  * This is free software, See COPYING for details
  */
 
+using Hyena;
 using System;
 using FSpot.Utils;
 using Gdk;
@@ -19,7 +20,7 @@ namespace FSpot.Platform
 	{
 		static Gnome.ThumbnailFactory gnome_thumbnail_factory = new Gnome.ThumbnailFactory (Gnome.ThumbnailSize.Large);
 
-		public static void SaveThumbnail (Pixbuf pixbuf, Uri imageUri)
+		public static void SaveThumbnail (Pixbuf pixbuf, SafeUri imageUri)
 		{
 			if (pixbuf == null)
 				throw new ArgumentNullException ("pixbuf");
@@ -33,17 +34,17 @@ namespace FSpot.Platform
 			SaveThumbnail (pixbuf, imageUri, mtime);
 		}
 
-		public static void SaveThumbnail (Pixbuf pixbuf, Uri imageUri, DateTime originalMtime)
+		public static void SaveThumbnail (Pixbuf pixbuf, SafeUri imageUri, DateTime originalMtime)
 		{
 			if (pixbuf == null)
 				throw new ArgumentNullException ("pixbuf");
 			if (imageUri == null)
 				throw new ArgumentNullException ("imageUri");
 
-			gnome_thumbnail_factory.SaveThumbnail (pixbuf, UriUtils.UriToStringEscaped (imageUri), originalMtime);
+			gnome_thumbnail_factory.SaveThumbnail (pixbuf, imageUri, originalMtime);
 		}
 
-		public static void DeleteThumbnail (Uri imageUri)
+		public static void DeleteThumbnail (SafeUri imageUri)
 		{
 			if (imageUri == null)
 				throw new ArgumentNullException ("imageUri");
@@ -55,7 +56,7 @@ namespace FSpot.Platform
 			}
 		}
 
-		public static void MoveThumbnail (Uri fromUri, Uri toUri)
+		public static void MoveThumbnail (SafeUri fromUri, SafeUri toUri)
 		{
 			if (fromUri == null)
 				throw new ArgumentNullException ("fromUri");
@@ -64,7 +65,7 @@ namespace FSpot.Platform
 			System.IO.File.Move (PathForUri (fromUri), PathForUri (toUri));
 		}
 
-		public static bool ThumbnailIsValid (Pixbuf pixbuf, Uri imageUri)
+		public static bool ThumbnailIsValid (Pixbuf pixbuf, SafeUri imageUri)
 		{
 			if (imageUri == null)
 				throw new ArgumentNullException ("imageUri");
@@ -85,7 +86,7 @@ namespace FSpot.Platform
 			}
 		}
 
-		public static bool ThumbnailIsValid (Pixbuf pixbuf, Uri imageUri, DateTime mtime)
+		public static bool ThumbnailIsValid (Pixbuf pixbuf, SafeUri imageUri, DateTime mtime)
 		{
 			if (pixbuf == null)
 				throw new ArgumentNullException ("pixbuf");
@@ -93,7 +94,7 @@ namespace FSpot.Platform
 				throw new ArgumentNullException ("imageUri");
 
 			try {
-				return  Gnome.Thumbnail.IsValid (pixbuf, UriUtils.UriToStringEscaped (imageUri), mtime);
+				return  Gnome.Thumbnail.IsValid (pixbuf, imageUri, mtime);
 			} catch (System.IO.FileNotFoundException) {
 				// If the original file is not on disk, the thumbnail is as valid as it's going to get
 				return true;
@@ -103,7 +104,7 @@ namespace FSpot.Platform
 			}
 		}
 
-		public static Pixbuf LoadThumbnail (Uri imageUri)
+		public static Pixbuf LoadThumbnail (SafeUri imageUri)
 		{
 			if (imageUri == null)
 				throw new ArgumentNullException ("imageUri");
@@ -118,19 +119,19 @@ namespace FSpot.Platform
 			}
 		}
 
-		public static Pixbuf LoadThumbnail (Uri imageUri, int destWidth, int destHeight)
+		public static Pixbuf LoadThumbnail (SafeUri imageUri, int destWidth, int destHeight)
 		{
 			using (Pixbuf p = LoadThumbnail (imageUri)) {
 				return Gnome.Thumbnail.ScaleDownPixbuf (p, destWidth, destHeight);
 			}
 		}
 
-		public static bool ThumbnailExists (Uri imageUri)
+		public static bool ThumbnailExists (SafeUri imageUri)
 		{
 			return System.IO.File.Exists (PathForUri (imageUri));
 		}
 
-		public static bool ThumbnailIsRecent (Uri imageUri)
+		public static bool ThumbnailIsRecent (SafeUri imageUri)
 		{
 			if (imageUri == null)
 				throw new ArgumentNullException ("imageUri");
@@ -144,9 +145,9 @@ namespace FSpot.Platform
 			return imageUri.IsFile && System.IO.File.Exists (PathForUri (imageUri)) && System.IO.File.GetLastWriteTime (PathForUri (imageUri)) >= System.IO.File.GetLastWriteTime (imageUri.AbsolutePath);
 		}
 
-		static string PathForUri (Uri uri)
+		static string PathForUri (SafeUri uri)
 		{
-			return Gnome.Thumbnail.PathForUri (UriUtils.UriToStringEscaped (uri), Gnome.ThumbnailSize.Large);
+			return Gnome.Thumbnail.PathForUri (uri, Gnome.ThumbnailSize.Large);
 		}
 	}
 }
diff --git a/src/Platform/Null/ThumbnailFactory.cs b/src/Platform/Null/ThumbnailFactory.cs
index 0a3666c..5159da5 100644
--- a/src/Platform/Null/ThumbnailFactory.cs
+++ b/src/Platform/Null/ThumbnailFactory.cs
@@ -9,6 +9,7 @@
  * This is free software, See COPYING for details
  */
 
+using Hyena;
 using System;
 using FSpot.Utils;
 using System.Collections.Generic;
@@ -19,23 +20,23 @@ namespace FSpot.Platform
 	public class ThumbnailFactory
 	{
 
-		static Dictionary<Uri, Pixbuf> cache = new Dictionary<Uri, Pixbuf>();
-		public static void SaveThumbnail (Pixbuf pixbuf, Uri image_uri)
+		static Dictionary<SafeUri, Pixbuf> cache = new Dictionary<SafeUri, Pixbuf>();
+		public static void SaveThumbnail (Pixbuf pixbuf, SafeUri image_uri)
 		{
 			cache[image_uri]=pixbuf.Clone() as Pixbuf;
 		}
 
-		public static void SaveThumbnail (Pixbuf pixbuf, Uri image_uri, DateTime original_mtime)
+		public static void SaveThumbnail (Pixbuf pixbuf, SafeUri image_uri, DateTime original_mtime)
 		{
 			cache[image_uri]=pixbuf.Clone() as Pixbuf;
 		}
 
-		public static void DeleteThumbnail (Uri image_uri)
+		public static void DeleteThumbnail (SafeUri image_uri)
 		{
 			cache.Remove (image_uri);
 		}
 
-		public static void MoveThumbnail (Uri from_uri, Uri to_uri)
+		public static void MoveThumbnail (SafeUri from_uri, SafeUri to_uri)
 		{
 			Pixbuf p;
 			if (cache.TryGetValue (from_uri, out p))
@@ -43,17 +44,17 @@ namespace FSpot.Platform
 			cache.Remove (from_uri);
 		}
 
-		public static bool ThumbnailIsValid (Pixbuf pixbuf, Uri image_uri)
+		public static bool ThumbnailIsValid (Pixbuf pixbuf, SafeUri image_uri)
 		{
 			return cache.ContainsKey(image_uri);
 		}
 
-		public static bool ThumbnailIsValid (Pixbuf pixbuf, Uri image_uri, DateTime mtime)
+		public static bool ThumbnailIsValid (Pixbuf pixbuf, SafeUri image_uri, DateTime mtime)
 		{
 			return cache.ContainsKey(image_uri);
 		}
 
-		public static Pixbuf LoadThumbnail (Uri image_uri)
+		public static Pixbuf LoadThumbnail (SafeUri image_uri)
 		{
 			Pixbuf p;
 			if (cache.TryGetValue (image_uri, out p))
@@ -62,17 +63,17 @@ namespace FSpot.Platform
 			return null;
 		}
 
-		public static Pixbuf LoadThumbnail (Uri image_uri, int dest_width, int dest_height)
+		public static Pixbuf LoadThumbnail (SafeUri image_uri, int dest_width, int dest_height)
 		{
 			return null;
 		}
 
-		public static bool ThumbnailExists (Uri image_uri)
+		public static bool ThumbnailExists (SafeUri image_uri)
 		{
 			return cache.ContainsKey(image_uri);
 		}
 
-		public static bool ThumbnailIsRecent (Uri image_uri)
+		public static bool ThumbnailIsRecent (SafeUri image_uri)
 		{
 			return cache.ContainsKey(image_uri);
 		}
diff --git a/src/Query/FolderSet.cs b/src/Query/FolderSet.cs
index 70a13ea..1e284da 100644
--- a/src/Query/FolderSet.cs
+++ b/src/Query/FolderSet.cs
@@ -10,22 +10,23 @@
 
 using System;
 using System.Collections.Generic;
+using Hyena;
 
 
 namespace FSpot.Query
 {
 	public class FolderSet : IQueryCondition
 	{
-		HashSet<Uri> uri_list;
+		HashSet<SafeUri> uri_list;
 		
 		public FolderSet ()
 		{
-			uri_list = new HashSet<Uri> ();
+			uri_list = new HashSet<SafeUri> ();
 		}
 		
-		public IEnumerable<Uri> Folders {
+		public IEnumerable<SafeUri> Folders {
 			get { return uri_list; }
-			set { uri_list = (value == null) ? new HashSet<Uri> () : new HashSet<Uri> (value); }
+			set { uri_list = (value == null) ? new HashSet<SafeUri> () : new HashSet<SafeUri> (value); }
 		}
 		
 		protected static string EscapeQuotes (string v)
@@ -41,7 +42,7 @@ namespace FSpot.Query
 				return null;
 			
 			int i = 0;
-			foreach (Uri uri in uri_list) {
+			foreach (var uri in uri_list) {
 				items[i] =
 					String.Format ("id IN (SELECT id FROM photos WHERE base_uri LIKE '{0}%')",
 					               EscapeQuotes (uri.ToString ()));
diff --git a/src/QueryWidget.cs b/src/QueryWidget.cs
index 271ea81..a346061 100644
--- a/src/QueryWidget.cs
+++ b/src/QueryWidget.cs
@@ -18,7 +18,7 @@ using Gtk;
 using FSpot.Utils;
 using FSpot.Query;
 using FSpot.Widgets;
-
+using Hyena;
 
 
 namespace FSpot {
@@ -218,7 +218,7 @@ namespace FSpot {
 			return logic_widget.TagRequired (tag);
 		}
 		
-		public void SetFolders (IEnumerable<Uri> uri_list)
+		public void SetFolders (IEnumerable<SafeUri> uri_list)
 		{
 			folder_query_widget.SetFolders (uri_list);
 			query.RequestReload ();
diff --git a/src/RotateCommand.cs b/src/RotateCommand.cs
index a1faf4b..e4b80f1 100644
--- a/src/RotateCommand.cs
+++ b/src/RotateCommand.cs
@@ -18,6 +18,7 @@ using FSpot;
 using FSpot.Png;
 using FSpot.UI.Dialog;
 
+using Hyena;
 using FSpot.Utils;
 
 using Mono.Unix;
@@ -133,7 +134,7 @@ namespace FSpot {
 
 			Rotate (original_path, direction);
 
-			Gdk.Pixbuf thumb = FSpot.ThumbnailGenerator.Create (UriUtils.PathToFileUri (original_path));
+			Gdk.Pixbuf thumb = FSpot.ThumbnailGenerator.Create (new SafeUri (original_path));
 			if (thumb != null)
 				thumb.Dispose ();
 		
diff --git a/src/SendEmail.cs b/src/SendEmail.cs
index 2dfd203..7465d36 100644
--- a/src/SendEmail.cs
+++ b/src/SendEmail.cs
@@ -17,6 +17,7 @@ using FSpot.Filters;
 using FSpot.Utils;
 using FSpot.UI.Dialog;
 
+using Hyena;
 using Mono.Unix;
 
 namespace FSpot {
@@ -258,7 +259,7 @@ namespace FSpot {
 				filters.Add (new ResizeFilter ((uint) size));
 			else if (rotate)
 				filters.Add (new OrientationFilter ());
-			filters.Add (new UniqueNameFilter (tmp_mail_dir));
+			filters.Add (new UniqueNameFilter (new SafeUri (tmp_mail_dir)));
 
 
 			for (int i = 0; i < selection.Count; i++) {
diff --git a/src/SingleView.cs b/src/SingleView.cs
index 63652e5..a64f7eb 100644
--- a/src/SingleView.cs
+++ b/src/SingleView.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
 using Mono.Addins;
 using Mono.Unix;
 
+using Hyena;
 using FSpot.Extensions;
 using FSpot.Utils;
 using FSpot.UI.Dialog;
@@ -45,7 +46,7 @@ namespace FSpot {
 		private Gtk.Window window;
 		PhotoImageView image_view;
 		FSpot.Widgets.IconView directory_view;
-		private Uri uri;
+		private SafeUri uri;
 		
 		UriCollection collection;
 		
@@ -53,7 +54,7 @@ namespace FSpot {
 
 		private static Gtk.Tooltips toolTips = new Gtk.Tooltips ();
 
-		public SingleView (Uri [] uris) 
+		public SingleView (SafeUri [] uris)
 		{
 			string glade_name = "single_view";
 			this.uri = uris [0];
@@ -221,7 +222,7 @@ namespace FSpot {
 			}
 		}
 
-		private Uri CurrentUri
+		private SafeUri CurrentUri
 		{
 			get { 
 			 	return this.uri; 
@@ -229,7 +230,7 @@ namespace FSpot {
 			set {
 			 	this.uri = value;
 				collection.Clear ();
-				collection.LoadItems (new Uri[] { this.uri });
+				collection.LoadItems (new SafeUri[] { this.uri });
 			}
 		}
 
@@ -317,7 +318,7 @@ namespace FSpot {
 		private void HandleNewWindow (object sender, System.EventArgs args)
 		{
 			/* FIXME this needs to register witth the core */
-			new SingleView (new Uri[] {uri});
+			new SingleView (new SafeUri[] {uri});
 		}
 
 		private void HandlePreferences (object sender, System.EventArgs args)
@@ -353,7 +354,7 @@ namespace FSpot {
 			int response = chooser.Run ();
 
 			if ((ResponseType) response == ResponseType.Ok)
-				CurrentUri = new System.Uri (chooser.Uri);
+				CurrentUri = new SafeUri (chooser.Uri);
 			
 
 			chooser.Destroy ();
@@ -500,9 +501,9 @@ namespace FSpot {
 			int response = file_selector.Run ();
 			
 			if ((Gtk.ResponseType) response == Gtk.ResponseType.Ok) {
-				var l = new List<Uri> ();
+				var l = new List<SafeUri> ();
 				foreach (var s in file_selector.Uris)
-					l.Add (new Uri (s));
+					l.Add (new SafeUri (s));
 				new FSpot.SingleView (l.ToArray ());
 			}
 			
diff --git a/src/TagSelectionWidget.cs b/src/TagSelectionWidget.cs
index 9f09a09..0dd5ee5 100644
--- a/src/TagSelectionWidget.cs
+++ b/src/TagSelectionWidget.cs
@@ -706,7 +706,7 @@ namespace FSpot {
 				
 				database.BeginTransaction ();
 				List<Photo> photos = new List<Photo> ();
-				foreach (Uri photo_uri in list) {
+				foreach (var photo_uri in list) {
 					Photo photo = database.Photos.GetByUri (photo_uri);
 					
 					// FIXME - at this point we should import the photo, and then continue
diff --git a/src/ThumbnailCache.cs b/src/ThumbnailCache.cs
index 1910bdc..ce46c87 100644
--- a/src/ThumbnailCache.cs
+++ b/src/ThumbnailCache.cs
@@ -13,6 +13,7 @@ using System;
 using System.Collections;
 using Gdk;
 
+using Hyena;
 using FSpot.Utils;
 
 namespace FSpot
@@ -23,7 +24,7 @@ public class ThumbnailCache : IDisposable {
 
 	private class Thumbnail {
 		// Uri of the image source
-		public Uri uri;
+		public SafeUri uri;
 
 		// The uncompressed thumbnail.
 		public Pixbuf pixbuf;
@@ -55,7 +56,7 @@ public class ThumbnailCache : IDisposable {
 		}
 	}
 
-	public void AddThumbnail (Uri uri, Pixbuf pixbuf)
+	public void AddThumbnail (SafeUri uri, Pixbuf pixbuf)
 	{
 		Thumbnail thumbnail = new Thumbnail ();
 
@@ -70,7 +71,7 @@ public class ThumbnailCache : IDisposable {
 		MaybeExpunge ();
 	}
 
-	public Pixbuf GetThumbnailForUri (Uri uri)
+	public Pixbuf GetThumbnailForUri (SafeUri uri)
 	{
 		if (! pixbuf_hash.ContainsKey (uri))
 			return null;
@@ -83,7 +84,7 @@ public class ThumbnailCache : IDisposable {
 		return PixbufUtils.ShallowCopy (item.pixbuf);
 	}
 
-	public void RemoveThumbnailForUri (Uri uri)
+	public void RemoveThumbnailForUri (SafeUri uri)
 	{
 		if (! pixbuf_hash.ContainsKey (uri))
 			return;
diff --git a/src/ThumbnailGenerator.cs b/src/ThumbnailGenerator.cs
index ae4d408..ed27d5d 100644
--- a/src/ThumbnailGenerator.cs
+++ b/src/ThumbnailGenerator.cs
@@ -8,7 +8,7 @@
  */
 
 using System;
-using System.IO;
+using Hyena;
 using FSpot.Utils;
 using FSpot.Platform;
 
@@ -19,13 +19,8 @@ namespace FSpot {
 	public class ThumbnailGenerator : ImageLoaderThread {
 
 		static public ThumbnailGenerator Default = new ThumbnailGenerator ();
-		
-		public const string ThumbMTime = "tEXt::Thumb::MTime";
-		public const string ThumbUri = "tEXt::Thumb::URI";
-		public const string ThumbImageWidth = "tEXt::Thumb::Image::Width";
-		public const string ThumbImageHeight = "tEXt::Thumb::Image::Height"; 
 
-		public static Gdk.Pixbuf Create (Uri uri)
+		public static Gdk.Pixbuf Create (SafeUri uri)
 		{
 			try {
 				Gdk.Pixbuf thumb;
@@ -37,16 +32,6 @@ namespace FSpot {
 				if (thumb == null)
 					return null;
 
-				try { //Setting the thumb options
-					GFileInfo info = GLib.FileFactory.NewForUri (uri).QueryInfo ("time::modified", GLib.FileQueryInfoFlags.None, null);
-					DateTime mtime = NativeConvert.ToDateTime ((long)info.GetAttributeULong ("time::modified"));
-
-					FSpot.Utils.PixbufUtils.SetOption (thumb, ThumbUri, UriUtils.UriToStringEscaped (uri));
-					FSpot.Utils.PixbufUtils.SetOption (thumb, ThumbMTime, ((uint)GLib.Marshaller.DateTimeTotime_t (mtime)).ToString ());
-				} catch (System.Exception e) {
-					Log.Exception (e);
-				}
-
 				Save (thumb, uri);
 				return thumb;
 			} catch (Exception e) {
@@ -55,7 +40,7 @@ namespace FSpot {
 			}
 		}
 		
-		private static void Save (Gdk.Pixbuf image, Uri uri)
+		private static void Save (Gdk.Pixbuf image, SafeUri uri)
 		{
 			try {
 				ThumbnailCache.Default.RemoveThumbnailForUri (uri);
diff --git a/src/UI.Dialog/EditTagIconDialog.cs b/src/UI.Dialog/EditTagIconDialog.cs
index 954586d..49f8c09 100644
--- a/src/UI.Dialog/EditTagIconDialog.cs
+++ b/src/UI.Dialog/EditTagIconDialog.cs
@@ -16,6 +16,7 @@ using Mono.Unix;
 using Gtk;
 using FSpot.Widgets;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot.UI.Dialog
 {
@@ -159,7 +160,7 @@ namespace FSpot.UI.Dialog
 		void CreateTagIconFromExternalPhoto ()
 		{
 			try {
-				using (FSpot.ImageFile img = FSpot.ImageFile.Create (new Uri(external_photo_chooser.Uri))) {
+				using (FSpot.ImageFile img = FSpot.ImageFile.Create (new SafeUri(external_photo_chooser.Uri))) {
 					using (Gdk.Pixbuf external_image = img.Load ()) {
 						PreviewPixbuf = PixbufUtils.TagIconFromPixbuf (external_image);
 					}
diff --git a/src/UriCollection.cs b/src/UriCollection.cs
index 6f6a4b3..a6d453b 100644
--- a/src/UriCollection.cs
+++ b/src/UriCollection.cs
@@ -17,6 +17,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Xml;
 
+using Hyena;
 using GLib;
 
 namespace FSpot {
@@ -30,12 +31,12 @@ namespace FSpot {
 			LoadItems (files);
 		}
 
-		public UriCollection (Uri [] uri) : this ()
+		public UriCollection (SafeUri [] uri) : this ()
 		{
 			LoadItems (uri);
 		}
 
-		public void Add (Uri uri)
+		public void Add (SafeUri uri)
 		{
 			if (FSpot.ImageFile.HasLoader (uri)) {
 				//Console.WriteLine ("using image loader {0}", uri.ToString ());
@@ -57,16 +58,16 @@ namespace FSpot {
 			}
 		}
 
-		public void LoadItems (Uri [] uris)
+		public void LoadItems (SafeUri [] uris)
 		{
-			foreach (Uri uri in uris) {
+			foreach (SafeUri uri in uris) {
 				Add (uri);
 			}
 		}
 
 		private class RssLoader
 		{
-			public RssLoader (UriCollection collection, System.Uri uri)
+			public RssLoader (UriCollection collection, SafeUri uri)
 			{
 				XmlDocument doc = new XmlDocument ();
 				doc.Load (uri.ToString ());
@@ -78,7 +79,7 @@ namespace FSpot {
 				ArrayList items = new ArrayList ();
 				XmlNodeList list = doc.SelectNodes ("/rss/channel/item/media:content", ns);
 				foreach (XmlNode item in list) {
-					Uri image_uri = new Uri (item.Attributes ["url"].Value);
+					SafeUri image_uri = new SafeUri (item.Attributes ["url"].Value);
 					System.Console.WriteLine ("flickr uri = {0}", image_uri.ToString ());
 					items.Add (new FileBrowsableItem (image_uri));
 				}
@@ -86,7 +87,7 @@ namespace FSpot {
 				if (list.Count < 1) {
 					list = doc.SelectNodes ("/rss/channel/item/pheed:imgsrc", ns);
 					foreach (XmlNode item in list) {
-						Uri image_uri = new Uri (item.InnerText.Trim ());
+						SafeUri image_uri = new SafeUri (item.InnerText.Trim ());
 						System.Console.WriteLine ("pheed uri = {0}", uri);
 						items.Add (new FileBrowsableItem (image_uri));
 					}
@@ -95,7 +96,7 @@ namespace FSpot {
 				if (list.Count < 1) {
 					list = doc.SelectNodes ("/rss/channel/item/apple:image", ns);
 					foreach (XmlNode item in list) {
-						Uri image_uri = new Uri (item.InnerText.Trim ());
+						SafeUri image_uri = new SafeUri (item.InnerText.Trim ());
 						System.Console.WriteLine ("apple uri = {0}", uri);
 						items.Add (new FileBrowsableItem (image_uri));
 					}
@@ -107,10 +108,10 @@ namespace FSpot {
 		private class DirectoryLoader
 		{
 			UriCollection collection;
-			Uri uri;
+			SafeUri uri;
 			GLib.File file;
 
-			public DirectoryLoader (UriCollection collection, System.Uri uri)
+			public DirectoryLoader (UriCollection collection, SafeUri uri)
 			{
 				this.collection = collection;
 				this.uri = uri;
@@ -127,7 +128,7 @@ namespace FSpot {
 			{
 				List<FileBrowsableItem> items = new List<FileBrowsableItem> ();
 				foreach (GLib.FileInfo info in file.EnumerateChildrenFinish (res)) {
-					Uri i = file.GetChild (info.Name).Uri;
+					SafeUri i = new SafeUri (file.GetChild (info.Name).Uri);
 					FSpot.Utils.Log.Debug ("testing uri = {0}", i);
 					if (FSpot.ImageFile.HasLoader (i))
 						items.Add (new FileBrowsableItem (i));
@@ -144,7 +145,7 @@ namespace FSpot {
 			foreach (var f in files) {
 				if (FSpot.ImageFile.HasLoader (f.FullName)) {
 					Console.WriteLine (f.FullName);
-					items.Add (new FileBrowsableItem (f.FullName));
+					items.Add (new FileBrowsableItem (new SafeUri (f.FullName)));
 				}
 			}
 
diff --git a/src/Util.cs b/src/Util.cs
index d934fbb..99e85a1 100644
--- a/src/Util.cs
+++ b/src/Util.cs
@@ -14,15 +14,16 @@ using System.Collections.Generic;
 using System.IO;
 using System.Text;
 using System;
+using Hyena;
 
 
 namespace FSpot.Utils
 {
 
-	public class UriList : List<Uri> {
+	public class UriList : List<SafeUri> {
 		public UriList (FSpot.IBrowsableItem [] photos) {
 			foreach (FSpot.IBrowsableItem p in photos) {
-				Uri uri;
+				SafeUri uri;
 				try {
 					uri = p.DefaultVersion.Uri;
 				} catch {
@@ -41,7 +42,7 @@ namespace FSpot.Utils
 			
 			foreach (String i in items) {
 				if (!i.StartsWith ("#")) {
-					Uri uri;
+					SafeUri uri;
 					String s = i;
 	
 					if (i.EndsWith ("\r")) {
@@ -50,13 +51,13 @@ namespace FSpot.Utils
 					}
 					
 					try {
-						uri = new Uri (s);
+						uri = new SafeUri (s);
 					} catch {
 #if true //Workaround to bgo 362016 in gnome-screenshot. Remove this hack when gnome 2.6.18 is widely distributed.
 						if (System.Text.RegularExpressions.Regex.IsMatch (s, "^file:/[^/]")) {
 							try {
 								s = "file:///" + s.Substring(6);
-								uri = new Uri (s);
+								uri = new SafeUri (s);
 								Console.WriteLine ("Converted uri from file:/ to >>{0}<<", s);
 							} catch {
 								continue;
@@ -71,23 +72,15 @@ namespace FSpot.Utils
 				}
 			}
 		}
-	
-	/*	public UriList (string [] uris)
-		{	
-			// FIXME this is so lame do real chacking at some point
-			foreach (string str in uris) {
-				AddUnknown (str);
-			}
-		}
-	*/
+
 		public void AddUnknown (string unknown)
 		{
-			Uri uri;
+			SafeUri uri;
 			
 			if (File.Exists (unknown) || Directory.Exists (unknown))
-				uri = UriUtils.PathToFileUri (unknown);
+				uri = new SafeUri (unknown);
 			else 
-				uri = new Uri (unknown);
+				uri = new SafeUri (unknown);
 			
 			Add (uri);
 		}
@@ -121,7 +114,7 @@ namespace FSpot.Utils
 		public override string ToString () {
 			StringBuilder list = new StringBuilder ();
 	
-			foreach (Uri uri in this) {
+			foreach (SafeUri uri in this) {
 				if (uri == null)
 					break;
 	
@@ -133,14 +126,14 @@ namespace FSpot.Utils
 	
 		public string [] ToLocalPaths () {
 			int count = 0;
-			foreach (Uri uri in this) {
+			foreach (SafeUri uri in this) {
 				if (uri.IsFile)
 					count++;
 			}
 			
 			String [] paths = new String [count];
 			count = 0;
-			foreach (Uri uri in this) {
+			foreach (SafeUri uri in this) {
 				if (uri.IsFile)
 					paths[count++] = uri.LocalPath;
 			}
diff --git a/src/Utils/PixbufUtils.cs b/src/Utils/PixbufUtils.cs
index 68ff5d4..ad611ef 100644
--- a/src/Utils/PixbufUtils.cs
+++ b/src/Utils/PixbufUtils.cs
@@ -195,32 +195,7 @@ namespace FSpot.Utils
 			if (pixbuf == null)
 				return null;
 			Pixbuf result = new Pixbuf (pixbuf, 0, 0, pixbuf.Width, pixbuf.Height);
-			CopyThumbnailOptions (pixbuf, result);
 			return result;
 		}
-
-		// 
-		// FIXME this is actually not public api and we should do a verison check,
-		// but frankly I'm irritated that it isn't public so I don't much care.
-		//
-		[DllImport("libgdk_pixbuf-2.0-0.dll")]
-		static extern bool gdk_pixbuf_set_option(IntPtr raw, string key, string value);
-		
-		public static bool SetOption(Gdk.Pixbuf pixbuf, string key, string value)
-		{
-			
-			if (value != null)
-				return gdk_pixbuf_set_option(pixbuf.Handle, key, value);
-			else
-				return false;
-		}
-		
-		public static void CopyThumbnailOptions (Gdk.Pixbuf src, Gdk.Pixbuf dest)
-		{
-			if (src != null && dest != null) {
-				PixbufUtils.SetOption (dest, "tEXt::Thumb::URI", src.GetOption ("tEXt::Thumb::URI"));
-				PixbufUtils.SetOption (dest, "tEXt::Thumb::MTime", src.GetOption ("tEXt::Thumb::MTime"));
-			}
-		}
 	}
 }
diff --git a/src/Utils/RecursiveFileEnumerator.cs b/src/Utils/RecursiveFileEnumerator.cs
index 96ce4a9..cb47ad5 100644
--- a/src/Utils/RecursiveFileEnumerator.cs
+++ b/src/Utils/RecursiveFileEnumerator.cs
@@ -7,19 +7,19 @@ namespace FSpot.Utils
 {
     public class RecursiveFileEnumerator : IEnumerable<File>
     {
-        Uri root;
+        string root;
         bool recurse;
         bool catch_no_permission;
 
-        public RecursiveFileEnumerator (Uri root) : this (root, true, false)
+        public RecursiveFileEnumerator (string root) : this (root, true, false)
         {
         }
 
-        public RecursiveFileEnumerator (Uri root, bool recurse) : this (root, recurse, false)
+        public RecursiveFileEnumerator (string root, bool recurse) : this (root, recurse, false)
         {
         }
 
-        public RecursiveFileEnumerator (Uri root, bool recurse, bool catch_no_permission)
+        public RecursiveFileEnumerator (string root, bool recurse, bool catch_no_permission)
         {
             this.root = root;
             this.recurse = recurse;
diff --git a/src/Widgets/Filmstrip.cs b/src/Widgets/Filmstrip.cs
index acf322d..d1d7431 100644
--- a/src/Widgets/Filmstrip.cs
+++ b/src/Widgets/Filmstrip.cs
@@ -20,6 +20,7 @@ using Gdk;
 using FSpot.Utils;
 using FSpot.Platform;
 using FSpot.Bling;
+using Hyena;
 
 namespace FSpot.Widgets
 {
@@ -291,7 +292,7 @@ namespace FSpot.Widgets
 		}
 
 		FSpot.BrowsablePointer selection;
-		DisposableCache<Uri, Pixbuf> thumb_cache;
+		DisposableCache<SafeUri, Pixbuf> thumb_cache;
 
 		public Filmstrip (FSpot.BrowsablePointer selection) : this (selection, true)
 		{
@@ -305,7 +306,7 @@ namespace FSpot.Widgets
 			this.selection.Collection.Changed += HandleCollectionChanged;
 			this.selection.Collection.ItemsChanged += HandleCollectionItemsChanged;
 			this.squared_thumbs = squared_thumbs;
-			thumb_cache = new DisposableCache<Uri, Pixbuf> (30);
+			thumb_cache = new DisposableCache<SafeUri, Pixbuf> (30);
 			ThumbnailGenerator.Default.OnPixbufLoaded += HandlePixbufLoaded;
 
 			animation = new DoubleAnimation (0, 0, TimeSpan.FromSeconds (1.5), SetPositionCore, new CubicEase (EasingMode.EaseOut));
@@ -547,7 +548,7 @@ namespace FSpot.Widgets
 			QueueDraw ();
 		}
 
-		void HandlePixbufLoaded (ImageLoaderThread pl, Uri uri, int order, Pixbuf p) {
+		void HandlePixbufLoaded (ImageLoaderThread pl, SafeUri uri, int order, Pixbuf p) {
 			if (!thumb_cache.Contains (uri)) {
 				return;
 			}
@@ -612,7 +613,7 @@ namespace FSpot.Widgets
  		protected virtual Pixbuf GetPixbuf (int i, bool highlighted)
 		{
 			Pixbuf current;
-			Uri uri = (selection.Collection [i]).DefaultVersion.Uri;
+			SafeUri uri = (selection.Collection [i]).DefaultVersion.Uri;
 			try {
 				current = PixbufUtils.ShallowCopy (thumb_cache.Get (uri));
 			} catch (IndexOutOfRangeException) {
diff --git a/src/Widgets/FolderTreeView.cs b/src/Widgets/FolderTreeView.cs
index bedc0eb..1b4a132 100644
--- a/src/Widgets/FolderTreeView.cs
+++ b/src/Widgets/FolderTreeView.cs
@@ -17,6 +17,7 @@ using GLib;
 using FSpot;
 using FSpot.Utils;
 
+using Hyena;
 using Mono.Unix;
 
 namespace FSpot.Widgets
@@ -58,7 +59,7 @@ namespace FSpot.Widgets
 				TreePath[] selected_rows = Selection.GetSelectedRows ();
 				
 				foreach (TreePath row in selected_rows)
-					list.Add (folder_tree_model.GetUriByPath (row));
+					list.Add (new SafeUri (folder_tree_model.GetUriByPath (row)));
 				
 				return list;
 			}
diff --git a/src/Widgets/IconView.cs b/src/Widgets/IconView.cs
index 0c635b7..59be723 100644
--- a/src/Widgets/IconView.cs
+++ b/src/Widgets/IconView.cs
@@ -927,8 +927,6 @@ namespace FSpot.Widgets
 						temp_thumbnail = thumbnail.ScaleSimple (region.Width, region.Height,
 								InterpType.Bilinear);
 					}
-
-					FSpot.Utils.PixbufUtils.CopyThumbnailOptions (thumbnail, temp_thumbnail);
 				} else
 					temp_thumbnail = thumbnail;
 
@@ -1381,7 +1379,7 @@ namespace FSpot.Widgets
 			int order = (int) entry.Data;
 
 			if (order >= 0 && order < collection.Count) {
-				System.Uri uri = collection [order].DefaultVersion.Uri;
+				var uri = collection [order].DefaultVersion.Uri;
 
 				if (result == null && !ThumbnailFactory.ThumbnailExists (uri))
 					FSpot.ThumbnailGenerator.Default.Request (uri, 0, 256, 256);
diff --git a/src/Widgets/ImageInfo.cs b/src/Widgets/ImageInfo.cs
index 64c90cd..77e0cbd 100644
--- a/src/Widgets/ImageInfo.cs
+++ b/src/Widgets/ImageInfo.cs
@@ -11,13 +11,14 @@ using Cairo;
 using Gdk;
 using Gtk;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot.Widgets {
 	public class ImageInfo : IDisposable {
 		public Surface Surface;
 		public Gdk.Rectangle Bounds;
 		
-		public ImageInfo (Uri uri)
+		public ImageInfo (SafeUri uri)
 		{
 				using (ImageFile img = ImageFile.Create (uri)) {
 					Pixbuf pixbuf = img.Load ();
diff --git a/src/XmpTagsImporter.cs b/src/XmpTagsImporter.cs
index 30297ba..5d106b7 100644
--- a/src/XmpTagsImporter.cs
+++ b/src/XmpTagsImporter.cs
@@ -19,6 +19,7 @@ using SemWeb;
 using SemWeb.Util;
 using Mono.Unix;
 using FSpot.Utils;
+using Hyena;
 
 namespace FSpot.Xmp {
         internal class XmpTagsImporter {
@@ -271,7 +272,7 @@ namespace FSpot.Xmp {
 #endif
 		}
 		
-		public bool Import (Photo photo, Uri uri, Uri orig_uri)
+		public bool Import (Photo photo, SafeUri uri, SafeUri orig_uri)
 		{
 			XmpFile xmp;
 			



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