f-spot r4137 - in trunk/extensions: . FlickrExport FlickrExport/FlickrNet



Author: sdelcroix
Date: Wed Jul  2 11:21:09 2008
New Revision: 4137
URL: http://svn.gnome.org/viewvc/f-spot?rev=4137&view=rev

Log:
2008-07-02  Stephane Delcroix  <stephane delcroix org>

	* FlickrExport/: update to flickrnet 1.2.5


Added:
   trunk/extensions/FlickrExport/FlickrNet/ActivityEvent.cs
   trunk/extensions/FlickrExport/FlickrNet/ActivityItem.cs
   trunk/extensions/FlickrExport/FlickrNet/ApiKeyRequiredException.cs
   trunk/extensions/FlickrExport/FlickrNet/AuthenticationRequiredException.cs
   trunk/extensions/FlickrExport/FlickrNet/FlickrApiException.cs
   trunk/extensions/FlickrExport/FlickrNet/FlickrWebException.cs
   trunk/extensions/FlickrExport/FlickrNet/ResponseXmlException.cs
   trunk/extensions/FlickrExport/FlickrNet/SafeNativeMethods.cs
   trunk/extensions/FlickrExport/FlickrNet/SignatureRequiredException.cs
Modified:
   trunk/extensions/ChangeLog
   trunk/extensions/FlickrExport/FlickrExport.addin.xml
   trunk/extensions/FlickrExport/FlickrExport.cs
   trunk/extensions/FlickrExport/FlickrNet/AssemblyInfo.cs
   trunk/extensions/FlickrExport/FlickrNet/BoundaryBox.cs
   trunk/extensions/FlickrExport/FlickrNet/Cache.cs
   trunk/extensions/FlickrExport/FlickrNet/Comments.cs
   trunk/extensions/FlickrExport/FlickrNet/Enums.cs
   trunk/extensions/FlickrExport/FlickrNet/ExifPhoto.cs
   trunk/extensions/FlickrExport/FlickrNet/Flickr.cs
   trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationManager.cs
   trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationSettings.cs
   trunk/extensions/FlickrExport/FlickrNet/FlickrException.cs
   trunk/extensions/FlickrExport/FlickrNet/GeoAccuracy.cs
   trunk/extensions/FlickrExport/FlickrNet/GroupSearchResults.cs
   trunk/extensions/FlickrExport/FlickrNet/License.txt
   trunk/extensions/FlickrExport/FlickrNet/LockFile.cs
   trunk/extensions/FlickrExport/FlickrNet/Makefile.am
   trunk/extensions/FlickrExport/FlickrNet/PartialSearchOptions.cs
   trunk/extensions/FlickrExport/FlickrNet/PersistentCache.cs
   trunk/extensions/FlickrExport/FlickrNet/Person.cs
   trunk/extensions/FlickrExport/FlickrNet/Photo.cs
   trunk/extensions/FlickrExport/FlickrNet/PhotoInfo.cs
   trunk/extensions/FlickrExport/FlickrNet/PhotoSearchExtras.cs
   trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOptions.cs
   trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOrder.cs
   trunk/extensions/FlickrExport/FlickrNet/PhotoSets.cs
   trunk/extensions/FlickrExport/FlickrNet/Photos.cs
   trunk/extensions/FlickrExport/FlickrNet/Response.cs
   trunk/extensions/FlickrExport/FlickrNet/Tags.cs
   trunk/extensions/FlickrExport/FlickrNet/Uploader.cs
   trunk/extensions/FlickrExport/FlickrNet/User.cs
   trunk/extensions/FlickrExport/FlickrNet/Utils.cs
   trunk/extensions/FlickrExport/FlickrRemote.cs

Modified: trunk/extensions/FlickrExport/FlickrExport.addin.xml
==============================================================================
--- trunk/extensions/FlickrExport/FlickrExport.addin.xml	(original)
+++ trunk/extensions/FlickrExport/FlickrExport.addin.xml	Wed Jul  2 11:21:09 2008
@@ -1,5 +1,5 @@
 <Addin namespace="FSpot"
-	version="0.4.3.2"
+	version="0.4.3.3"
 	name="Flickr Export"
 	description="This extension allows you to export your photos to Flickr and 23hq."
 	author="F-Spot team"

Modified: trunk/extensions/FlickrExport/FlickrExport.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrExport.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrExport.cs	Wed Jul  2 11:21:09 2008
@@ -273,7 +273,7 @@
 				fr = new FlickrRemote (token, current_service);
 				fr.TryWebLogin();
 				CurrentState = State.Connected;
-			} catch (FlickrException e) {
+			} catch (FlickrApiException e) {
 				if (e.Code == 98) {
 					Logout ();
 					Login ();

Added: trunk/extensions/FlickrExport/FlickrNet/ActivityEvent.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/ActivityEvent.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,110 @@
+using System;
+using System.Xml;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Summary description for ActivityEvent.
+	/// </summary>
+	public class ActivityEvent
+	{
+		private ActivityEventType _type;
+		private string _userId;
+		private string _userName;
+		private DateTime _dateAdded;
+		private string _content;
+
+		/// <summary>
+		/// THe <see cref="ActivityEventType"/> of the event, either Comment or Note.
+		/// </summary>
+		public ActivityEventType EventType
+		{
+			get { return _type; }
+		}
+
+		/// <summary>
+		/// The user id of the user who made the comment or note.
+		/// </summary>
+		public string UserId
+		{
+			get { return _userId; }
+		}
+
+		/// <summary>
+		/// The screen name of the user who made the comment or note.
+		/// </summary>
+		public string UserName
+		{
+			get { return _userName; }
+		}
+
+		/// <summary>
+		/// The date the note or comment was added.
+		/// </summary>
+		public DateTime DateAdded
+		{
+			get { return _dateAdded; }
+		}
+
+		/// <summary>
+		/// The text of the note or comment.
+		/// </summary>
+		public string Value
+		{
+			get { return _content; }
+		}
+
+		internal ActivityEvent(XmlNode eventNode)
+		{
+			XmlNode node;
+
+			node = eventNode.Attributes.GetNamedItem("type");
+			if( node == null ) 
+				_type = ActivityEventType.Unknown;
+			else if( node.Value == "comment" )
+				_type = ActivityEventType.Comment;
+			else if( node.Value == "note" )
+				_type = ActivityEventType.Note;
+			else if( node.Value == "fave" )
+				_type = ActivityEventType.Favourite;
+			else
+				_type = ActivityEventType.Unknown;
+
+			node = eventNode.Attributes.GetNamedItem("user");
+			if( node != null ) _userId = node.Value;
+
+			node = eventNode.Attributes.GetNamedItem("username");
+			if( node != null ) _userName = node.Value;
+
+			node = eventNode.Attributes.GetNamedItem("dateadded");
+			if( node != null ) _dateAdded = Utils.UnixTimestampToDate(node.Value);
+
+			node = eventNode.FirstChild;
+			if( node != null && node.NodeType == XmlNodeType.Text ) _content = node.Value;
+
+		}
+	}
+
+	/// <summary>
+	/// The type of the <see cref="ActivityEvent"/>.
+	/// </summary>
+	public enum ActivityEventType
+	{
+		/// <summary>
+		/// The event type was not specified, or was a new unsupported type.
+		/// </summary>
+		Unknown,
+		/// <summary>
+		/// The event was a comment.
+		/// </summary>
+		Comment,
+		/// <summary>
+		/// The event was a note.
+		/// </summary>
+		Note,
+		/// <summary>
+		/// The event is a favourite.
+		/// </summary>
+		Favourite
+	}
+}

Added: trunk/extensions/FlickrExport/FlickrNet/ActivityItem.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/ActivityItem.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,312 @@
+using System;
+using System.Xml;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Activity class used for <see cref="Flickr.ActivityUserPhotos()"/>
+	/// and <see cref="Flickr.ActivityUserComments"/>.
+	/// </summary>
+	public class ActivityItem
+	{
+		private ActivityItemType _activityType;
+		private string _id;
+		private string _secret;
+		private string _server;
+		private string _farm;
+		private int _commentsNew;
+		private int _commentsOld;
+		private int _comments;
+		private string _ownerId;
+		private int _more;
+		private int _views;
+
+		// Photoset specific
+		private int _photos = -1;
+		private string _primaryId = null;
+
+		// Photo specific
+		private int _notesNew = -1;
+		private int _notesOld = -1;
+		private int _notes = -1;
+		private int _favs = -1;
+
+		private string _title;
+		private ActivityEvent[] _events;
+
+		/// <summary>
+		/// The <see cref="ActivityItemType"/> of the item.
+		/// </summary>
+		public ActivityItemType ItemType
+		{
+			get { return _activityType; }
+		}
+
+		/// <summary>
+		/// The ID of either the photoset or the photo.
+		/// </summary>
+		public string Id
+		{
+			get { return _id; }
+		}
+
+		/// <summary>
+		/// The secret for either the photo, or the primary photo for the photoset.
+		/// </summary>
+		public string Secret
+		{
+			get { return _secret; }
+		}
+
+		/// <summary>
+		/// The server for either the photo, or the primary photo for the photoset.
+		/// </summary>
+		public string Server
+		{
+			get { return _server; }
+		}
+
+		/// <summary>
+		/// The server farm for either the photo, or the primary photo for the photoset.
+		/// </summary>
+		public string Farm
+		{
+			get { return _farm; }
+		}
+
+		/// <summary>
+		/// The title of the photoset or photo.
+		/// </summary>
+		public string Title
+		{
+			get { return _title; }
+		}
+
+		/// <summary>
+		/// The number of new comments within the given time frame. 
+		/// </summary>
+		/// <remarks>
+		/// Only applicable for <see cref="Flickr.ActivityUserPhotos()"/>.
+		/// </remarks>
+		public int CommentsNew
+		{
+			get { return _commentsNew; }
+		}
+
+		/// <summary>
+		/// The number of old comments within the given time frame. 
+		/// </summary>
+		/// <remarks>
+		/// Only applicable for <see cref="Flickr.ActivityUserPhotos()"/>.
+		/// </remarks>
+		public int CommentsOld
+		{
+			get { return _commentsOld; }
+		}
+
+		/// <summary>
+		/// The number of comments on the item. 
+		/// </summary>
+		/// <remarks>
+		/// Only applicable for <see cref="Flickr.ActivityUserComments"/>.
+		/// </remarks>
+		public int Comments
+		{
+			get { return _comments; }
+		}
+
+		/// <summary>
+		/// Gets the number of views for this photo or photoset.
+		/// </summary>
+		public int Views
+		{
+			get { return _views; }
+		}
+
+		/// <summary>
+		/// You want more! You got it!
+		/// </summary>
+		/// <remarks>
+		/// Actually, not sure what this it for!
+		/// </remarks>
+		public int More
+		{
+			get { return _more; }
+		}
+
+		/// <summary>
+		/// The user id of the owner of this item.
+		/// </summary>
+		public string OwnerId
+		{
+			get { return _ownerId; }
+		}
+
+		/// <summary>
+		/// If the type is a photoset then this contains the number of photos in the set. Otherwise returns -1.
+		/// </summary>
+		public int Photos
+		{
+			get { return _photos; }
+		}
+
+		/// <summary>
+		/// If this is a photoset then returns the primary photo id, otherwise will be null (<code>Nothing</code> in VB.Net).
+		/// </summary>
+		public string PrimaryPhotoId
+		{
+			get { return _primaryId; }
+		}
+
+		/// <summary>
+		/// The number of new notes within the given time frame. 
+		/// </summary>
+		/// <remarks>
+		/// Only applicable for photos and when calling <see cref="Flickr.ActivityUserPhotos()"/>.
+		/// </remarks>
+		public int NotesNew
+		{
+			get { return _notesNew; }
+		}
+
+		/// <summary>
+		/// The number of old notes within the given time frame. 
+		/// </summary>
+		/// <remarks>
+		/// Only applicable for photos and when calling <see cref="Flickr.ActivityUserPhotos()"/>.
+		/// </remarks>
+		public int NotesOld
+		{
+			get { return _notesOld; }
+		}
+
+		/// <summary>
+		/// The number of comments on the photo.
+		/// </summary>
+		/// <remarks>
+		/// Only applicable for photos and when calling <see cref="Flickr.ActivityUserComments"/>.
+		/// </remarks>
+		public int Notes
+		{
+			get { return _notes; }
+		}
+
+		/// <summary>
+		/// If the type is a photo then this contains the number of favourites in the set. Otherwise returns -1.
+		/// </summary>
+		public int Favourites
+		{
+			get { return _favs; }
+		}
+
+		/// <summary>
+		/// The events that comprise this activity item.
+		/// </summary>
+		public ActivityEvent[] Events
+		{
+			get { return _events; }
+		}
+
+		internal ActivityItem(XmlNode itemNode)
+		{
+			XmlNode node;
+
+			node = itemNode.Attributes.GetNamedItem("type");
+
+			if( node == null )
+				_activityType = ActivityItemType.Unknown;
+			else if( node.Value == "photoset" )
+				_activityType = ActivityItemType.Photoset;
+			else if( node.Value == "photo" )
+				_activityType = ActivityItemType.Photo;
+			else
+				_activityType = ActivityItemType.Unknown;
+
+			node = itemNode.Attributes.GetNamedItem("owner");
+			if( node != null ) _ownerId = node.Value;
+
+			node = itemNode.Attributes.GetNamedItem("id");
+			if( node != null ) _id = node.Value;
+
+			node = itemNode.Attributes.GetNamedItem("secret");
+			if( node != null ) _secret = node.Value;
+
+			node = itemNode.Attributes.GetNamedItem("server");
+			if( node != null ) _server = node.Value;
+
+			node = itemNode.Attributes.GetNamedItem("farm");
+			if( node != null ) _farm = node.Value;
+
+			node = itemNode.Attributes.GetNamedItem("commentsnew");
+			if( node != null ) _commentsNew = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("commentsold");
+			if( node != null ) _commentsOld = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("comments");
+			if( node != null ) _comments = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("more");
+			if( node != null ) _more = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("views");
+			if( node != null ) _views = Convert.ToInt32(node.Value);
+
+			node = itemNode.SelectSingleNode("title");
+			if( node != null ) _title = node.InnerText;
+
+			XmlNodeList list = itemNode.SelectNodes("activity/event");
+			
+			_events = new ActivityEvent[list.Count];
+
+			for(int i = 0; i < _events.Length; i++)
+			{
+				node = list[i];
+				_events[i] = new ActivityEvent(node);
+			}
+
+			// Photoset specific
+			// Photos, PrimaryPhotoId
+
+			node = itemNode.Attributes.GetNamedItem("photos");
+			if( node != null ) _photos = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("primary");
+			if( node != null ) _primaryId = node.Value;
+
+			// Photo specific
+			// NodesNew and NodesOld, Favourites
+
+			node = itemNode.Attributes.GetNamedItem("notesnew");
+			if( node != null ) _notesNew = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("notesold");
+			if( node != null ) _notesOld = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("notes");
+			if( node != null ) _notes = Convert.ToInt32(node.Value);
+
+			node = itemNode.Attributes.GetNamedItem("faves");
+			if( node != null ) _favs = Convert.ToInt32(node.Value);
+		}
+	}
+
+	/// <summary>
+	/// The type of the <see cref="ActivityItem"/>.
+	/// </summary>
+	public enum ActivityItemType
+	{
+		/// <summary>
+		/// The type is unknown, either not set of a new unsupported type.
+		/// </summary>
+		Unknown,
+		/// <summary>
+		/// The activity item is on a photoset.
+		/// </summary>
+		Photoset,
+		/// <summary>
+		/// The activitiy item is on a photo.
+		/// </summary>
+		Photo
+	}
+}

