banshee r4901 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Web src/Extensions/Banshee.Podcasting src/Extensions/Banshee.Podcasting/Banshee.Podcasting



Author: gburt
Date: Sun Jan 11 02:01:46 2009
New Revision: 4901
URL: http://svn.gnome.org/viewvc/banshee?rev=4901&view=rev

Log:
2009-01-10  Gabriel Burt  <gabriel burt gmail com>

	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs:
	* src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs:
	* src/Extensions/Banshee.Podcasting/Makefile.am: Add support for itms://
	podcast links that you see on many podcast websites (BNC #465149).
	I think setting Banshee as the app Firefox (etc) uses when they are
	clicked has to be done manually, unfortunately

	* src/Core/Banshee.Services/Banshee.Web/HttpRequest.cs: Transparently
	support gzip'd responses, add ResponseBody property.



Added:
   trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Services/Banshee.Web/HttpRequest.cs
   trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
   trunk/banshee/src/Extensions/Banshee.Podcasting/Makefile.am

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Web/HttpRequest.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Web/HttpRequest.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Web/HttpRequest.cs	Sun Jan 11 02:01:46 2009
@@ -31,6 +31,8 @@
 using System.Net;
 using System.Collections.Generic;
 
+using ICSharpCode.SharpZipLib.GZip;
+
 using Banshee.Base;
 using Banshee.ServiceStack;
 using Banshee.Networking;
@@ -115,7 +117,7 @@
         
         public void DumpResponseStream ()
         {
-            using (Stream stream = response.GetResponseStream ()) {
+            using (Stream stream = GetResponseStream ()) {
                 StreamReader reader = new StreamReader (stream);
                 Console.WriteLine (reader.ReadToEnd ());
                 reader.Dispose ();
@@ -162,6 +164,29 @@
         public HttpWebResponse Response {
             get { return response; }
         }
+
+        public Stream GetResponseStream ()
+        {
+            return response.ContentEncoding == "gzip"
+                ? new GZipInputStream (response.GetResponseStream ())
+                : response.GetResponseStream ();
+        }
+
+        private string response_body;
+        public string ResponseBody {
+            get {
+                if (response_body == null) {
+                    GetResponse ();
+                    using (Stream stream = GetResponseStream ()) {
+                        StreamReader reader = new StreamReader (stream);
+                        response_body = reader.ReadToEnd ();
+                        reader.Dispose ();
+                    }
+                }
+
+                return response_body;
+            }
+        }
         
         private static TimeSpan default_timeout = TimeSpan.FromSeconds (20);
         protected virtual TimeSpan Timeout {

Added: trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/ItmsPodcast.cs	Sun Jan 11 02:01:46 2009
@@ -0,0 +1,104 @@
+//
+// ItmsPodcast.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Text.RegularExpressions;
+
+using Banshee.Web;
+
+namespace Banshee.Podcasting
+{
+    public class ItmsPodcast
+    {  
+        private string itms_uri;
+        private string feed_url;
+        private string xml;
+
+        public ItmsPodcast (string itmsUri)
+        {
+            Fetch (itmsUri, 2);
+
+            feed_url = GetString ("feedURL");
+            
+            // <key>podcastName</key>
+            // <string>This Week in Django - MP3 Edition</string>
+        }
+
+        public string FeedUrl {
+            get { return feed_url; }
+        }
+
+        private void Fetch (string url, int tries)
+        {
+            url = url.Replace ("itms://", "http://";);
+
+            // Get rid of all the url variables except the id
+            int args_start = url.IndexOf ("?");
+            Regex id_regex = new Regex ("[?&]id=(\\d+)", RegexOptions.IgnoreCase);
+            Match match = id_regex.Match (url, args_start);
+            url = String.Format ("{0}?id={1}",
+                url.Substring (0, args_start),
+                match.Groups[1]
+            );
+
+            using (HttpRequest req = new HttpRequest (url)) {
+                req.Request.KeepAlive = true;
+                req.Request.Accept = "*/*";
+                req.GetResponse ();
+
+                if (req.Response.ContentType.StartsWith ("text/html")) {
+                    if (tries > 0) {
+                        string start = "onload=\"return itmsOpen('";
+                        string rsp_body = req.ResponseBody;
+                        int value_start = rsp_body.IndexOf (start) + start.Length;
+                        int value_end   = rsp_body.IndexOf ("','", value_start);
+                        string new_url  = rsp_body.Substring (value_start, value_end - value_start);
+                        new_url = System.Web.HttpUtility.HtmlDecode (new_url);
+                        Fetch (new_url, tries--);
+                    }
+                } else {
+                    xml = req.ResponseBody;
+                    itms_uri = url;
+                }
+            }
+        }
+
+        private string GetString (string key_name)
+        {
+            try {
+                int entry_start = xml.IndexOf (String.Format ("<key>{0}</key>", key_name));
+                int value_start = xml.IndexOf ("<string>", entry_start) + 8;
+                int value_end   = xml.IndexOf ("</string>", value_start);
+                return xml.Substring (value_start, value_end - value_start);
+            } catch (Exception) {
+                throw new Exception (String.Format (
+                    "Unable to get value for {0} from {1}", key_name, itms_uri));
+            }
+        }
+    }
+}

Modified: trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Podcasting/Banshee.Podcasting/PodcastService.cs	Sun Jan 11 02:01:46 2009
@@ -306,14 +306,30 @@
                 } catch (Exception e) {
                     Log.Exception (e);
                 }
-            } else if (uri.Contains ("xml") || uri.Contains ("rss") || uri.Contains ("feed") || uri.StartsWith ("itpc")) {
+            } else if (uri.Contains ("xml") || uri.Contains ("rss") || uri.Contains ("feed") || uri.StartsWith ("itpc") || uri.StartsWith ("pcast")) {
                 if (uri.StartsWith ("feed://") || uri.StartsWith ("itpc://")) {
                     uri = String.Format ("http://{0}";, uri.Substring (7));
+                } else if (uri.StartsWith ("pcast://")) {
+                    uri = String.Format ("http://{0}";, uri.Substring (8));
                 }
 
                 // TODO replace autodownload w/ actual default preference
                 FeedsManager.Instance.FeedManager.CreateFeed (uri, FeedAutoDownload.None);
                 source.NotifyUser ();
+            } else if (uri.StartsWith ("itms://")) {
+                System.Threading.ThreadPool.QueueUserWorkItem (delegate {
+                    try {
+                        string feed_url = new ItmsPodcast (uri).FeedUrl;
+                        if (feed_url != null) {
+                            ThreadAssist.ProxyToMain (delegate {
+                                FeedsManager.Instance.FeedManager.CreateFeed (feed_url, FeedAutoDownload.None);
+                                source.NotifyUser ();
+                            });
+                        }
+                    } catch (Exception e) {
+                        Hyena.Log.Exception (e);
+                    }
+                });
             }
         }
         

Modified: trunk/banshee/src/Extensions/Banshee.Podcasting/Makefile.am
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Podcasting/Makefile.am	(original)
+++ trunk/banshee/src/Extensions/Banshee.Podcasting/Makefile.am	Sun Jan 11 02:01:46 2009
@@ -30,6 +30,7 @@
 	Banshee.Podcasting.Gui/PodcastManager/Dialog/SyncPreferenceComboBox.cs \
 	Banshee.Podcasting.Gui/PodcastSourceContents.cs \
 	Banshee.Podcasting.Gui/PodcastUnheardFilterView.cs \
+	Banshee.Podcasting/ItmsPodcast.cs \
 	Banshee.Podcasting/PodcastImageFetchJob.cs \
 	Banshee.Podcasting/PodcastImportManager.cs \
 	Banshee.Podcasting/PodcastQuery.cs \



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