Added: trunk/extensions/FlickrExport/FlickrNet/ApiKeyRequiredException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/ApiKeyRequiredException.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,17 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Exception thrown is no API key is supplied.
+	/// </summary>
+	public class ApiKeyRequiredException : FlickrException
+	{
+		/// <summary>
+		/// Default constructor.
+		/// </summary>
+		public ApiKeyRequiredException() : base("API Key is required for all method calls")
+		{
+		}
+	}
+}

Modified: trunk/extensions/FlickrExport/FlickrNet/AssemblyInfo.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/AssemblyInfo.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/AssemblyInfo.cs	Wed Jul  2 11:21:09 2008
@@ -15,7 +15,7 @@
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("Sam Judson")]
 [assembly: AssemblyProduct("Flickr .Net Api Library")]
-[assembly: AssemblyCopyright("http://www.gnu.org/copyleft/lesser.html";)]
+[assembly: AssemblyCopyright("See website http://www.wackylabs.net/flickr";)]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 
@@ -30,7 +30,7 @@
 // You can specify all the values or you can default the Revision and Build Numbers 
 // by using the '*' as shown below:
 
-[assembly: AssemblyVersion("2.1.2.*")]
+[assembly: AssemblyVersion("2.1.5.*")]
 
 //
 // In order to sign your assembly you must specify a key to use. Refer to the 
@@ -57,12 +57,11 @@
 //   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
 //       documentation for more information on this.
 //
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("FlickrNet.snk")]
-//[assembly: AssemblyKeyName("")]
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyName("")]
 
 [assembly: AllowPartiallyTrustedCallers()]
 [assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
 
 [assembly: CLSCompliantAttribute(true)]
-//[assembly: ComVisible(false)]
+[assembly: ComVisible(false)]

Added: trunk/extensions/FlickrExport/FlickrNet/AuthenticationRequiredException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/AuthenticationRequiredException.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,14 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Exception thrown when method requires authentication but no authentication token is supplied.
+	/// </summary>
+	public class AuthenticationRequiredException : FlickrException
+	{
+		internal AuthenticationRequiredException() : base("Method requires authentication but no token supplied.")
+		{
+		}
+	}
+}

Modified: trunk/extensions/FlickrExport/FlickrNet/BoundaryBox.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/BoundaryBox.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/BoundaryBox.cs	Wed Jul  2 11:21:09 2008
@@ -1,5 +1,4 @@
 using System;
-using System.Drawing;
 
 namespace FlickrNet
 {
@@ -7,6 +6,7 @@
 	/// <summary>
 	/// Summary description for BoundaryBox.
 	/// </summary>
+	[Serializable]
 	public class BoundaryBox
 	{
 		private GeoAccuracy _accuracy = GeoAccuracy.Street;
@@ -43,7 +43,7 @@
 			set 
 			{
 				if( value < -90 || value > 90 ) 
-					throw new ArgumentOutOfRangeException("MinimumLatitude", value, "Must be between -90 and 90");
+					throw new ArgumentOutOfRangeException("MinimumLatitude", "Must be between -90 and 90");
 				_isSet = true; _minimumLat = value; 
 			}
 		}
@@ -56,7 +56,7 @@
 			get { return _minimumLon; }
 			set { 
 				if( value < -180 || value > 180 ) 
-					throw new ArgumentOutOfRangeException("MinimumLongitude", value, "Must be between -180 and 180");
+					throw new ArgumentOutOfRangeException("MinimumLongitude", "Must be between -180 and 180");
 				_isSet = true; _minimumLon = value; 
 			}
 		}
@@ -70,7 +70,7 @@
 			set 
 			{
 				if( value < -90 || value > 90 ) 
-					throw new ArgumentOutOfRangeException("MaximumLatitude", value, "Must be between -90 and 90");
+					throw new ArgumentOutOfRangeException("MaximumLatitude", "Must be between -90 and 90");
 				_isSet = true; _maximumLat = value; 
 			}
 		}
@@ -84,7 +84,7 @@
 			set 
 			{
 				if( value < -180 || value > 180 ) 
-					throw new ArgumentOutOfRangeException("MaximumLongitude", value, "Must be between -180 and 180");
+					throw new ArgumentOutOfRangeException("MaximumLongitude", "Must be between -180 and 180");
 				_isSet = true; _maximumLon = value; 
 			}
 		}

Modified: trunk/extensions/FlickrExport/FlickrNet/Cache.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Cache.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Cache.cs	Wed Jul  2 11:21:09 2008
@@ -72,8 +72,10 @@
 		{
 			get
 			{
+#if !WindowsCE
 				if( _cacheDisabled == Tristate.Null && FlickrConfigurationManager.Settings != null )
 					_cacheDisabled = (FlickrConfigurationManager.Settings.CacheDisabled?Tristate.True:Tristate.False);
+#endif
 				
 				if( _cacheDisabled == Tristate.Null ) _cacheDisabled = Tristate.False;
 
@@ -91,13 +93,19 @@
 		{
 			get 
 			{ 
+#if !WindowsCE
 				if( _cacheLocation == null && FlickrConfigurationManager.Settings != null )
 					_cacheLocation = FlickrConfigurationManager.Settings.CacheLocation;
+#endif
 				if( _cacheLocation == null )
 				{
 					try
 					{
+#if !WindowsCE
 						_cacheLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "FlickrNet");
+#else
+                        _cacheLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "FlickrNetCache");
+#endif
 					}
 					catch(System.Security.SecurityException)
 					{
@@ -117,21 +125,19 @@
 			}
 		}
 
+		// Default cache size is set to 50MB
+        private static long _cacheSizeLimit = 52428800;
+        private static long _cacheSize;
+
 		internal static long CacheSizeLimit
 		{
 			get 
 			{
-				if( CacheSettings.ContainsKey("SizeLimit") )
-					return (long)CacheSettings["SizeLimit"];
-				else
-					return 50 * 1024 * 1024;
+                return _cacheSizeLimit;
 			}
 			set 
-			{ 
-				if( CacheSettings.ContainsKey("SizeLimit") )
-					CacheSettings["SizeLimit"] = value;
-				else
-					CacheSettings.Add("SizeLimit", value);
+			{
+                _cacheSizeLimit = value;
 			}
 		}
 
@@ -139,17 +145,11 @@
 		{
 			get 
 			{
-				if( CacheSettings.ContainsKey("CurrentSize") )
-					return (long)CacheSettings["CurrentSize"];
-				else
-					return 0;
+                return _cacheSize;
 			}
 			set 
-			{ 
-				if( CacheSettings.ContainsKey("CurrentSize") )
-					CacheSettings["CurrentSize"] = value;
-				else
-					CacheSettings.Add("CurrentSize", value);
+			{
+                _cacheSize = value;
 			}
 		}
 
@@ -166,79 +166,6 @@
 			set { _cachetimeout = value; }
 		}
 		
-		private static Hashtable _cacheSettings;
-
-		private static Hashtable CacheSettings
-		{
-			get
-			{
-				lock(lockObject)
-				{
-					if( _cacheSettings == null )
-						LoadSettings();
-					return _cacheSettings;
-				}
-			}
-		}
-
-		private static void SaveSettings()
-		{
-			System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
-
-			System.IO.Stream stream;
-
-			lock(CacheSettings.SyncRoot)
-			{
-				if( CacheLocation == null ) return;
-
-				stream = new FileStream(Path.Combine(CacheLocation, "cacheSettings.bin"), FileMode.OpenOrCreate, FileAccess.Write);
-				try
-				{
-					formatter.Serialize(stream, CacheSettings);
-				}
-				finally
-				{
-					stream.Close();
-				}
-			}
-		}
-
-		private static void LoadSettings()
-		{
-			if( !Directory.Exists(CacheLocation) ) Directory.CreateDirectory(CacheLocation);
-
-			System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
-
-			System.IO.Stream stream = null;
-
-			if( CacheLocation != null ) 
-			{
-				stream = new FileStream(Path.Combine(CacheLocation, "cacheSettings.bin"), FileMode.OpenOrCreate);
-			}
-
-			if( stream == null )
-			{
-				_cacheSettings = new Hashtable();
-				return;
-			}
-			try
-			{
-				_cacheSettings = (Hashtable)formatter.Deserialize(stream);
-			}
-			catch(InvalidCastException)
-			{
-				_cacheSettings = new Hashtable();
-			}
-			catch(System.Runtime.Serialization.SerializationException)
-			{
-				_cacheSettings = new Hashtable();
-			}
-			finally
-			{
-				stream.Close();
-			}
-		}
-
 		internal static void FlushCache(string url)
 		{
 			Responses[url] = null;

Modified: trunk/extensions/FlickrExport/FlickrNet/Comments.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Comments.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Comments.cs	Wed Jul  2 11:21:09 2008
@@ -109,7 +109,7 @@
 			if( node.Attributes["authorname"] != null )
 				_authorUserName = node.Attributes["authorname"].Value;
 			if( node.Attributes["permalink"] != null )
-				_permaLink = new Uri(node.Attributes["permalink"].Value, true);
+				_permaLink = new Uri(node.Attributes["permalink"].Value);
 			if( node.Attributes["datecreate"] != null )
 				_dateCreated = Utils.UnixTimestampToDate(node.Attributes["datecreate"].Value);
 			if( node.InnerXml.Length > 0 )

Modified: trunk/extensions/FlickrExport/FlickrNet/Enums.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Enums.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Enums.cs	Wed Jul  2 11:21:09 2008
@@ -29,6 +29,7 @@
 	/// <summary>
 	/// Used to specify where all tags must be matched or any tag to be matched.
 	/// </summary>
+	[Serializable]
 	public enum TagMode
 	{
 		/// <summary>
@@ -49,10 +50,99 @@
 		Boolean
 	}
 
+	/// <summary>
+	/// What type of content is the upload representing.
+	/// </summary>
+	[Serializable]
+	public enum ContentType
+	{
+		/// <summary>
+		/// No content type specified.
+		/// </summary>
+		None = 0,
+		/// <summary>
+		/// For normal photographs.
+		/// </summary>
+		Photo = 1,
+		/// <summary>
+		/// For screenshots.
+		/// </summary>
+		Screenshot = 2,
+		/// <summary>
+		/// For other uploads, such as artwork.
+		/// </summary>
+		Other = 3
+	}
+
+	/// <summary>
+	/// Safety level of the photographic image.
+	/// </summary>
+	[Serializable]
+	public enum SafetyLevel
+	{
+		/// <summary>
+		/// No safety level specified.
+		/// </summary>
+		None = 0,
+		/// <summary>
+		/// Very safe (suitable for a global family audience).
+		/// </summary>
+		Safe = 1,
+		/// <summary>
+		/// Moderate (the odd articstic nude is ok, but thats the limit).
+		/// </summary>
+		Moderate = 2,
+		/// <summary>
+		/// Restricted (suitable for over 18s only).
+		/// </summary>
+		Restricted = 3
+	}
+
+	/// <summary>
+	/// Determines weither the photo is visible in public searches. The default is 1, Visible.
+	/// </summary>
+	[Serializable]
+	public enum HiddenFromSearch
+	{
+		/// <summary>
+		/// No preference specified, defaults to your preferences on Flickr.
+		/// </summary>
+		None = 0,
+		/// <summary>
+		/// Photo is visible to public searches.
+		/// </summary>
+		Visible = 1,
+		/// <summary>
+		/// photo is hidden from public searches.
+		/// </summary>
+		Hidden = 2
+	}
+
+
+	/// <summary>
+	/// Used to specify where all tags must be matched or any tag to be matched.
+	/// </summary>
+	[Serializable]
+	public enum MachineTagMode
+	{
+		/// <summary>
+		/// No tag mode specified.
+		/// </summary>
+		None,
+		/// <summary>
+		/// Any tag must match, but not all.
+		/// </summary>
+		AnyTag,
+		/// <summary>
+		/// All tags must be found.
+		/// </summary>
+		AllTags
+	}
 
 	/// <summary>
 	/// When searching for photos you can filter on the privacy of the photos.
 	/// </summary>
+	[Serializable]
 	public enum PrivacyFilter
 	{
 		/// <summary>
@@ -64,13 +154,13 @@
 		/// </summary>
 		PublicPhotos = 1,
 		/// <summary>
-		/// Show photos which are marked as private but viewable by family contacts.
+		/// Show photos which are marked as private but viewable by friends.
 		/// </summary>
-		PrivateVisibleToFamily = 2,
+		PrivateVisibleToFriends = 2,
 		/// <summary>
-		/// Show photos which are marked as private but viewable by friends.
+		/// Show photos which are marked as private but viewable by family contacts.
 		/// </summary>
-		PrivateVisibleToFriends = 3,
+		PrivateVisibleToFamily = 3,
 		/// <summary>
 		/// Show photos which are marked as private but viewable by friends and family contacts.
 		/// </summary>
@@ -84,6 +174,7 @@
 	/// <summary>
 	/// An enumeration defining who can add comments.
 	/// </summary>
+	[Serializable]
 	public enum PermissionComment
 	{
 		/// <summary>

Modified: trunk/extensions/FlickrExport/FlickrNet/ExifPhoto.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/ExifPhoto.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/ExifPhoto.cs	Wed Jul  2 11:21:09 2008
@@ -10,7 +10,7 @@
 	[Serializable]
 	public class ExifPhoto
 	{
-		internal ExifPhoto(string photoId, string secret, int server, ExifTag[] array)
+		internal ExifPhoto(string photoId, string secret, string server, ExifTag[] array)
 		{
 			_photoId = photoId;
 			_secret = secret;
@@ -20,7 +20,7 @@
 
 		private string _photoId;
 		private string _secret;
-		private int _server;
+		private string _server;
 		private ExifTag[] _tagCollection;
 
 		/// <summary>
@@ -42,7 +42,7 @@
 		/// <summary>
 		/// The server number for the photo.
 		/// </summary>
-		public int Server
+		public string Server
 		{
 			get { return _server; }
 		}

Modified: trunk/extensions/FlickrExport/FlickrNet/Flickr.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Flickr.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Flickr.cs	Wed Jul  2 11:21:09 2008
@@ -40,7 +40,9 @@
 		#endregion
 
 		#region [ Private Variables ]
+#if !WindowsCE
 		private static bool _isServiceSet = false;
+#endif
 		private static SupportedService _defaultService = SupportedService.Flickr;
 
 		private SupportedService _service = SupportedService.Flickr;
@@ -51,36 +53,36 @@
 		}
 
 		private string[] _baseUrl = new string[] { 
-									"http://api.flickr.com/services/rest/";, 
-									"http://beta.zooomr.com/bluenote/api/rest";,
-									"http://www.23hq.com/services/rest/"};
+															"http://api.flickr.com/services/rest/";, 
+															"http://beta.zooomr.com/bluenote/api/rest";,
+															"http://www.23hq.com/services/rest/"};
 
 		private string UploadUrl
 		{
 			get { return _uploadUrl[(int)_service]; }
 		}
 		private static string[] _uploadUrl = new string[] {
-									"http://api.flickr.com/services/upload/";,
-									"http://beta.zooomr.com/bluenote/api/upload";,
-									"http://www.23hq.com/services/upload/"};
+															  "http://api.flickr.com/services/upload/";,
+															  "http://beta.zooomr.com/bluenote/api/upload";,
+															  "http://www.23hq.com/services/upload/"};
 
 		private string ReplaceUrl
 		{
 			get { return _replaceUrl[(int)_service]; }
 		}
 		private static string[] _replaceUrl = new string[] {
-									"http://api.flickr.com/services/replace/";,
-									"http://beta.zooomr.com/bluenote/api/replace";,
-									"http://www.23hq.com/services/replace/"};
+															   "http://api.flickr.com/services/replace/";,
+															   "http://beta.zooomr.com/bluenote/api/replace";,
+															   "http://www.23hq.com/services/replace/"};
 
 		private string AuthUrl
 		{
 			get { return _authUrl[(int)_service]; }
 		}
 		private static string[] _authUrl = new string[] {
-									"http://www.flickr.com/services/auth/";,
-									"http://beta.zooomr.com/auth/";,
-									"http://www.23hq.com/services/auth/"};
+															   "http://www.flickr.com/services/auth/";,
+															   "http://beta.zooomr.com/auth/";,
+															   "http://www.23hq.com/services/auth/"};
 
 		private string _apiKey;
 		private string _apiToken;
@@ -208,14 +210,22 @@
 		{
 			get 
 			{
+#if !WindowsCE
 				if( !_isServiceSet && FlickrConfigurationManager.Settings != null )
 				{
 					_defaultService = FlickrConfigurationManager.Settings.Service;
 					_isServiceSet = true;
 				}
-				return _defaultService;
+#endif
+                return _defaultService;
+			}
+			set
+			{
+				_defaultService = value;
+#if !WindowsCE
+				_isServiceSet = true;
+#endif
 			}
-			set { _defaultService = value; _isServiceSet = true; }
 		}
 
 		/// <summary>
@@ -223,8 +233,17 @@
 		/// </summary>
 		public SupportedService CurrentService
 		{
-			get { return _service; }
-			set { _service = value; }
+			get 
+			{ 
+				return _service; 
+			}
+			set 
+			{
+				_service = value; 
+#if !WindowsCE
+				if( _service == SupportedService.Zooomr ) ServicePointManager.Expect100Continue = false;
+#endif
+			}
 		}
 
 		/// <summary>
@@ -307,8 +326,9 @@
 		/// Constructor loads configuration settings from app.config or web.config file if they exist.
 		/// </summary>
 		public Flickr()
-		{
-			FlickrConfigurationSettings settings = FlickrConfigurationManager.Settings;
+        {
+#if !WindowsCE
+            FlickrConfigurationSettings settings = FlickrConfigurationManager.Settings;
 			if( settings == null ) return;
 
 			if( settings.CacheSize != 0 ) CacheSizeLimit = settings.CacheSize;
@@ -316,9 +336,8 @@
 			ApiKey = settings.ApiKey;
 			AuthToken = settings.ApiToken;
 			ApiSecret = settings.SharedSecret;
-			CurrentService = DefaultService;
 
-			if( settings.IsProxyDefined )
+            if (settings.IsProxyDefined)
 			{
 				Proxy = new WebProxy();
 				Proxy.Address = new Uri("http://"; + settings.ProxyIPAddress + ":" + settings.ProxyPort);
@@ -343,6 +362,10 @@
 					// Capture SecurityException for when running in a Medium Trust environment.
 				}
 			}
+
+#endif
+
+            CurrentService = DefaultService;
 		}
 
 		/// <summary>
@@ -384,21 +407,44 @@
 		/// the details are not found within the cache.
 		/// </summary>
 		/// <param name="url">The URL to download.</param>
+		/// <param name="variables">The query string parameters to be added to the end of the URL.</param>
 		/// <returns>A <see cref="FlickrNet.Response"/> object.</returns>
-		private string DoGetResponse(string url)
+		/// <remarks>If the final length of the URL would be greater than 2000 characters 
+		/// then they are sent as part of the body instead.</remarks>
+		private string DoGetResponse(string url, string variables)
 		{
 			HttpWebRequest req = null;
 			HttpWebResponse res = null;
 
+			if( variables.Length < 2000 )
+			{
+				url += "?" + variables;
+				variables = "";
+			}
+
 			// Initialise the web request
 			req = (HttpWebRequest)HttpWebRequest.Create(url);
 			req.Method = CurrentService==SupportedService.Zooomr?"GET":"POST";
-			if( req.Method == "POST" ) req.ContentLength = 0;
-			//req.Method = "POST";
-			req.UserAgent = UserAgent;
+
+            if (req.Method == "POST") req.ContentLength = variables.Length;
+
+            req.UserAgent = UserAgent;
 			if( Proxy != null ) req.Proxy = Proxy;
 			req.Timeout = HttpTimeout;
 			req.KeepAlive = false;
+            if (variables.Length > 0)
+            {
+                req.ContentType = "application/x-www-form-urlencoded";
+                StreamWriter sw = new StreamWriter(req.GetRequestStream());
+                sw.Write(variables);
+                sw.Close();
+            }
+            else
+            {
+                // This is needed in the Compact Framework
+                // See for more details: http://msdn2.microsoft.com/en-us/library/1afx2b0f.aspx
+                req.GetRequestStream().Close();
+            }
 
 			try
 			{
@@ -412,10 +458,10 @@
 					HttpWebResponse res2 = (HttpWebResponse)ex.Response;
 					if( res2 != null )
 					{
-						throw new FlickrException((int)res2.StatusCode, res2.StatusDescription);
+						throw new FlickrWebException(String.Format("HTTP Error {0}, {1}", (int)res2.StatusCode, res2.StatusDescription), ex);
 					}
 				}
-				throw new FlickrException(9999, ex.Message);
+				throw new FlickrWebException(ex.Message, ex);
 			}
 
 			string responseString = string.Empty;
@@ -454,14 +500,14 @@
 					HttpWebResponse res2 = (HttpWebResponse)ex.Response;
 					if( res2 != null )
 					{
-						throw new FlickrException((int)res2.StatusCode, res2.StatusDescription);
+						throw new FlickrWebException(String.Format("HTTP Error while downloading photo: {0}, {1}", (int)res2.StatusCode, res2.StatusDescription), ex);
 					}
 				}
 				else if( ex.Status == WebExceptionStatus.Timeout )
 				{
-					throw new FlickrException(301, "Request time-out");
+					throw new FlickrWebException("The request timed-out", ex);
 				}
-				throw new FlickrException(9999, "Picture download failed (" + ex.Message + ")");
+				throw new FlickrWebException("Picture download failed (" + ex.Message + ")", ex);
 			}
 
 			return res.GetResponseStream();
@@ -486,11 +532,13 @@
 
 		private Response GetResponse(Hashtable parameters, TimeSpan cacheTimeout)
 		{
+			CheckApiKey();
+
 			// Calulate URL 
-			StringBuilder UrlStringBuilder = new StringBuilder(BaseUrl, 2 * 1024);
-			StringBuilder HashStringBuilder = new StringBuilder(_sharedSecret, 2 * 1024);
+			string url = BaseUrl;
 
-			UrlStringBuilder.Append("?");
+            StringBuilder UrlStringBuilder = new StringBuilder("", 2 * 1024);
+            StringBuilder HashStringBuilder = new StringBuilder(_sharedSecret, 2 * 1024);
 
 			parameters["api_key"] = _apiKey;
 
@@ -505,49 +553,47 @@
 
 			foreach(string key in keys)
 			{
-				if( UrlStringBuilder.Length > BaseUrl.Length + 1 ) 
-				 	UrlStringBuilder.Append("&");
-
-		                UrlStringBuilder.Append(key);
-                		UrlStringBuilder.Append("=");
-		                UrlStringBuilder.Append(Utils.UrlEncode((string)parameters[key]));
-		                HashStringBuilder.Append(key);
-                		HashStringBuilder.Append(parameters[key]);
+				if( UrlStringBuilder.Length > 0 ) UrlStringBuilder.Append("&");
+                UrlStringBuilder.Append(key);
+                UrlStringBuilder.Append("=");
+                UrlStringBuilder.Append(Utils.UrlEncode(Convert.ToString(parameters[key])));
+                HashStringBuilder.Append(key);
+                HashStringBuilder.Append(parameters[key]);
 			}
 
-			if (_sharedSecret != null && _sharedSecret.Length > 0) 
-			{
-				if (UrlStringBuilder.Length > BaseUrl.Length + 1)
-				{
-					UrlStringBuilder.Append("&");
-				}
-				UrlStringBuilder.Append("api_sig=");
-				UrlStringBuilder.Append(Md5Hash(HashStringBuilder.ToString()));
-			}
+            if (_sharedSecret != null && _sharedSecret.Length > 0) 
+            {
+                if (UrlStringBuilder.Length > BaseUrl.Length + 1)
+                {
+                    UrlStringBuilder.Append("&");
+                }
+                UrlStringBuilder.Append("api_sig=");
+                UrlStringBuilder.Append(Md5Hash(HashStringBuilder.ToString()));
+            }
 
-			string url = UrlStringBuilder.ToString();
+			string variables = UrlStringBuilder.ToString();
 			_lastRequest = url;
 			_lastResponse = string.Empty;
 
 			if( CacheDisabled )
 			{
-				string responseXml = DoGetResponse(url);
+				string responseXml = DoGetResponse(url, variables);
 				_lastResponse = responseXml;
-				return Deserialize(responseXml);
+				return Utils.Deserialize(responseXml);
 			}
 			else
 			{
-				ResponseCacheItem cached = (ResponseCacheItem) Cache.Responses.Get(url, cacheTimeout, true);
+				ResponseCacheItem cached = (ResponseCacheItem) Cache.Responses.Get(url + "?" + variables, cacheTimeout, true);
 				if (cached != null)
 				{
 					System.Diagnostics.Debug.WriteLine("Cache hit");
 					_lastResponse = cached.Response;
-					return Deserialize(cached.Response);
+					return Utils.Deserialize(cached.Response);
 				}
 				else
 				{
 					System.Diagnostics.Debug.WriteLine("Cache miss");
-					string responseXml = DoGetResponse(url);
+					string responseXml = DoGetResponse(url, variables);
 					_lastResponse = responseXml;
 
 					ResponseCacheItem resCache = new ResponseCacheItem();
@@ -555,7 +601,7 @@
 					resCache.Url = url;
 					resCache.CreationTime = DateTime.UtcNow;
 
-					FlickrNet.Response response = Deserialize(responseXml);
+					FlickrNet.Response response = Utils.Deserialize(responseXml);
 
 					if( response.Status == ResponseStatus.OK )
 					{
@@ -568,30 +614,6 @@
 			}
 		}
 
-		/// <summary>
-		/// Converts the response string (in XML) into the <see cref="Response"/> object.
-		/// </summary>
-		/// <param name="responseString">The response from Flickr.</param>
-		/// <returns>A <see cref="Response"/> object containing the details of the </returns>
-		private static Response Deserialize(string responseString)
-		{
-			XmlSerializer serializer = _responseSerializer;
-			try
-			{
-				// Deserialise the web response into the Flickr response object
-				StringReader responseReader = new StringReader(responseString);
-				FlickrNet.Response response = (FlickrNet.Response)serializer.Deserialize(responseReader);
-				responseReader.Close();
-
-				return response;
-			}
-			catch(InvalidOperationException ex)
-			{
-				// Serialization error occurred!
-				throw new FlickrException(9998, "Invalid response received (" + ex.Message + ")");
-			}
-		}
-
 		#endregion
 
 		#region [ DownloadPicture ]
@@ -607,6 +629,11 @@
 		/// </remarks>
 		public System.IO.Stream DownloadPicture(string url)
 		{
+			if( CacheDisabled )
+			{
+				return DoDownloadPicture(url);
+			}
+
 			const int BUFFER_SIZE = 1024 * 10;
 
 			PictureCacheItem cacheItem = (PictureCacheItem) Cache.Downloads[url];
@@ -678,7 +705,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -692,7 +719,7 @@
 		/// <returns>The url to redirect the user to.</returns>
 		public string AuthCalcUrl(string frob, AuthLevel authLevel)
 		{
-			if( _sharedSecret == null ) throw new FlickrException(0, "AuthGetToken requires signing. Please supply api key and secret.");
+			if( _sharedSecret == null ) throw new SignatureRequiredException();
 
 			string hash = _sharedSecret + "api_key" + _apiKey + "frob" + frob + "perms" + authLevel.ToString().ToLower();
 			hash = Md5Hash(hash);
@@ -717,7 +744,7 @@
 		/// <returns>The url to redirect the user to.</returns>
 		public string AuthCalcWebUrl(AuthLevel authLevel)
 		{
-			if( _sharedSecret == null ) throw new FlickrException(0, "AuthGetToken requires signing. Please supply api key and secret.");
+			if( _sharedSecret == null ) throw new SignatureRequiredException();
 
 			string hash = _sharedSecret + "api_key" + _apiKey + "perms" + authLevel.ToString().ToLower();
 			hash = Md5Hash(hash);
@@ -736,7 +763,7 @@
 		/// <returns>A <see cref="Auth"/> object containing user and token details.</returns>
 		public Auth AuthGetToken(string frob)
 		{
-			if( _sharedSecret == null ) throw new FlickrException(0, "AuthGetToken requires signing. Please supply api key and secret.");
+			if( _sharedSecret == null ) throw new SignatureRequiredException();
 
 			Hashtable parameters = new Hashtable();
 			parameters.Add("method", "flickr.auth.getToken");
@@ -750,7 +777,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -764,7 +791,7 @@
 		{
 			Hashtable parameters = new Hashtable();
 			parameters.Add("method", "flickr.auth.getFullToken");
-			parameters.Add("mini_token", miniToken);
+			parameters.Add("mini_token", miniToken.Replace("-", ""));
 			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
@@ -774,7 +801,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -798,11 +825,102 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
 		#endregion
+				
+		#region [ Activity ]
+		/// <summary>
+		/// Returns a list of recent activity on photos belonging to the calling user.
+		/// </summary>
+		/// <remarks>
+		/// <b>Do not poll this method more than once an hour.</b>
+		/// </remarks>
+		/// <returns>An array of <see cref="ActivityItem"/> instances.</returns>
+		public ActivityItem[] ActivityUserPhotos()
+		{
+			return ActivityUserPhotos(null);
+		}
+
+		/// <summary>
+		/// Returns a list of recent activity on photos belonging to the calling user.
+		/// </summary>
+		/// <remarks>
+		/// <b>Do not poll this method more than once an hour.</b>
+		/// </remarks>
+		/// <param name="timePeriod">The number of days or hours you want to get activity for.</param>
+		/// <param name="timeType">'d' for days, 'h' for hours.</param>
+		/// <returns>An array of <see cref="ActivityItem"/> instances.</returns>
+		public ActivityItem[] ActivityUserPhotos(int timePeriod, string timeType)
+		{
+			if( timePeriod == 0 ) 
+				throw new ArgumentOutOfRangeException("timePeriod", "Time Period should be greater than 0");
+
+			if( timeType == null ) 
+				throw new ArgumentNullException("timeType");
+
+			if( timeType != "d" && timeType != "h" )
+				throw new ArgumentOutOfRangeException("timeType", "Time type must be 'd' or 'h'");
+
+			return ActivityUserPhotos(timePeriod + timeType);
+		}
+
+		private ActivityItem[] ActivityUserPhotos(string timeframe)
+		{
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.activity.userPhotos");
+			if( timeframe != null && timeframe.Length > 0 ) parameters.Add("timeframe", timeframe);
+			
+			FlickrNet.Response response = GetResponseCache(parameters);
+			if( response.Status == ResponseStatus.OK )
+			{
+				XmlNodeList list = response.AllElements[0].SelectNodes("item");
+				ActivityItem[] items = new ActivityItem[list.Count];
+				for(int i = 0; i < items.Length; i++)
+				{
+					items[i] = new ActivityItem(list[i]);
+				}
+				return items;
+			}
+			else
+			{
+				throw new FlickrApiException(response.Error);
+			}
+		}
+
+		/// <summary>
+		/// Returns a list of recent activity on photos commented on by the calling user.
+		/// </summary>
+		/// <remarks>
+		/// <b>Do not poll this method more than once an hour.</b>
+		/// </remarks>
+		/// <returns></returns>
+		public ActivityItem[] ActivityUserComments(int page, int perPage)
+		{
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.activity.userComments");
+			if( page > 0 ) parameters.Add("page", page);
+			if( perPage > 0 ) parameters.Add("per_page", perPage);
+
+			FlickrNet.Response response = GetResponseCache(parameters);
+			if( response.Status == ResponseStatus.OK )
+			{
+				XmlNodeList list = response.AllElements[0].SelectNodes("item");
+				ActivityItem[] items = new ActivityItem[list.Count];
+				for(int i = 0; i < items.Length; i++)
+				{
+					items[i] = new ActivityItem(list[i]);
+				}
+				return items;
+			}
+			else
+			{
+				throw new FlickrApiException(response.Error);
+			}
+		}
+		#endregion
 
 		#region [ UploadPicture ]
 		/// <summary>
@@ -857,7 +975,7 @@
 		public string UploadPicture(string filename, string title, string description, string tags)
 		{
 			Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
-			return UploadPicture(stream, title, description, tags, -1, -1, -1);
+			return UploadPicture(stream, title, description, tags, -1, -1, -1, ContentType.None, SafetyLevel.None, HiddenFromSearch.None);
 		}
 
 		/// <summary>
@@ -876,7 +994,7 @@
 		public string UploadPicture(string filename, string title, string description, string tags, bool isPublic, bool isFamily, bool isFriend)
 		{
 			Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
-			return UploadPicture(stream, title, description, tags, isPublic?1:0, isFamily?1:0, isFriend?1:0);
+			return UploadPicture(stream, title, description, tags, isPublic?1:0, isFamily?1:0, isFriend?1:0, ContentType.None, SafetyLevel.None, HiddenFromSearch.None);
 		}
 
 		/// <summary>
@@ -889,8 +1007,11 @@
 		/// <param name="isPublic">0 for private, 1 for public.</param>
 		/// <param name="isFamily">1 if family, 0 is not.</param>
 		/// <param name="isFriend">1 if friend, 0 if not.</param>
+		/// <param name="contentType">The content type of the photo, i.e. Photo, Screenshot or Other.</param>
+		/// <param name="safetyLevel">The safety level of the photo, i.e. Safe, Moderate or Restricted.</param>
+		/// <param name="hiddenFromSearch">Is the photo hidden from public searches.</param>
 		/// <returns>The id of the photograph after successful uploading.</returns>
-		public string UploadPicture(Stream stream, string title, string description, string tags, int isPublic, int isFamily, int isFriend)
+		public string UploadPicture(Stream stream, string title, string description, string tags, int isPublic, int isFamily, int isFriend, ContentType contentType, SafetyLevel safetyLevel, HiddenFromSearch hiddenFromSearch)
 		{
 			/*
 			 * 
@@ -941,6 +1062,18 @@
 			{
 				parameters.Add("is_family", isFamily.ToString());
 			}
+			if( safetyLevel != SafetyLevel.None )
+			{
+				parameters.Add("safety_level", (int)safetyLevel);
+			}
+			if( contentType != ContentType.None )
+			{
+				parameters.Add("content_type", (int)contentType);
+			}
+			if( hiddenFromSearch != HiddenFromSearch.None )
+			{
+				parameters.Add("hidden", (int)hiddenFromSearch);
+			}
 
 			parameters.Add("api_key", _apiKey);
 			parameters.Add("auth_token", _apiToken);
@@ -1027,7 +1160,7 @@
 			}
 			else
 			{
-				throw new FlickrException(uploader.Code, uploader.Message);
+				throw new FlickrApiException(uploader.Error);
 			}
 		}
 
@@ -1161,7 +1294,7 @@
 			}
 			else
 			{
-				throw new FlickrException(uploader.Code, uploader.Message);
+				throw new FlickrApiException(uploader.Error);
 			}
 		}
 		#endregion
@@ -1185,7 +1318,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1231,7 +1364,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -1254,7 +1387,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1276,7 +1409,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -1301,7 +1434,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1324,7 +1457,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1382,7 +1515,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1422,7 +1555,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -1456,7 +1589,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1505,7 +1638,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1528,7 +1661,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -1554,7 +1687,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1583,7 +1716,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1607,7 +1740,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1627,7 +1760,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1707,7 +1840,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -1772,7 +1905,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1813,7 +1946,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1845,7 +1978,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1867,7 +2000,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -1894,7 +2027,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1919,7 +2052,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1939,11 +2072,11 @@
 
 			if( response.Status == ResponseStatus.OK )
 			{
-				return response.Person;
+				return Person.SerializePerson(response.AllElements[0]);
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1964,7 +2097,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -1988,7 +2121,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2012,7 +2145,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -2051,7 +2184,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2075,7 +2208,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2100,7 +2233,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -2146,7 +2279,7 @@
 		{
 			if( count != 0 && (count < 10 || count > 50) && !singlePhoto )
 			{
-				throw new ArgumentOutOfRangeException("count", count, "Count must be between 10 and 50.");
+				throw new ArgumentOutOfRangeException("count", String.Format("Count must be between 10 and 50. ({0})", count));
 			}
 			Hashtable parameters = new Hashtable();
 			parameters.Add("method", "flickr.photos.getContactsPhotos");
@@ -2163,7 +2296,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2255,7 +2388,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2283,7 +2416,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2365,7 +2498,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2406,7 +2539,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2441,7 +2574,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2464,7 +2597,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2522,77 +2655,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
-			}
-		}
-
-		/// <summary>
-		/// Return a list of your photos that have been recently created or which have been recently modified.
-		/// Recently modified may mean that the photo's metadata (title, description, tags) 
-		/// may have been changed or a comment has been added (or just modified somehow :-)
-		/// </summary>
-		/// <param name="minDate">The date from which modifications should be compared.</param>
-		/// <param name="extras">A list of extra information to fetch for each returned record.</param>
-		/// <returns>Returns a <see cref="Photos"/> instance containing the list of photos.</returns>
-		public Photos PhotosRecentlyUpdated(DateTime minDate, PhotoSearchExtras extras)
-		{
-			return PhotosRecentlyUpdated(minDate, extras, 0, 0);
-		}
-
-		/// <summary>
-		/// Return a list of your photos that have been recently created or which have been recently modified.
-		/// Recently modified may mean that the photo's metadata (title, description, tags) 
-		/// may have been changed or a comment has been added (or just modified somehow :-)
-		/// </summary>
-		/// <param name="minDate">The date from which modifications should be compared.</param>
-		/// <param name="perPage">Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.</param>
-		/// <param name="page">The page of results to return. If this argument is omitted, it defaults to 1.</param>
-		/// <returns>Returns a <see cref="Photos"/> instance containing the list of photos.</returns>
-		public Photos PhotosRecentlyUpdated(DateTime minDate, int perPage, int page)
-		{
-			return PhotosRecentlyUpdated(minDate, PhotoSearchExtras.None, perPage, page);
-		}
-
-		/// <summary>
-		/// Return a list of your photos that have been recently created or which have been recently modified.
-		/// Recently modified may mean that the photo's metadata (title, description, tags) 
-		/// may have been changed or a comment has been added (or just modified somehow :-)
-		/// </summary>
-		/// <param name="minDate">The date from which modifications should be compared.</param>
-		/// <returns>Returns a <see cref="Photos"/> instance containing the list of photos.</returns>
-		public Photos PhotosRecentlyUpdated(DateTime minDate)
-		{
-			return PhotosRecentlyUpdated(minDate, PhotoSearchExtras.None, 0, 0);
-		}
-
-		/// <summary>
-		/// Return a list of your photos that have been recently created or which have been recently modified.
-		/// Recently modified may mean that the photo's metadata (title, description, tags) 
-		/// may have been changed or a comment has been added (or just modified somehow :-)
-		/// </summary>
-		/// <param name="minDate">The date from which modifications should be compared.</param>
-		/// <param name="extras">A list of extra information to fetch for each returned record.</param>
-		/// <param name="perPage">Number of photos to return per page. If this argument is omitted, it defaults to 100. The maximum allowed value is 500.</param>
-		/// <param name="page">The page of results to return. If this argument is omitted, it defaults to 1.</param>
-		/// <returns>Returns a <see cref="Photos"/> instance containing the list of photos.</returns>
-		public Photos PhotosRecentlyUpdated(DateTime minDate, PhotoSearchExtras extras, int perPage, int page)
-		{
-			Hashtable parameters = new Hashtable();
-			parameters.Add("method", "flickr.photos.recentlyUpdated");
-			parameters.Add("min_date", Utils.DateToUnixTimestamp(minDate).ToString());
-			if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
-			if( perPage > 0  ) parameters.Add("per_page", perPage.ToString());
-			if( page > 0 ) parameters.Add("page", page.ToString());
-
-			FlickrNet.Response response = GetResponseCache(parameters);
-
-			if( response.Status == ResponseStatus.OK )
-			{
-				return response.Photos;
-			}
-			else
-			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2615,7 +2678,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2672,7 +2735,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2744,7 +2807,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2766,7 +2829,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -2789,7 +2852,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3336,7 +3399,7 @@
 			options.Text = text;
 			options.MinUploadDate = minUploadDate;
 			options.MaxUploadDate = maxUploadDate;
-			options.AddLicense(license);
+			if( license > 0 ) options.AddLicense(license);
 			options.PerPage = perPage;
 			options.Page = page;
 			options.Extras = extras;
@@ -3357,6 +3420,8 @@
 			if( options.Text != null && options.Text.Length > 0 ) parameters.Add("text", options.Text);
 			if( options.Tags != null && options.Tags.Length > 0 ) parameters.Add("tags", options.Tags);
 			if( options.TagMode != TagMode.None ) parameters.Add("tag_mode", options.TagModeString);
+			if( options.MachineTags != null && options.MachineTags.Length > 0 ) parameters.Add("machine_tags", options.MachineTags);
+			if( options.MachineTagMode != MachineTagMode.None ) parameters.Add("machine_tag_mode", options.MachineTagModeString);
 			if( options.MinUploadDate != DateTime.MinValue ) parameters.Add("min_upload_date", Utils.DateToUnixTimestamp(options.MinUploadDate).ToString());
 			if( options.MaxUploadDate != DateTime.MinValue ) parameters.Add("max_upload_date", Utils.DateToUnixTimestamp(options.MaxUploadDate).ToString());
 			if( options.MinTakenDate != DateTime.MinValue ) parameters.Add("min_taken_date", options.MinTakenDate.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo));
@@ -3387,7 +3452,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3448,7 +3513,7 @@
 				parameters.Add("date_taken_granularity", granularity.ToString("d"));
 			}
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3456,7 +3521,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3477,7 +3542,7 @@
 			parameters.Add("title", title);
 			parameters.Add("description", description);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3485,7 +3550,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3524,7 +3589,7 @@
 			parameters.Add("perm_comment", permComment.ToString("d"));
 			parameters.Add("perm_addmeta", permAddMeta.ToString("d"));
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3532,7 +3597,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3541,7 +3606,7 @@
 		/// Set the tags for a photo.
 		/// </summary>
 		/// <remarks>
-		/// This will remove all old tags and add these new ones specified. See <see cref="PhotosAddTags"/>
+		/// This will remove all old tags and add these new ones specified. See <see cref="PhotosAddTags(string, string)"/>
 		/// to just add new tags without deleting old ones.
 		/// </remarks>
 		/// <param name="photoId">The id of the photo to update.</param>
@@ -3557,7 +3622,7 @@
 		/// Set the tags for a photo.
 		/// </summary>
 		/// <remarks>
-		/// This will remove all old tags and add these new ones specified. See <see cref="PhotosAddTags"/>
+		/// This will remove all old tags and add these new ones specified. See <see cref="PhotosAddTags(string, string)"/>
 		/// to just add new tags without deleting old ones.
 		/// </remarks>
 		/// <param name="photoId">The id of the photo to update.</param>
@@ -3570,7 +3635,7 @@
 			parameters.Add("photo_id", photoId);
 			parameters.Add("tags", tags);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3578,10 +3643,92 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
+
+		/// <summary>
+		/// Sets the content type for a photo.
+		/// </summary>
+		/// <param name="photoId">The ID of the photos to set.</param>
+		/// <param name="contentType">The new content type.</param>
+		public void PhotosSetContentType(string photoId, ContentType contentType)
+		{
+			CheckRequiresAuthentication();
+
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.photos.setContentType");
+			parameters.Add("photo_id", photoId);
+			parameters.Add("content_type", (int)contentType);
+
+			FlickrNet.Response response = GetResponseNoCache(parameters);
+
+			if( response.Status == ResponseStatus.OK )
+			{
+				return;
+			}
+			else
+			{
+				throw new FlickrApiException(response.Error);
+			}
+		}
+
+		/// <summary>
+		/// Set the safety level for a photo, but only set the hidden aspect.
+		/// </summary>
+		/// <param name="photoId">The ID of the photo to set the hidden property for.</param>
+		/// <param name="hidden">The new value of the hidden value.</param>
+		public void PhotosSetSafetyLevel(string photoId, HiddenFromSearch hidden)
+		{
+			PhotosSetSafetyLevel(photoId, SafetyLevel.None, hidden);
+		}
+
+		/// <summary>
+		/// Set the safety level for a photo.
+		/// </summary>
+		/// <param name="photoId">The ID of the photo to set the safety level property for.</param>
+		/// <param name="safetyLevel">The new value of the safety level value.</param>
+		public void PhotosSetSafetyLevel(string photoId, SafetyLevel safetyLevel)
+		{
+			PhotosSetSafetyLevel(photoId, safetyLevel, HiddenFromSearch.None);
+		}
+
+		/// <summary>
+		/// Sets the safety level and hidden property of a photo.
+		/// </summary>
+		/// <param name="photoId">The ID of the photos to set.</param>
+		/// <param name="safetyLevel">The new content type.</param>
+		/// <param name="hidden">The new hidden value.</param>
+		public void PhotosSetSafetyLevel(string photoId, SafetyLevel safetyLevel, HiddenFromSearch hidden)
+		{
+			CheckRequiresAuthentication();
+
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.photos.setSafetyLevel");
+			parameters.Add("photo_id", photoId);
+			if( safetyLevel != SafetyLevel.None ) parameters.Add("safety_level", (int)safetyLevel);
+			switch(hidden)
+			{
+				case HiddenFromSearch.Visible:
+					parameters.Add("hidden", 0);
+					break;
+				case HiddenFromSearch.Hidden:
+					parameters.Add("hidden", 1);
+					break;
+			}
+
+			FlickrNet.Response response = GetResponseNoCache(parameters);
+
+			if( response.Status == ResponseStatus.OK )
+			{
+				return;
+			}
+			else
+			{
+				throw new FlickrApiException(response.Error);
+			}
+		}
 		#endregion
 
 		#region [ Photos Comments ]
@@ -3604,7 +3751,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3629,11 +3776,11 @@
 				if( node.Attributes.GetNamedItem("id") != null )
 					return node.Attributes.GetNamedItem("id").Value;
 				else
-					throw new FlickrException(9001, "Comment ID not found");
+					throw new ResponseXmlException("Comment ID not found in response Xml.");
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3655,7 +3802,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3679,7 +3826,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -3697,7 +3844,7 @@
 			parameters.Add("photoset_id", photosetId);
 			parameters.Add("photo_id", photoId);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3705,7 +3852,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3735,7 +3882,7 @@
 			parameters.Add("primary_photo_id", primaryPhotoId);
 			parameters.Add("description", description);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3743,7 +3890,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3759,7 +3906,7 @@
 			parameters.Add("method", "flickr.photosets.delete");
 			parameters.Add("photoset_id", photosetId);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3767,7 +3914,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3787,7 +3934,7 @@
 			parameters.Add("title", title);
 			parameters.Add("description", description);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3795,7 +3942,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3838,7 +3985,7 @@
 			parameters.Add("primary_photo_id", primaryPhotoId);
 			parameters.Add("photo_ids", photoIds);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -3846,7 +3993,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3877,7 +4024,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3900,7 +4047,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 
 		}
@@ -3933,7 +4080,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -3941,10 +4088,22 @@
 		/// Gets a collection of photos for a photoset.
 		/// </summary>
 		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
-		/// <returns>An array of <see cref="Photo"/> instances.</returns>
-		public Photo[] PhotosetsGetPhotos(string photosetId)
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId)
+		{
+			return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, PrivacyFilter.None, 0, 0);
+		}
+
+		/// <summary>
+		/// Gets a collection of photos for a photoset.
+		/// </summary>
+		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
+		/// <param name="page">The page to return, defaults to 1.</param>
+		/// <param name="perPage">The number of photos to return per page.</param>
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId, int page, int perPage)
 		{
-			return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, PrivacyFilter.None);
+			return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, PrivacyFilter.None, page, perPage);
 		}
 
 		/// <summary>
@@ -3952,10 +4111,23 @@
 		/// </summary>
 		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
 		/// <param name="privacyFilter">The privacy filter to search on.</param>
-		/// <returns>An array of <see cref="Photo"/> instances.</returns>
-		public Photo[] PhotosetsGetPhotos(string photosetId, PrivacyFilter privacyFilter)
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId, PrivacyFilter privacyFilter)
+		{
+			return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, privacyFilter, 0, 0);
+		}
+
+		/// <summary>
+		/// Gets a collection of photos for a photoset.
+		/// </summary>
+		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
+		/// <param name="privacyFilter">The privacy filter to search on.</param>
+		/// <param name="page">The page to return, defaults to 1.</param>
+		/// <param name="perPage">The number of photos to return per page.</param>
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId, PrivacyFilter privacyFilter, int page, int perPage)
 		{
-			return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, privacyFilter);
+			return PhotosetsGetPhotos(photosetId, PhotoSearchExtras.All, privacyFilter, page, perPage);
 		}
 
 		/// <summary>
@@ -3963,10 +4135,23 @@
 		/// </summary>
 		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
 		/// <param name="extras">The extras to return for each photo.</param>
-		/// <returns>An array of <see cref="Photo"/> instances.</returns>
-		public Photo[] PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras)
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras)
+		{
+			return PhotosetsGetPhotos(photosetId, extras, PrivacyFilter.None, 0, 0);
+		}
+
+		/// <summary>
+		/// Gets a collection of photos for a photoset.
+		/// </summary>
+		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
+		/// <param name="extras">The extras to return for each photo.</param>
+		/// <param name="page">The page to return, defaults to 1.</param>
+		/// <param name="perPage">The number of photos to return per page.</param>
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, int page, int perPage)
 		{
-			return PhotosetsGetPhotos(photosetId, extras, PrivacyFilter.None);
+			return PhotosetsGetPhotos(photosetId, extras, PrivacyFilter.None, page, perPage);
 		}
 
 		/// <summary>
@@ -3975,20 +4160,35 @@
 		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
 		/// <param name="extras">The extras to return for each photo.</param>
 		/// <param name="privacyFilter">The privacy filter to search on.</param>
+		/// <returns>A <see cref="Photoset"/> object containing the list of <see cref="Photo"/> instances.</returns>
+		public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, PrivacyFilter privacyFilter)
+		{
+			return PhotosetsGetPhotos(photosetId, extras, privacyFilter, 0, 0);
+		}
+		
+		/// <summary>
+		/// Gets a collection of photos for a photoset.
+		/// </summary>
+		/// <param name="photosetId">The ID of the photoset to return photos for.</param>
+		/// <param name="extras">The extras to return for each photo.</param>
+		/// <param name="privacyFilter">The privacy filter to search on.</param>
+		/// <param name="page">The page to return, defaults to 1.</param>
+		/// <param name="perPage">The number of photos to return per page.</param>
 		/// <returns>An array of <see cref="Photo"/> instances.</returns>
-		public Photo[] PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, PrivacyFilter privacyFilter)
+		public Photoset PhotosetsGetPhotos(string photosetId, PhotoSearchExtras extras, PrivacyFilter privacyFilter, int page, int perPage)
 		{
 			Hashtable parameters = new Hashtable();
 			parameters.Add("method", "flickr.photosets.getPhotos");
 			parameters.Add("photoset_id", photosetId);
 			if( extras != PhotoSearchExtras.None ) parameters.Add("extras", Utils.ExtrasToString(extras));
 			if( privacyFilter != PrivacyFilter.None ) parameters.Add("privacy_filter", privacyFilter.ToString("d"));
+			if( page > 0 ) parameters.Add("page", page);
+			if( perPage > 0 ) parameters.Add("per_page", perPage);
 
 			FlickrNet.Response response = GetResponseCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
-				if( response.Photoset.PhotoCollection == null ) return new Photo[0];
 				if( response.Photoset.OwnerId != null && response.Photoset.OwnerId.Length > 0 )
 				{
 					foreach(Photo p in response.Photoset.PhotoCollection)
@@ -3996,11 +4196,11 @@
 						p.UserId = response.Photoset.OwnerId;
 					}
 				}
-				return response.Photoset.PhotoCollection;
+				return response.Photoset;
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4027,7 +4227,7 @@
 			parameters.Add("method", "flickr.photosets.orderSets");
 			parameters.Add("photosetIds", photosetIds);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -4035,7 +4235,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4054,7 +4254,7 @@
 			parameters.Add("photoset_id", photosetId);
 			parameters.Add("photo_id", photoId);
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -4062,7 +4262,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -4087,7 +4287,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4112,11 +4312,11 @@
 				if( node.Attributes.GetNamedItem("id") != null )
 					return node.Attributes.GetNamedItem("id").Value;
 				else
-					throw new FlickrException(9001, "Comment ID not found");
+					throw new ResponseXmlException("Comment ID not found in response.");
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4138,7 +4338,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4162,7 +4362,78 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
+			}
+		}
+		#endregion
+
+		#region [ Prefs ]
+		/// <summary>
+		/// Gets the currently authenticated users default safety level.
+		/// </summary>
+		/// <returns></returns>
+		public SafetyLevel PrefsGetSafetyLevel()
+		{
+			CheckRequiresAuthentication();
+
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.prefs.getSafetyLevel");
+
+			Response res = GetResponseCache(parameters);
+			if( res.Status == ResponseStatus.OK )
+			{
+				string s = res.AllElements[0].GetAttribute("safety_level");
+				return (SafetyLevel)int.Parse(s);
+			}
+			else
+			{
+				throw new FlickrApiException(res.Error);
+			}
+		}
+
+		/// <summary>
+		/// Gets the currently authenticated users default hidden from search setting.
+		/// </summary>
+		/// <returns></returns>
+		public HiddenFromSearch PrefsGetHidden()
+		{
+			CheckRequiresAuthentication();
+
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.prefs.getHidden");
+
+			Response res = GetResponseCache(parameters);
+			if( res.Status == ResponseStatus.OK )
+			{
+				string s = res.AllElements[0].GetAttribute("hidden");
+				return (HiddenFromSearch)int.Parse(s);
+			}
+			else
+			{
+				throw new FlickrApiException(res.Error);
+			}
+		}
+		
+		/// <summary>
+		/// Gets the currently authenticated users default content type.
+		/// </summary>
+		/// <returns></returns>
+		public ContentType PrefsGetContentType()
+		{
+			CheckRequiresAuthentication();
+
+			Hashtable parameters = new Hashtable();
+			parameters.Add("method", "flickr.prefs.getContentType");
+
+			Response res = GetResponseCache(parameters);
+			if( res.Status == ResponseStatus.OK )
+			{
+				string s = res.AllElements[0].GetAttribute("content_type");
+				return (ContentType)int.Parse(s);
+			}
+			else
+			{
+				throw new FlickrApiException(res.Error);
 			}
 		}
 		#endregion
@@ -4173,7 +4444,7 @@
 		/// </summary>
 		/// <param name="photoId">The id of the photo to return tags for.</param>
 		/// <returns>An instance of the <see cref="PhotoInfo"/> class containing only the <see cref="PhotoInfo.Tags"/> property.</returns>
-		public PhotoInfo TagsGetListPhoto(string photoId)
+		public PhotoInfoTag[] TagsGetListPhoto(string photoId)
 		{
 			Hashtable parameters = new Hashtable();
 			parameters.Add("method", "flickr.tags.getListPhoto");
@@ -4184,11 +4455,11 @@
 
 			if( response.Status == ResponseStatus.OK )
 			{
-				return response.PhotoInfo;
+				return response.PhotoInfo.Tags.TagCollection;
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4226,7 +4497,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4286,7 +4557,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4316,7 +4587,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4351,7 +4622,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4379,7 +4650,7 @@
 				if( response.Error.Code == 2 )
 					return null;
 				else
-					throw new FlickrException(response.Error);
+					throw new FlickrApiException(response.Error);
 			}
 		}
 		/// <summary>
@@ -4418,7 +4689,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4443,7 +4714,7 @@
 				if( response.Error.Code == 2 )
 					return false;
 				else
-					throw new FlickrException(response.Error);
+					throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4468,14 +4739,14 @@
 			parameters.Add("method", "flickr.photos.getWithoutGeoData");
 			Utils.PartialOptionsIntoArray(options, parameters);
 
-			FlickrNet.Response response = GetResponseNoCache(parameters);
+			FlickrNet.Response response = GetResponseCache(parameters);
 			if( response.Status == ResponseStatus.OK )
 			{
 				return response.Photos;
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4540,14 +4811,14 @@
 			parameters.Add("method", "flickr.photos.getWithGeoData");
 			Utils.PartialOptionsIntoArray(options, parameters);
 
-			FlickrNet.Response response = GetResponseNoCache(parameters);
+			FlickrNet.Response response = GetResponseCache(parameters);
 			if( response.Status == ResponseStatus.OK )
 			{
 				return response.Photos;
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4570,7 +4841,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4592,7 +4863,7 @@
 			parameters.Add("is_friend", IsFriend?"1":"0");
 			parameters.Add("is_family", IsFamily?"1":"0");
 
-			FlickrNet.Response response = GetResponseCache(parameters);
+			FlickrNet.Response response = GetResponseNoCache(parameters);
 
 			if( response.Status == ResponseStatus.OK )
 			{
@@ -4600,7 +4871,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4639,7 +4910,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		/// <summary>
@@ -4689,7 +4960,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4710,7 +4981,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -4739,7 +5010,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4774,7 +5045,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4809,7 +5080,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4843,7 +5114,7 @@
 				if( response.Error.Code == 1 )
 					return null;
 				else
-					throw new FlickrException(response.Error);
+					throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4867,7 +5138,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 		#endregion
@@ -4893,7 +5164,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4917,7 +5188,7 @@
 			}
 			else
 			{
-				throw new FlickrException(response.Error);
+				throw new FlickrApiException(response.Error);
 			}
 		}
 
@@ -4932,6 +5203,22 @@
 			return BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
 		}
 		#endregion
+
+		private void CheckApiKey()
+		{
+			if( ApiKey == null || ApiKey.Length == 0 )
+				throw new ApiKeyRequiredException();
+		}
+		private void CheckRequiresAuthentication()
+		{
+			CheckApiKey();
+
+			if( ApiSecret == null || ApiSecret.Length == 0 )
+				throw new SignatureRequiredException();
+			if( AuthToken == null || AuthToken.Length == 0 )
+				throw new AuthenticationRequiredException();
+
+		}
 	}
 
 }

Added: trunk/extensions/FlickrExport/FlickrNet/FlickrApiException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/FlickrApiException.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,46 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Exception thrown when the Flickr API returned a specifi error code.
+	/// </summary>
+	public class FlickrApiException : FlickrException
+	{
+		private int code;
+		private string msg = "";
+
+		internal FlickrApiException(ResponseError error)
+		{
+			code = error.Code;
+			msg = error.Message;
+		}
+
+		/// <summary>
+		/// Get the code of the Flickr error.
+		/// </summary>
+		public int Code
+		{
+			get { return code; }
+		}
+
+		/// <summary>
+		/// Gets the verbose message returned by Flickr.
+		/// </summary>
+		public string Verbose
+		{
+			get { return msg; }
+		}
+		
+		/// <summary>
+		/// Overrides the message to return custom error message.
+		/// </summary>
+		public override string Message
+		{
+			get
+			{
+				return msg + " (" + code + ")";
+			}
+		}
+	}
+}

Modified: trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationManager.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationManager.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationManager.cs	Wed Jul  2 11:21:09 2008
@@ -2,6 +2,7 @@
 using System.Configuration;
 using System.Xml;
 
+#if !WindowsCE
 namespace FlickrNet
 {
 	/// <summary>
@@ -36,3 +37,4 @@
 		}
 	}
 }
+#endif
\ No newline at end of file

Modified: trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationSettings.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationSettings.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/FlickrConfigurationSettings.cs	Wed Jul  2 11:21:09 2008
@@ -1,3 +1,4 @@
+#if !WindowsCE
 using System;
 using System.Collections.Specialized ;
 using System.Xml;
@@ -302,3 +303,4 @@
 
 	}
 }
+#endif
\ No newline at end of file

Modified: trunk/extensions/FlickrExport/FlickrNet/FlickrException.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/FlickrException.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/FlickrException.cs	Wed Jul  2 11:21:09 2008
@@ -3,62 +3,21 @@
 namespace FlickrNet
 {
 	/// <summary>
-	/// A FlickrException, thrown when a connection to Flickr fails.
+	/// Generic Flickr.Net Exception.
 	/// </summary>
 	[Serializable]
 	public class FlickrException : Exception
 	{
-		private int code;
-		private string msg = "";
-
-		/// <summary>
-		/// Get the code of the Flickr error.
-		/// </summary>
-		public int Code
-		{
-			get { return code; }
-		}
-
-		/// <summary>
-		/// Gets the verbose message returned by Flickr.
-		/// </summary>
-		public string Verbose
+		internal FlickrException()
 		{
-			get { return msg; }
-		}
-		
-		/// <summary>
-		/// Creates a new exception with the given the code and verbose message string
-		/// </summary>
-		/// <param name="code">The code of the error. 100 is Invalid Api Key and 99 is User not logged in. Others are method specific.</param>
-		/// <param name="verbose">The verbose description of the error.</param>
-		public FlickrException(int code, string verbose)
-		{
-			this.code = code;
-			msg = verbose;
 		}
 
-		/// <summary>
-		/// Creates a new exception from the <see cref="ResponseError"/> class.
-		/// </summary>
-		/// <param name="error">An instance of the <see cref="ResponseError"/> class.</param>
-		public FlickrException(ResponseError error)
+		internal FlickrException(string message) : base(message)
 		{
-			code = error.Code;
-			msg = error.Message;
 		}
 
-		/// <summary>
-		/// Overrides the message to return custom error message.
-		/// </summary>
-		public override string Message
+		internal FlickrException(string message, Exception innerException) : base(message, innerException)
 		{
-			get
-			{
-				return msg + " (" + code + ")";
-			}
 		}
-
-
 	}
 }

Added: trunk/extensions/FlickrExport/FlickrNet/FlickrWebException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/FlickrWebException.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,14 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Exception thrown when a communication error occurs with a web call.
+	/// </summary>
+	public class FlickrWebException : FlickrException
+	{
+		internal FlickrWebException(string message, Exception innerException) : base(message, innerException)
+		{
+		}
+	}
+}

Modified: trunk/extensions/FlickrExport/FlickrNet/GeoAccuracy.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/GeoAccuracy.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/GeoAccuracy.cs	Wed Jul  2 11:21:09 2008
@@ -9,6 +9,7 @@
 	/// <remarks>
 	/// Level descriptions are only approximate.
 	/// </remarks>
+	[Serializable]
 	public enum GeoAccuracy
 	{
 		/// <summary>

Modified: trunk/extensions/FlickrExport/FlickrNet/GroupSearchResults.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/GroupSearchResults.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/GroupSearchResults.cs	Wed Jul  2 11:21:09 2008
@@ -5,7 +5,7 @@
 namespace FlickrNet
 {
 	/// <summary>
-	/// Returned by <see cref="Flickr.GroupsSearch"/> methods.
+	/// Returned by <see cref="Flickr.GroupsSearch(string)"/> methods.
 	/// </summary>
 	public class GroupSearchResults
 	{

Modified: trunk/extensions/FlickrExport/FlickrNet/License.txt
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/License.txt	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/License.txt	Wed Jul  2 11:21:09 2008
@@ -1,20 +1,20 @@
-Flickr .Net API Library
------------------------
-All source code and information supplied as part of the Flick .Net API Library is copyright too its contributers.
-
-The source code has been released under a dual license - meaning you can use either licensed version of the library with your code.
-
-It is released under the Common Public License 1.0, a copy of which can be found at the link below.
-http://www.opensource.org/licenses/cpl.php
-
-It is released under the LGPL (GNU Lesser General Public License), a copy of which can be found at the link below.
-http://www.gnu.org/copyleft/lesser.html
-
-You are free to distribute copies of this Program in its compiled, unaltered form, including, but not limited to using it (in library form) in other .Net application, without use of this license.
-You are free to modify this code, however you must release the resulting Contributions under the CPL or the LGPL (or compatible license).
-
-Flickr API Key
---------------
-I do not have permission to include a Flickr API Key in any distribution which includes source code.
-If I do by accident then it is not included in the above license and should not be used. 
-
+Flickr .Net API Library
+-----------------------
+All source code and information supplied as part of the Flick .Net API Library is copyright too its contributers.
+
+The source code has been released under a dual license - meaning you can use either licensed version of the library with your code.
+
+It is released under the Common Public License 1.0, a copy of which can be found at the link below.
+http://www.opensource.org/licenses/cpl.php
+
+It is released under the LGPL (GNU Lesser General Public License), a copy of which can be found at the link below.
+http://www.gnu.org/copyleft/lesser.html
+
+You are free to distribute copies of this Program in its compiled, unaltered form, including, but not limited to using it (in library form) in other .Net application, without use of this license.
+You are free to modify this code, however you must release the resulting Contributions under the CPL or the LGPL (or compatible license).
+
+Flickr API Key
+--------------
+I do not have permission to include a Flickr API Key in any distribution which includes source code.
+If I do by accident then it is not included in the above license and should not be used. 
+

Modified: trunk/extensions/FlickrExport/FlickrNet/LockFile.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/LockFile.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/LockFile.cs	Wed Jul  2 11:21:09 2008
@@ -39,8 +39,10 @@
 
 			lock (this)
 			{
+#if !WindowsCE
 				while (stream != null)
 					Monitor.Wait(this);
+#endif
 
 				while (true)
 				{
@@ -52,22 +54,20 @@
 						stream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None, 8, false);
 						return disposeHelper;
 					}
-					catch (IOException)
+					catch (IOException ioe)
 					{
-						Thread.Sleep(50);
-						continue;
-//						int errorCode = Marshal.GetHRForException(ioe) & 0xFFFF;
-//						switch (errorCode)
-//						{
-//							case 32:
-//							case 33:
-//							case 32 | 0x1620:
-//							case 33 | 0x1620:
-//								Thread.Sleep(50);
-//								continue;
-//							default:
-//								throw;
-//						}
+						int errorCode = SafeNativeMethods.GetErrorCode(ioe);
+						switch (errorCode)
+						{
+							case 32:
+							case 33:
+							case 32 | 0x1620:
+							case 33 | 0x1620:
+								Thread.Sleep(50);
+								continue;
+							default:
+								throw;
+						}
 					}
 				}
 			}
@@ -77,9 +77,11 @@
 		{
 			lock (this)
 			{
+#if !WindowsCE
 				// Doesn't hurt to pulse. Note that waiting threads will not actually
 				// continue to execute until this critical section is exited.
 				Monitor.PulseAll(this);
+#endif
 
 				if (stream == null)
 					throw new InvalidOperationException("Tried to dispose a FileLock that was not owned");

Modified: trunk/extensions/FlickrExport/FlickrNet/Makefile.am
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Makefile.am	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Makefile.am	Wed Jul  2 11:21:09 2008
@@ -4,7 +4,11 @@
 
 ASSEMBLY_SOURCES =				\
 	$(srcdir)/AssemblyInfo.cs 		\
+	$(srcdir)/ActivityEvent.cs		\
+	$(srcdir)/ActivityItem.cs		\
+	$(srcdir)/ApiKeyRequiredException.cs	\
 	$(srcdir)/Auth.cs 			\
+	$(srcdir)/AuthenticationRequiredException.cs		\
 	$(srcdir)/Blogs.cs 			\
 	$(srcdir)/BoundaryBox.cs 		\
 	$(srcdir)/Cache.cs 			\
@@ -16,6 +20,8 @@
 	$(srcdir)/Enums.cs 			\
 	$(srcdir)/ExifPhoto.cs 			\
 	$(srcdir)/Flickr.cs 			\
+	$(srcdir)/FlickrApiException.cs		\
+	$(srcdir)/FlickrWebException.cs		\
 	$(srcdir)/FlickrConfigurationManager.cs	\
 	$(srcdir)/FlickrConfigurationSettings.cs\
 	$(srcdir)/FlickrException.cs 		\
@@ -41,6 +47,9 @@
 	$(srcdir)/PhotoSets.cs 			\
 	$(srcdir)/Photos.cs 			\
 	$(srcdir)/Response.cs 			\
+	$(srcdir)/ResponseXmlException.cs	\
+	$(srcdir)/SafeNativeMethods.cs		\
+	$(srcdir)/SignatureRequiredException.cs	\
 	$(srcdir)/Sizes.cs 			\
 	$(srcdir)/Tags.cs 			\
 	$(srcdir)/Uploader.cs 			\
@@ -48,6 +57,7 @@
 	$(srcdir)/User.cs 			\
 	$(srcdir)/Utils.cs 
 
+
 REFS =  -r:System.Web.dll	\
 	-r:System.Drawing.dll
 

Modified: trunk/extensions/FlickrExport/FlickrNet/PartialSearchOptions.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PartialSearchOptions.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PartialSearchOptions.cs	Wed Jul  2 11:21:09 2008
@@ -86,7 +86,7 @@
 			get { return _page; }
 			set 
 			{
-				if( value < 0 ) throw new ArgumentOutOfRangeException("Page", value, "Must be greater than 0");
+				if( value < 0 ) throw new ArgumentOutOfRangeException("Page", "Must be greater than 0");
 				_page = value; 
 			}
 		}

Modified: trunk/extensions/FlickrExport/FlickrNet/PersistentCache.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PersistentCache.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PersistentCache.cs	Wed Jul  2 11:21:09 2008
@@ -2,7 +2,7 @@
 using System.Collections;
 using System.Diagnostics;
 using System.IO;
-using System.Runtime.Serialization.Formatters.Binary;
+//using System.Runtime.Serialization.Formatters.Binary;
 
 namespace FlickrNet
 {
@@ -254,7 +254,7 @@
 			if (dataFile.Exists)
 			{
 				dataFile.Refresh();
-				newTimestamp = dataFile.LastWriteTimeUtc;
+				newTimestamp = dataFile.LastWriteTime;
 				newLength = dataFile.Length;
 			}
 
@@ -290,7 +290,7 @@
 			}
 
 			dataFile.Refresh();
-			timestamp = dataFile.LastWriteTimeUtc;
+			timestamp = dataFile.LastWriteTime;
 			length = dataFile.Length;
 
 			dirty = false;

Modified: trunk/extensions/FlickrExport/FlickrNet/Person.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Person.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Person.cs	Wed Jul  2 11:21:09 2008
@@ -10,60 +10,87 @@
 	/// method.
 	/// </summary>
 	[System.Serializable]
+	[XmlRoot("person")]
 	public class Person
 	{
+		internal static Person SerializePerson(System.Xml.XmlNode node)
+		{
+			Person p = (Person)Utils.Deserialize(node, typeof(Person));
+			return p;
+		}
+		private string _userId;
+		private int _isAdmin;
+		private int _isPro;
+		private int _iconServer;
+		private int _iconFarm;
+		private string _username;
+		private string _realname;
+		private string _location;
+		private PersonPhotosSummary _summary = new PersonPhotosSummary();
+		private string _photosUrl;
+		private string _profileUrl;
+		private string _mboxHash;
+
 		/// <summary>The user id of the user.</summary>
 		/// <remarks/>
 		[XmlAttribute("nsid", Form=XmlSchemaForm.Unqualified)]
-		public string UserId;
+		public string UserId { get { return _userId; } set { _userId = value; } }
     
 		/// <summary>Is the user an administrator. 
 		/// 1 = admin, 0 = normal user.</summary>
 		/// <remarks></remarks>
 		[XmlAttribute("isadmin", Form=XmlSchemaForm.Unqualified)]
-		public int IsAdmin;
+		public int IsAdmin { get { return _isAdmin; } set { _isAdmin = value; } }
 
 		/// <summary>Does the user posses a pro account.
 		/// 0 = free acouunt, 1 = pro account holder.</summary>
 		[XmlAttribute("ispro", Form=XmlSchemaForm.Unqualified)]
-		public int IsPro;
+		public int IsPro { get { return _isPro; } set { _isPro = value; } }
 	
 		/// <summary>Does the user posses a pro account.
 		/// 0 = free acouunt, 1 = pro account holder.</summary>
 		[XmlAttribute("iconserver", Form=XmlSchemaForm.Unqualified)]
-		public int IconServer;
+		public int IconServer { get { return _iconServer; } set { _iconServer = value; } }
+	
+		/// <summary>No idea what purpose this field serves.</summary>
+		[XmlAttribute("iconfarm", Form=XmlSchemaForm.Unqualified)]
+		public int IconFarm { get { return _iconFarm; } set { _iconFarm = value; } }
 	
 		/// <summary>The users username, also known as their screenname.</summary>
 		[XmlElement("username", Form=XmlSchemaForm.Unqualified)]
-		public string UserName;
+		public string UserName { get { return _username; } set { _username = value; } }
 	
 		/// <summary>The users real name, as entered in their profile.</summary>
 		[XmlElement("realname", Form=XmlSchemaForm.Unqualified)]
-		public string RealName;
+		public string RealName { get { return _realname; } set { _realname = value; } }
+	
+		/// <summary>The SHA1 hash of the users email address - used for FOAF networking.</summary>
+		[XmlElement("mbox_sha1sum", Form=XmlSchemaForm.Unqualified)]
+		public string MailBoxSha1Hash { get { return _mboxHash; } set { _mboxHash = value; } }
 	
 		/// <summary>Consists of your current location followed by country.</summary>
 		/// <example>e.g. Newcastle, UK.</example>
 		[XmlElement("location", Form=XmlSchemaForm.Unqualified)]
-		public string Location;
+		public string Location { get { return _location; } set { _location = value; } }
 
 		/// <summary>Sub element containing a summary of the users photo information.</summary>
 		/// <remarks/>
 		[XmlElement("photos", Form=XmlSchemaForm.Unqualified)]
-		public PersonPhotosSummary PhotosSummary;
+		public PersonPhotosSummary PhotosSummary { get { return _summary; } set { _summary = value; } }
 
 		/// <summary>
 		/// The users photo location on Flickr
 		/// http://www.flickr.com/photos/username/
 		/// </summary>
 		[XmlElement("photosurl",Form=XmlSchemaForm.Unqualified)]
-		public string PhotosUrl;
+		public string PhotosUrl { get { return _photosUrl; } set { _photosUrl = value; } }
 
 		/// <summary>
 		/// The users profile location on Flickr
 		/// http://www.flickr.com/people/username/
 		/// </summary>
 		[XmlElement("profileurl",Form=XmlSchemaForm.Unqualified)]
-		public string ProfileUrl;
+		public string ProfileUrl { get { return _profileUrl; } set { _profileUrl = value; } }
 
 		/// <summary>
 		/// Returns the <see cref="Uri"/> for the users Buddy Icon.
@@ -87,6 +114,9 @@
 	[System.Serializable]
 	public class PersonPhotosSummary
 	{
+		private int _photoCount;
+		private int _views;
+
 		/// <summary>The first date the user uploaded a picture, converted into <see cref="DateTime"/> format.</summary>
 		[XmlIgnore()]
 		public DateTime FirstDate
@@ -98,19 +128,36 @@
 		[XmlIgnore()]
 		public DateTime FirstTakenDate
 		{
-			get { return Utils.UnixTimestampToDate(firsttakendate_raw); }
+			get 
+			{
+				if( firsttakendate_raw == null || firsttakendate_raw.Length == 0 ) return DateTime.MinValue;
+				return System.DateTime.Parse(firsttakendate_raw);
+			}
 		}
 
 		/// <summary>The total number of photos for the user.</summary>
 		/// <remarks/>
 		[XmlElement("count", Form=XmlSchemaForm.Unqualified)]
-		public int PhotoCount;
+		public int PhotoCount
+		{
+			get { return _photoCount; }
+			set { _photoCount = value; }
+		}
+
+		/// <summary>The total number of photos for the user.</summary>
+		/// <remarks/>
+		[XmlElement("views", Form=XmlSchemaForm.Unqualified)]
+		public int Views
+		{
+			get { return _views; }
+			set { _views = value; }
+		}
 
 		/// <remarks>The unix timestamp of the date the first photo was uploaded.</remarks>
 		[XmlElement("firstdate", Form=XmlSchemaForm.Unqualified)]
 		public string firstdate_raw;
 
-		/// <remarks>The unix timestamp of the date the first photo was uploaded.</remarks>
+		/// <remarks>The date the first photo was taken.</remarks>
 		[XmlElement("firsttakendate", Form=XmlSchemaForm.Unqualified)]
 		public string firsttakendate_raw;
 

Modified: trunk/extensions/FlickrExport/FlickrNet/Photo.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Photo.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Photo.cs	Wed Jul  2 11:21:09 2008
@@ -9,12 +9,11 @@
 	public class Photo 
 	{
     
-		private const string photoUrl = "http://static.flickr.com/{0}/{1}_{2}{3}.{4}";;
-
 		private string _photoId;
 		private string _userId;
 		private string _secret;
 		private string _server;
+		private string _farm;
 		private string _title;
 		private int _isPublic;
 		private int _isFriend;
@@ -24,7 +23,9 @@
 		private string _ownerName;
 		private string _iconServer;
 		private string _originalFormat;
+		private string _originalSecret;
 		private string _cleanTags;
+		private string _machineTags;
 		private decimal _latitude;
 		private decimal _longitude;
 		private GeoAccuracy _accuracy;
@@ -46,6 +47,10 @@
 		public string Server { get { return _server; } set { _server = value; } }
     
 		/// <remarks/>
+		[XmlAttribute("farm", Form=XmlSchemaForm.Unqualified)]
+		public string Farm { get { return _farm; } set { _farm = value; } }
+    
+		/// <remarks/>
 		[XmlAttribute("title", Form=XmlSchemaForm.Unqualified)]
 		public string Title { get { return _title; } set { _title = value; } }
     
@@ -144,18 +149,31 @@
 		public string OriginalFormat { get { return _originalFormat; } set { _originalFormat = value; } }
 
 		/// <summary>
+		/// Optional extra field containing the original 'secret' of the 
+		/// photo used for forming the Url.
+		/// </summary>
+		[XmlAttribute("originalsecret", Form=XmlSchemaForm.Unqualified)]
+		public string OriginalSecret { get { return _originalSecret; } set { _originalSecret = value; } }
+
+		/// <summary>
 		/// Undocumented tags atrribute. Renamed to CleanTags.
 		/// </summary>
 		[Obsolete("Renamed to CleanTags, as the tags are clean, not raw")]
 		public string RawTags { get { return _cleanTags; } set { _cleanTags = value; } }
 
 		/// <summary>
-		/// Undocumented tags attribute
+		/// Tags, in their clean format (exception is machine tags which retain their machine encoding).
 		/// </summary>
 		[XmlAttribute("tags", Form=XmlSchemaForm.Unqualified)]
 		public string CleanTags { get { return _cleanTags; } set { _cleanTags = value; } }
 
 		/// <summary>
+		/// Machine tags
+		/// </summary>
+		[XmlAttribute("machine_tags", Form=XmlSchemaForm.Unqualified)]
+		public string MachineTags { get { return _machineTags; } set { _machineTags = value; } }
+
+		/// <summary>
 		/// The url to the web page for this photo. Uses the users userId, not their web alias, but
 		/// will still work.
 		/// </summary>
@@ -171,7 +189,7 @@
 		[XmlIgnore()]
 		public string SquareThumbnailUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_s", "jpg"); }
+			get { return Utils.UrlFormat(this, "_s", "jpg"); }
 		}
 
 		/// <summary>
@@ -180,7 +198,7 @@
 		[XmlIgnore()]
 		public string ThumbnailUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_t", "jpg"); }
+			get { return Utils.UrlFormat(this, "_t", "jpg"); }
 		}
 
 		/// <summary>
@@ -189,7 +207,7 @@
 		[XmlIgnore()]
 		public string SmallUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_m", "jpg"); }
+			get { return Utils.UrlFormat(this, "_m", "jpg"); }
 		}
 
 		/// <summary>
@@ -200,7 +218,7 @@
 		[XmlIgnore()]
 		public string MediumUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "", "jpg"); }
+			get { return Utils.UrlFormat(this, "", "jpg"); }
 		}
 
 		/// <summary>
@@ -211,7 +229,7 @@
 		[XmlIgnore()]
 		public string LargeUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_b", "jpg"); }
+			get { return Utils.UrlFormat(this, "_b", "jpg"); }
 		}
 
 		/// <summary>
@@ -225,7 +243,7 @@
 				if( OriginalFormat == null || OriginalFormat.Length == 0 )
 					throw new InvalidOperationException("No original format information available.");
 
-				return string.Format(photoUrl, Server, PhotoId, Secret, "_o", OriginalFormat);
+				return Utils.UrlFormat(this, "_o", OriginalFormat);
 			}
 		}
 

Modified: trunk/extensions/FlickrExport/FlickrNet/PhotoInfo.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PhotoInfo.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PhotoInfo.cs	Wed Jul  2 11:21:09 2008
@@ -10,23 +10,54 @@
 	[System.Serializable]
 	public class PhotoInfo
 	{
+		private string _photoId;
+		private string _secret;
+		private string _server;
+		private string _farm;
+		private string _originalFormat;
+		private string _originalSecret;
+		private int _views;
+		private int _comments;
+		private string _title;
+		private string _description;
+		private PhotoInfoTags _tags = new PhotoInfoTags();
+
 		/// <summary>
 		/// The id of the photo.
 		/// </summary>
 		[XmlAttribute("id", Form=XmlSchemaForm.Unqualified)]
-		public string PhotoId;
+		public string PhotoId { get { return _photoId; } set { _photoId = value; } }
 
 		/// <summary>
 		/// The secret of the photo. Used to calculate the URL (amongst other things).
 		/// </summary>
 		[XmlAttribute("secret", Form=XmlSchemaForm.Unqualified)]
-		public string Secret;
+		public string Secret { get { return _secret; } set { _secret = value; } }
 
 		/// <summary>
 		/// The server on which the photo resides.
 		/// </summary>
 		[XmlAttribute("server", Form=XmlSchemaForm.Unqualified)]
-		public int Server;
+		public string Server { get { return _server; } set { _server = value; } }
+
+		/// <summary>
+		/// The server farm on which the photo resides.
+		/// </summary>
+		[XmlAttribute("farm", Form=XmlSchemaForm.Unqualified)]
+		public string Farm { get { return _farm; } set { _farm = value; } }
+
+		/// <summary>
+		/// The original format of the image (e.g. jpg, png etc).
+		/// </summary>
+		[XmlAttribute("originalformat", Form=XmlSchemaForm.Unqualified)]
+		public string OriginalFormat { get { return _originalFormat; } set { _originalFormat = value; } }
+
+		/// <summary>
+		/// Optional extra field containing the original 'secret' of the 
+		/// photo used for forming the Url.
+		/// </summary>
+		[XmlAttribute("originalsecret", Form=XmlSchemaForm.Unqualified)]
+		public string OriginalSecret { get { return _originalSecret; } set { _originalSecret = value; } }
 
 		/// <summary>
 		/// The date the photo was uploaded (or 'posted').
@@ -69,13 +100,13 @@
 		/// The title of the photo.
 		/// </summary>
 		[XmlElement("title", Form=XmlSchemaForm.Unqualified)]
-		public string Title;
+		public string Title { get { return _title; } set { _title = value; } }
 
 		/// <summary>
 		/// The description of the photo.
 		/// </summary>
 		[XmlElement("description", Form=XmlSchemaForm.Unqualified)]
-		public string Description;
+		public string Description { get { return _description; } set { _description = value; } }
 
 		/// <summary>
 		/// The visibility of the photo.
@@ -108,7 +139,19 @@
 		/// The number of comments the photo has.
 		/// </summary>
 		[XmlElement("comments", Form=XmlSchemaForm.Unqualified)]
-		public int CommentsCount;
+		public int CommentsCount
+		{
+			get { return _comments; } set { _comments = value; }
+		}
+
+		/// <summary>
+		/// The number of views the photo has.
+		/// </summary>
+		[XmlAttribute("views", Form=XmlSchemaForm.Unqualified)]
+		public int ViewCount
+		{
+			get { return _views; } set { _views = value; }
+		}
 
 		/// <summary>
 		/// The notes for the photo.
@@ -120,7 +163,11 @@
 		/// The tags for the photo.
 		/// </summary>
 		[XmlElement("tags", Form=XmlSchemaForm.Unqualified)]
-		public PhotoInfoTags Tags;
+		public PhotoInfoTags Tags
+		{
+			get { return _tags; }
+			set { _tags = (value==null?new PhotoInfoTags():value); }
+		}
 	
 		/// <summary>
 		/// The EXIF tags for the photo.
@@ -152,15 +199,13 @@
 			get { return string.Format("http://www.flickr.com/photos/{0}/{1}/";, Owner.UserId, PhotoId); }
 		}
 
-		private const string photoUrl = "http://static.flickr.com/{0}/{1}_{2}{3}.jpg";;
-
 		/// <summary>
 		/// The URL for the square thumbnail for the photo.
 		/// </summary>
 		[XmlIgnore()]
 		public string SquareThumbnailUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_s"); }
+			get { return Utils.UrlFormat(this, "_s", "jpg"); }
 		}
 
 		/// <summary>
@@ -169,7 +214,7 @@
 		[XmlIgnore()]
 		public string ThumbnailUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_t"); }
+			get { return Utils.UrlFormat(this, "_t", "jpg"); }
 		}
 
 		/// <summary>
@@ -178,7 +223,7 @@
 		[XmlIgnore()]
 		public string SmallUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_m"); }
+			get { return Utils.UrlFormat(this, "_m", "jpg"); }
 		}
 
 		/// <summary>
@@ -191,7 +236,7 @@
 		[XmlIgnore()]
 		public string MediumUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, ""); }
+			get { return Utils.UrlFormat(this, "", "jpg"); }
 		}
 
 		/// <summary>
@@ -204,7 +249,22 @@
 		[XmlIgnore()]
 		public string LargeUrl
 		{
-			get { return string.Format(photoUrl, Server, PhotoId, Secret, "_b"); }
+			get { return Utils.UrlFormat(this, "_b", "jpg"); }
+		}
+
+		/// <summary>
+		/// If <see cref="OriginalFormat"/> was returned then this will contain the url of the original file.
+		/// </summary>
+		[XmlIgnore()]
+		public string OriginalUrl
+		{
+			get 
+			{ 
+				if( OriginalFormat == null || OriginalFormat.Length == 0 )
+					throw new InvalidOperationException("No original format information available.");
+
+				return Utils.UrlFormat(this, "_o", OriginalFormat);
+			}
 		}
 	}
 
@@ -382,11 +442,17 @@
 	[System.Serializable]
 	public class PhotoInfoTags
 	{
+		private PhotoInfoTag[] _tags = new PhotoInfoTag[0];
+
 		/// <summary>
 		/// A collection of tags for the photo.
 		/// </summary>
 		[XmlElement("tag", Form=XmlSchemaForm.Unqualified)]
-		public PhotoInfoTag[] TagCollection;
+		public PhotoInfoTag[] TagCollection
+		{
+			get { return _tags; }
+			set { _tags = (value==null?new PhotoInfoTag[0]:value); }
+		}
 	}
 
 	/// <summary>
@@ -395,23 +461,28 @@
 	[System.Serializable]
 	public class PhotoInfoTag
 	{
+		private int _machineTag;
+		private string _tagId;
+		private string _authorId;
+		private string _authorName;
+
 		/// <summary>
 		/// The id of the tag.
 		/// </summary>
 		[XmlAttribute("id", Form=XmlSchemaForm.Unqualified)]
-		public string TagId;
+		public string TagId { get { return _tagId; } set { _tagId = value; } }
 
 		/// <summary>
 		/// The author id of the tag.
 		/// </summary>
 		[XmlAttribute("author", Form=XmlSchemaForm.Unqualified)]
-		public string AuthorId;
+		public string AuthorId { get { return _authorId; } set { _authorId = value; } }
 
 		/// <summary>
 		/// Author of the tag - only available if using <see cref="Flickr.TagsGetListPhoto"/>.
 		/// </summary>
 		[XmlAttribute("authorname", Form=XmlSchemaForm.Unqualified)]
-		public string AuthorName;
+		public string AuthorName  { get { return _authorName; } set { _authorName = value; } }
 
 		/// <summary>
 		/// Raw copy of the tag, as the user entered it.
@@ -420,10 +491,16 @@
 		public string Raw;
 
 		/// <summary>
+		/// Raw copy of the tag, as the user entered it.
+		/// </summary>
+		[XmlAttribute("machine_tag", Form=XmlSchemaForm.Unqualified)]
+		public int IsMachineTag { get { return _machineTag; } set { _machineTag = value; } }
+
+		/// <summary>
 		/// The actually tag.
 		/// </summary>
 		[XmlText()]
 		public string TagText;
 	}
 
-}
\ No newline at end of file
+}

Modified: trunk/extensions/FlickrExport/FlickrNet/PhotoSearchExtras.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PhotoSearchExtras.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PhotoSearchExtras.cs	Wed Jul  2 11:21:09 2008
@@ -15,6 +15,7 @@
 	/// </code>
 	/// </example>
 	[Flags]
+	[Serializable]
 	public enum PhotoSearchExtras
 	{
 		/// <summary>
@@ -50,7 +51,7 @@
 		/// </summary>
 		LastUpdated = 64,
 		/// <summary>
-		/// Undocumented Tags extra
+		/// Returns Tags attribute
 		/// </summary>
 		Tags = 128,
 		/// <summary>
@@ -58,8 +59,12 @@
 		/// </summary>
 		Geo = 256,
 		/// <summary>
+		/// Machine encoded tags
+		/// </summary>
+		MachineTags = 512,
+		/// <summary>
 		/// Returns all the above information.
 		/// </summary>
-		All = License | DateUploaded | DateTaken | OwnerName | IconServer | OriginalFormat | LastUpdated | Tags | Geo
+		All = License | DateUploaded | DateTaken | OwnerName | IconServer | OriginalFormat | LastUpdated | Tags | Geo | MachineTags
 	}
 }

Modified: trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOptions.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOptions.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOptions.cs	Wed Jul  2 11:21:09 2008
@@ -5,11 +5,14 @@
 	/// <summary>
 	/// Summary description for PhotoSearchOptions.
 	/// </summary>
+	[Serializable]
 	public class PhotoSearchOptions
 	{
 		private string _userId;
 		private string _tags;
 		private TagMode _tagMode = TagMode.None;
+		private string _machineTags;
+		private MachineTagMode _machineTagMode = MachineTagMode.None;
 		private string _text;
 		private DateTime _minUploadDate = DateTime.MinValue;
 		private DateTime _maxUploadDate = DateTime.MinValue;
@@ -117,11 +120,52 @@
 					case TagMode.Boolean:
 						return "bool";
 					default:
+						return "";
+				}
+			}
+		}
+
+		/// <summary>
+		/// Search for the given machine tags.
+		/// </summary>
+		/// <remarks>
+		/// See http://www.flickr.com/services/api/flickr.photos.search.html for details 
+		/// on how to search for machine tags.
+		/// </remarks>
+		public string MachineTags
+		{
+			get { return _machineTags; } set { _machineTags = value; }
+		}
+
+		/// <summary>
+		/// The machine tag mode. 
+		/// </summary>
+		/// <remarks>
+		/// Allowed values are any and all. It defaults to any if none specified.
+		/// </remarks>
+		public MachineTagMode MachineTagMode
+		{
+			get { return _machineTagMode; } set { _machineTagMode = value; }
+		}
+
+		internal string MachineTagModeString
+		{
+			get
+			{
+				switch(_machineTagMode)
+				{
+					case MachineTagMode.None:
+						return "";
+					case MachineTagMode.AllTags:
 						return "all";
+					case MachineTagMode.AnyTag:
+						return "any";
+					default:
+						return "";
 				}
 			}
 		}
-	
+
 		/// <summary>
 		/// Search for the given text in photo titles and descriptions.
 		/// </summary>
@@ -250,7 +294,7 @@
 			get { return _page; }
 			set 
 			{
-				if( value < 0 ) throw new ArgumentOutOfRangeException("Page", value, "Must be greater than 0");
+				if( value < 0 ) throw new ArgumentOutOfRangeException("Page", "Must be greater than 0");
 				_page = value; 
 			}
 		}

Modified: trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOrder.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOrder.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PhotoSearchOrder.cs	Wed Jul  2 11:21:09 2008
@@ -3,9 +3,10 @@
 namespace FlickrNet
 {
 	/// <summary>
-	/// The sort order for the <see cref="Flickr.PhotosSearch"/>,
-	/// <see cref="Flickr.PhotosGetWithGeoData"/>, <see cref="Flickr.PhotosGetWithoutGeoData"/> methods.
+	/// The sort order for the <see cref="Flickr.PhotosSearch(PhotoSearchOptions)"/>,
+	/// <see cref="Flickr.PhotosGetWithGeoData()"/>, <see cref="Flickr.PhotosGetWithoutGeoData()"/> methods.
 	/// </summary>
+	[Serializable]
 	public enum PhotoSearchSortOrder
 	{
 		/// <summary>

Modified: trunk/extensions/FlickrExport/FlickrNet/PhotoSets.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/PhotoSets.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/PhotoSets.cs	Wed Jul  2 11:21:09 2008
@@ -32,7 +32,13 @@
 		public Photoset[] PhotosetCollection
 		{
 			get { return _photosetCollection; }
-			set { _photosetCollection = value;}
+			set 
+			{
+				if( value== null ) 
+					_photosetCollection = new Photoset[0];
+				else
+					_photosetCollection = value;
+			}
 		}
 	}
 
@@ -47,7 +53,8 @@
 		private string _ownerId;
 		private string _primaryPhotoId;
 		private string _secret;
-		private int _server;
+		private string _server;
+		private string _farm;
 		private int _numberOfPhotos;
 		private string _title;
 		private string _description;
@@ -102,12 +109,21 @@
 		/// The server for the primary photo for the photoset.
 		/// </summary>
 		[XmlAttribute("server", Form=XmlSchemaForm.Unqualified)]
-		public int Server
+		public string Server
 		{
 			get { return _server; } set { _server = value; }
 		}
 
 		/// <summary>
+		/// The server farm for the primary photo for the photoset.
+		/// </summary>
+		[XmlAttribute("farm", Form=XmlSchemaForm.Unqualified)]
+		public string Farm
+		{
+			get { return _farm; } set { _farm = value; }
+		}
+
+		/// <summary>
 		/// The number of photos in the photoset.
 		/// </summary>
 		[XmlAttribute("photos", Form=XmlSchemaForm.Unqualified)]
@@ -140,18 +156,23 @@
 		[XmlElement("photo", Form=XmlSchemaForm.Unqualified)]
 		public Photo[] PhotoCollection
 		{
-			get { return _photoCollection; } set { _photoCollection = value; }
+			get { return _photoCollection; } 
+			set 
+			{
+				if( value == null ) 
+					_photoCollection = new Photo[0];
+				else
+					_photoCollection = value; 
+			}
 		}
 
-		private const string photoUrl = "http://static.flickr.com/{0}/{1}_{2}{3}.{4}";;
-
 		/// <summary>
 		/// The URL for the thumbnail of a photo.
 		/// </summary>
 		[XmlIgnore()]
 		public string PhotosetThumbnailUrl
 		{
-			get { return string.Format(photoUrl, Server, PrimaryPhotoId, Secret, "_t", "jpg"); }
+			get { return Utils.UrlFormat(this, "_t", "jpg"); }
 		}
 
 		/// <summary>
@@ -160,7 +181,7 @@
 		[XmlIgnore()]
 		public string PhotosetSquareThumbnailUrl
 		{
-			get { return string.Format(photoUrl, Server, PrimaryPhotoId, Secret, "_s", "jpg"); }
+			get { return Utils.UrlFormat(this, "_s", "jpg"); }
 		}
 
 		/// <summary>
@@ -169,7 +190,7 @@
 		[XmlIgnore()]
 		public string PhotosetSmallUrl
 		{
-			get { return string.Format(photoUrl, Server, PrimaryPhotoId, Secret, "_m", "jpg"); }
+			get { return Utils.UrlFormat(this, "_m", "jpg"); }
 		}
 
 

Modified: trunk/extensions/FlickrExport/FlickrNet/Photos.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Photos.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Photos.cs	Wed Jul  2 11:21:09 2008
@@ -9,10 +9,19 @@
 	[Serializable]
 	public class Photos 
 	{
-    
+
+        private Photo[] _photos = new Photo[0];
+
 		/// <remarks/>
-		[XmlElement("photo", Form=XmlSchemaForm.Unqualified)]
-		public PhotoCollection PhotoCollection = new PhotoCollection();
+        [XmlElement("photo", Form = XmlSchemaForm.Unqualified)]
+        public Photo[] PhotoCollection
+        {
+            get { return _photos; }
+			set 
+			{
+				_photos = value==null?new Photo[0]:value; 
+			}
+        }
     
 		/// <remarks/>
 		[XmlAttribute("page", Form=XmlSchemaForm.Unqualified)]
@@ -52,6 +61,8 @@
 		/// <param name="photos">An array of <see cref="Photo"/> instances.</param>
 		public PhotoCollection(Photo[] photos)
 		{
+			if (photos == null) return;
+
 			for (int i=0; i<photos.Length; i++)
 			{
 				List.Add(photos[i]);

Modified: trunk/extensions/FlickrExport/FlickrNet/Response.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Response.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Response.cs	Wed Jul  2 11:21:09 2008
@@ -39,10 +39,6 @@
 		public PhotoInfo PhotoInfo;
 
 		/// <remarks/>
-		[XmlElement("person", Form=XmlSchemaForm.Unqualified)]
-		public Person Person;
-    
-		/// <remarks/>
 		[XmlElement("photoset", Form=XmlSchemaForm.Unqualified)]
 		public Photoset Photoset;
 
@@ -128,6 +124,12 @@
 	public enum ResponseStatus
 	{
 		/// <summary>
+		/// An unknown status, and the default value if not set.
+		/// </summary>
+		[XmlEnum("unknown")]
+		Unknown,
+
+		/// <summary>
 		/// The response returns "ok" on a successful execution of the method.
 		/// </summary>
 		[XmlEnum("ok")]

Added: trunk/extensions/FlickrExport/FlickrNet/ResponseXmlException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/ResponseXmlException.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,18 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Exception thrown when an error parsing the returned XML.
+	/// </summary>
+	public class ResponseXmlException : FlickrException
+	{
+		internal ResponseXmlException(string message) : base(message)
+		{
+		}
+
+		internal ResponseXmlException(string message, Exception innerException) : base(message, innerException)
+		{
+		}
+	}
+}

Added: trunk/extensions/FlickrExport/FlickrNet/SafeNativeMethods.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/SafeNativeMethods.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,26 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Summary description for SafeNativeMethods.
+	/// </summary>
+#if !WindowsCE
+	[System.Security.SuppressUnmanagedCodeSecurity()]
+#endif
+    internal class SafeNativeMethods 
+	{
+		private SafeNativeMethods()
+		{
+		}
+
+		internal static int GetErrorCode(System.IO.IOException ioe)
+		{
+#if !WindowsCE
+			return System.Runtime.InteropServices.Marshal.GetHRForException(ioe) & 0xFFFF;
+#else
+            return 0;
+#endif
+		}
+	}
+}

Added: trunk/extensions/FlickrExport/FlickrNet/SignatureRequiredException.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/FlickrExport/FlickrNet/SignatureRequiredException.cs	Wed Jul  2 11:21:09 2008
@@ -0,0 +1,14 @@
+using System;
+
+namespace FlickrNet
+{
+	/// <summary>
+	/// Thrown when a method requires a valid signature but no shared secret has been supplied.
+	/// </summary>
+	public class SignatureRequiredException : FlickrException
+	{
+		internal SignatureRequiredException() : base("Method requires signing but no shared secret supplied.")
+		{
+		}
+	}
+}

Modified: trunk/extensions/FlickrExport/FlickrNet/Tags.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Tags.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Tags.cs	Wed Jul  2 11:21:09 2008
@@ -4,7 +4,7 @@
 namespace FlickrNet
 {
 	/// <summary>
-	/// A simple tag class, containing a tag name and optional count (for <see cref="Flickr.TagsGetListUserPopular"/>)
+	/// A simple tag class, containing a tag name and optional count (for <see cref="Flickr.TagsGetListUserPopular()"/>)
 	/// </summary>
 	public class Tag
 	{

Modified: trunk/extensions/FlickrExport/FlickrNet/Uploader.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Uploader.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Uploader.cs	Wed Jul  2 11:21:09 2008
@@ -13,13 +13,13 @@
 	{
 		private ResponseStatus _status;
 		private string _photoId;
-		private int _code;
-		private string _message;
+		private string _ticketId;
+		private ResponseError _error;
 
 		/// <summary>
 		/// The status of the upload, either "ok" or "fail".
 		/// </summary>
-		[XmlElement("status", Form=XmlSchemaForm.Unqualified)]
+		[XmlAttribute("stat", Form=XmlSchemaForm.Unqualified)]
 		public ResponseStatus Status
 		{
 			get { return _status; }
@@ -37,23 +37,23 @@
 		}
 
 		/// <summary>
-		/// If the upload failed then this contains the error code.
+		/// The ticket id, if using Asynchronous uploading.
 		/// </summary>
-		[XmlElement("error", Form=XmlSchemaForm.Unqualified)]
-		public int Code
+		[XmlElement("ticketid", Form=XmlSchemaForm.Unqualified)]
+		public string TicketId
 		{
-			get { return _code; }
-			set { _code = value; }
+			get { return _ticketId; }
+			set { _ticketId = value; }
 		}
 
 		/// <summary>
-		/// If the upload failed then this contains the error description.
+		/// Contains the error returned if the upload is unsuccessful.
 		/// </summary>
-		[XmlElement("verbose", Form=XmlSchemaForm.Unqualified)]
-		public string Message
+		[XmlElement("err", Form=XmlSchemaForm.Unqualified)]
+		public ResponseError Error
 		{
-			get { return _message; }
-			set { _message = value; }
+			get { return _error; }
+			set { _error = value; }
 		}
 	}
 }

Modified: trunk/extensions/FlickrExport/FlickrNet/User.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/User.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/User.cs	Wed Jul  2 11:21:09 2008
@@ -141,4 +141,4 @@
 			get { return BandwidthUsed * 1.0 / BandwidthMax; }
 		}
 	}
-}
+}
\ No newline at end of file

Modified: trunk/extensions/FlickrExport/FlickrNet/Utils.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrNet/Utils.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrNet/Utils.cs	Wed Jul  2 11:21:09 2008
@@ -1,14 +1,16 @@
 using System;
 using System.IO;
-using System.IO.IsolatedStorage;
 using System.Collections;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml.Serialization;
 
 namespace FlickrNet
 {
 	/// <summary>
 	/// Internal class providing certain utility functions to other classes.
 	/// </summary>
-	public sealed class Utils
+	internal sealed class Utils
 	{
 		private static readonly DateTime unixStartDate = new DateTime(1970, 1, 1, 0, 0, 0);
 
@@ -16,6 +18,7 @@
 		{
 		}
 
+#if !WindowsCE
 		internal static string UrlEncode(string oldString)
 		{
 			if( oldString == null ) return null;
@@ -26,13 +29,39 @@
 			a = a.Replace(" ", "%20");
 			return a;
 		}
+#else
+        internal static string UrlEncode(string oldString)
+        {
+            if (oldString == null) return String.Empty;
+            StringBuilder sb = new StringBuilder(oldString.Length * 2);
+            Regex reg = new Regex("[a-zA-Z0-9$-_.+!*'(),]");
+
+            foreach (char c in oldString)
+            {
+                if (reg.IsMatch(c.ToString()))
+                {
+                    sb.Append(c);
+                }
+                else
+                {
+                    sb.Append(ToHex(c));
+                }
+            }
+            return sb.ToString();
+        }
+
+        private static string ToHex(char c)
+        {
+            return ((int)c).ToString("X");
+        }
+#endif
 
 		/// <summary>
 		/// Converts a <see cref="DateTime"/> object into a unix timestamp number.
 		/// </summary>
 		/// <param name="date">The date to convert.</param>
 		/// <returns>A long for the number of seconds since 1st January 1970, as per unix specification.</returns>
-		public static long DateToUnixTimestamp(DateTime date)
+		internal static long DateToUnixTimestamp(DateTime date)
 		{
 			TimeSpan ts = date - unixStartDate;
 			return (long)ts.TotalSeconds;
@@ -43,7 +72,7 @@
 		/// </summary>
 		/// <param name="timestamp">The timestamp, as a string.</param>
 		/// <returns>The <see cref="DateTime"/> object the time represents.</returns>
-		public static DateTime UnixTimestampToDate(string timestamp)
+		internal static DateTime UnixTimestampToDate(string timestamp)
 		{
 			if( timestamp == null || timestamp.Length == 0 ) return DateTime.MinValue;
 
@@ -55,7 +84,7 @@
 		/// </summary>
 		/// <param name="timestamp">The unix timestamp.</param>
 		/// <returns>The <see cref="DateTime"/> object the time represents.</returns>
-		public static DateTime UnixTimestampToDate(long timestamp)
+		internal static DateTime UnixTimestampToDate(long timestamp)
 		{
 			return unixStartDate.AddSeconds(timestamp);
 		}
@@ -65,15 +94,15 @@
 		/// </summary>
 		/// <example>
 		/// <code>
-        ///     PhotoSearchExtras extras = PhotoSearchExtras.DateTaken &amp; PhotoSearchExtras.IconServer;
+		///     PhotoSearchExtras extras = PhotoSearchExtras.DateTaken &amp; PhotoSearchExtras.IconServer;
 		///     string val = Utils.ExtrasToString(extras);
 		///     Console.WriteLine(val);
-        /// </code>
-        /// outputs: "date_taken,icon_server";
+		/// </code>
+		/// outputs: "date_taken,icon_server";
 		/// </example>
 		/// <param name="extras"></param>
-        /// <returns></returns>
-		public static string ExtrasToString(PhotoSearchExtras extras)
+		/// <returns></returns>
+		internal static string ExtrasToString(PhotoSearchExtras extras)
 		{
 			System.Text.StringBuilder sb = new System.Text.StringBuilder();
 			if( (extras & PhotoSearchExtras.DateTaken) == PhotoSearchExtras.DateTaken )
@@ -230,5 +259,93 @@
 			}
 			return new string(chars);
 		}
+	
+		private const string photoUrl = "http://farm{0}.static.flickr.com/{1}/{2}_{3}{4}.{5}";;
+
+		internal static string UrlFormat(Photo p, string size, string format)
+		{
+			if( size == "_o" )
+				return UrlFormat(photoUrl, p.Farm, p.Server, p.PhotoId, p.OriginalSecret, size, format);
+			else
+				return UrlFormat(photoUrl, p.Farm, p.Server, p.PhotoId, p.Secret, size, format);
+		}
+
+		internal static string UrlFormat(PhotoInfo p, string size, string format)
+		{
+			if( size == "_o" )
+				return UrlFormat(photoUrl, p.Farm, p.Server, p.PhotoId, p.OriginalSecret, size, format);
+			else
+				return UrlFormat(photoUrl, p.Farm, p.Server, p.PhotoId, p.Secret, size, format);
+		}
+
+		internal static string UrlFormat(Photoset p, string size, string format)
+		{
+			return UrlFormat(photoUrl, p.Farm, p.Server, p.PrimaryPhotoId, p.Secret, size, format);
+		}
+
+		private static string UrlFormat(string format, params object[] parameters)
+		{
+			return String.Format(format, parameters);
+		}
+
+		private static readonly Hashtable _serializers = new Hashtable();
+
+		private static XmlSerializer GetSerializer(Type type)
+		{
+			if( _serializers.ContainsKey(type.Name) )
+				return (XmlSerializer)_serializers[type.Name];
+			else
+			{
+				XmlSerializer s = new XmlSerializer(type);
+				_serializers.Add(type.Name, s);
+				return s;
+			}
+		}
+		/// <summary>
+		/// Converts the response string (in XML) into the <see cref="Response"/> object.
+		/// </summary>
+		/// <param name="responseString">The response from Flickr.</param>
+		/// <returns>A <see cref="Response"/> object containing the details of the </returns>
+		internal static Response Deserialize(string responseString)
+		{
+			XmlSerializer serializer = GetSerializer(typeof(FlickrNet.Response));
+			try
+			{
+				// Deserialise the web response into the Flickr response object
+				StringReader responseReader = new StringReader(responseString);
+				FlickrNet.Response response = (FlickrNet.Response)serializer.Deserialize(responseReader);
+				responseReader.Close();
+
+				return response;
+			}
+			catch(InvalidOperationException ex)
+			{
+				// Serialization error occurred!
+				throw new ResponseXmlException("Invalid response received from Flickr.", ex);
+			}
+		}
+
+		internal static object Deserialize(System.Xml.XmlNode node, Type type)
+		{
+			XmlSerializer serializer = GetSerializer(type);
+			try
+			{
+				// Deserialise the web response into the Flickr response object
+				System.Xml.XmlNodeReader reader = new System.Xml.XmlNodeReader(node);
+				object o = serializer.Deserialize(reader);
+				reader.Close();
+
+				return o;
+			}
+			catch(InvalidOperationException ex)
+			{
+				// Serialization error occurred!
+				throw new ResponseXmlException("Invalid response received from Flickr.", ex);
+			}
+		}
+
+
+
 	}
+
 }

Modified: trunk/extensions/FlickrExport/FlickrRemote.cs
==============================================================================
--- trunk/extensions/FlickrExport/FlickrRemote.cs	(original)
+++ trunk/extensions/FlickrExport/FlickrRemote.cs	Wed Jul  2 11:21:09 2008
@@ -65,7 +65,7 @@
 		if (licenses == null) {
 			try {
 				licenses = flickr.PhotosLicensesGetInfo(); 
-			} catch (FlickrNet.FlickrException e ) {
+			} catch (FlickrNet.FlickrApiException e ) {
 				Console.WriteLine ( e.Code + ": " + e.Verbose );
 				return null;
 			}
@@ -118,7 +118,7 @@
 				flickr.AuthToken = token;
 
 				return auth;
-			} catch (FlickrNet.FlickrException ex) {
+			} catch (FlickrNet.FlickrApiException ex) {
 				Console.WriteLine ("ERROR: Problems login in Flickr - "+ex.Verbose);
 
 				return null;



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