<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>
<script runat="server">
    /*
     * The code below was hacked together quite quickly - it is not an example
     * of well structured, efficient c#. The string manipulation could probably
     * have been done more neatly with Regular Expressions - it was faster for
     * me to write the Extract() method than lookup the regex syntax... I can
     * never remember that stuff.
     *
     * It was inspired by these blog posts
     * http://conceptdev.blogspot.com/2008/12/using-seadragon-iphone-with-photozoom.html
     * http://conceptdev.blogspot.com/2008/12/seadragon-returns-deep-zoom-on-iphone.html
     * and the instructions here
     * http://livelabs.com/seadragon-mobile/using-your-own-images/
     * 
     * Upload your photos to 
     * http://photozoom.mslivelabs.com/
     * via the website or Deep Zoom Composer to give it a try.
     * 
     * Feel free to modify the code below for your own use.
     * 
     * Craig Dunn  29-Dec-2008
     */
 
    /// <summary>
    /// Represents a specific DeepZoom image on PhotoZoom
    /// eg. http://photozoom.mslivelabs.com/Album.aspx?alias=mike&album=1
    /// </summary>
    class Album
    {
        public string Name;
        public string Thumbnail;
        public string SilverlightPageUrl;
        public string DeepZoomCollectionUrl;
        public string UniqueIdentifier;
        public string SourceUrl;
 
        /// <summary>Useful for debugging</summary>
        public string ToHtml() {
            return String.Format("album [{0}] preview <img src='{1}' /> dzi <a href='http://photozoom.mslivelabs.com/{2}'>silverlight</a> <a href='{3}'>xml</a><br />", Name, Thumbnail, SilverlightPageUrl, DeepZoomCollectionUrl);
        }
    }
 
    /// <summary>
    /// Collection of albums to display in the RSS feed.
    /// Extracted from a PhotoZoom 'user' page, 
    /// eg. http://photozoom.mslivelabs.com/Albums.aspx?alias=eflaten
    /// </summary>
    List<Album> Albums = new List<Album>();
    
    /// <summary>
    /// PhotoZoom user name eg. craig
    /// </summary>
    string Author = "";
    
    /// <summary>
    /// 1. Get the username from querystring parameter
    /// 2. Download the PhotoZoom 'index' page for that username
    /// 3. Extract all the album data (Url, thumbnail image) from the 'index' page
    /// 4. Download each individual album page to extract the Deep Zoom image/collection Xml Url
    /// 5. Display as an RSS feed according to http://livelabs.com/seadragon-mobile/using-your-own-images/
    /// </summary>
    void Page_Load()
    {
        Author = Convert.ToString(Request.QueryString["user"]);
        if (String.IsNullOrEmpty(Author)) Author = "craig"; // that's me 
 
        Uri uri = new Uri("http://photozoom.mslivelabs.com/Albums.aspx?alias=" + Author);
        string content = DownloadUri(uri);
        string div; int last = 0;
        do /* for each Album in the user index */
        {   
            div = Extract(content, @"<div class=""individualAlbumView"">", "</div>", ref last);
            string h2 = Extract(div, @"<h2>", "</h2>");
            string p = Extract(div, @"<p>", "</p>");
            if (p.Length > 0 && h2.Length > 0)
            {   // we have album _with_ content (ie. not empty)
                string albumName = "";
                Album album = new Album();
 
                album.SilverlightPageUrl = AHref(h2).Replace("&amp;", "&");
                album.Thumbnail = ImgSrc(p, ref albumName).Replace("&", "&amp;");
                album.Name = Server.HtmlEncode(albumName).Replace("&", "&amp;");
 
                string silverlightPageUrl = "http://photozoom.mslivelabs.com/" + album.SilverlightPageUrl;
                Uri uri2 = new Uri(silverlightPageUrl);
                div = DownloadUri(uri2);
                string objectTag = Extract(div, @"<object id=""PhotoZoomCollectionViewer""", "</object>");
                string param = Extract(objectTag, @"collectionUrl=", @"""");
                album.DeepZoomCollectionUrl = Server.UrlDecode(Server.HtmlDecode(param));
                album.UniqueIdentifier = Guid.NewGuid().ToString();
                album.SourceUrl = (silverlightPageUrl + "&indPics=true").Replace("&", "&amp;");
                Albums.Add(album);
                //Response.Write(album.ToHtml());   // debug
            }
            else
            {
                // empty album / test albums can appear in PhotoZoom - but are not useful
            }
        } while (div.Length > 0);
 
        Response.ContentType = "text/xml";
    }
 
    /// <summary>
    /// Download content (as text) from a supplied link
    /// </summary>
    /// <remarks>
    /// Copied this chunk of code from www.searcharoo.net code base.
    /// </remarks>
    /// <param name="uri">Html page to retrieve</param>
    /// <returns>Html string</returns>
    private string DownloadUri(Uri uri)
    {
        string content = "", Encoding = "";
        System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(uri.AbsoluteUri);
        req.AllowAutoRedirect = true;
        req.MaximumAutomaticRedirections = 3;
        req.UserAgent = "Mozilla/6.0 (MSIE 6.0; Windows NT 5.1; ROBOT; DeepZoomPublisher.com)";
        req.KeepAlive = true;
        req.Timeout = 3 * 1000; // 3 secinds
        // Get the stream from the returned web response
        System.Net.HttpWebResponse webresponse = null;
        try
        {
            webresponse = (System.Net.HttpWebResponse)req.GetResponse();
        }
        catch { }
        if (webresponse != null)
        {
            string enc = "utf-8"; // default
            if (webresponse.ContentEncoding != String.Empty)
            {
                // Use the HttpHeader Content-Type in preference to the one set in META
                Encoding = webresponse.ContentEncoding;
            }
            else if (Encoding == String.Empty)
            {
                Encoding = enc; // default
            }
            //http://www.c-sharpcorner.com/Code/2003/Dec/ReadingWebPageSources.asp
            using (System.IO.StreamReader stream = new System.IO.StreamReader
                (webresponse.GetResponseStream(), System.Text.Encoding.GetEncoding(Encoding)))
            {
                content = stream.ReadToEnd();//this.All = stream.ReadToEnd();
            }
        }
        return content;
    }
 
    /// <summary>
    /// Find and return the characters between two strings
    /// </summary>
    /// <returns>string found between the supplied strings, or String.Empty</returns>
    private string Extract(string from, string start, string to)
    {
        int i = 0;
        return Extract(from, start, to, ref i);
    }
    /// <summary>
    /// Find and return the characters between two strings
    /// </summary>
    /// <returns>string found between the supplied strings, or String.Empty</returns>
    /// <param name="last">
    /// returns the 'last' found index, so subsequent calls to this method 
    /// can begin searching _after_ that match
    /// </param>
    private string Extract(string from, string start, string to, ref int last)
    {
        string ret = "";
        int startPos = from.IndexOf(start, last);
        if (startPos > 0)
        {
            int endPos = from.IndexOf(to, startPos);
            if (endPos > startPos)
            {
                ret = from.Substring(startPos + start.Length, endPos - startPos - start.Length );
                last = endPos + to.Length;
            }
        }
        return ret;
    }
 
    /// <summary>
    /// Extract the url from a link tag
    /// </summary>
    /// <remarks>
    /// Copied this chunk of code from www.searcharoo.net code base.
    /// </remarks>
    /// <param name="from">string containing an html anchor tag</param>
    /// <returns>the href from the anchor tag</returns>
    private string AHref(string from)
    {
        string link = String.Empty;
        foreach (Match match in Regex.Matches(from
                , @"(?<anchor><\s*(a|area|frame|iframe|img)\s*(?:(?:\b\w+\b\s*(?:=\s*(?:""[^""]*""|'[^']*'|[^""'<> ]+)\s*)?)*)?\s*>)"
                , RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
        {
            // Parse ALL attributes from within tags... IMPORTANT when they're out of order!!
            // in addition to the 'href' attribute, there might also be 'alt', 'class', 'style', 'area', etc...
            // there might also be 'spaces' between the attributes and they may be ", ', or unquoted
            foreach (Match submatch in Regex.Matches(match.Value.ToString()
                , @"(?<name>\b\w+\b)\s*=\s*(""(?<value>[^""]*)""|'(?<value>[^']*)'|(?<value>[^""'<> \s]+)\s*)+"
                , RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
            {
                if ("href" == submatch.Groups[1].ToString().ToLower())
                {
                    link = submatch.Groups[2].ToString();
                }
            }
            if (link != String.Empty) break;
        }
        return link;
    }
 
    /// <summary>
    /// Extract the source and alt-text from an image tag
    /// </summary>
    /// <remarks>
    /// Copied this chunk of code from www.searcharoo.net code base.
    /// </remarks>
    /// <param name="from">string containing an html image tag</param>
    /// <param name="alt">returns the alt text of the image, if present</param>
    /// <returns>the url to the image source</returns>
    private string ImgSrc(string from, ref string alt)
    {
        string link = String.Empty;
        foreach (Match match in Regex.Matches(from
                , @"(?<anchor><\s*(a|area|frame|iframe|img)\s*(?:(?:\b\w+\b\s*(?:=\s*(?:""[^""]*""|'[^']*'|[^""'<> ]+)\s*)?)*)?\s*/>)"
                , RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
        {
            // Parse ALL attributes from within tags... IMPORTANT when they're out of order!!
            // in addition to the 'href' attribute, there might also be 'alt', 'class', 'style', 'area', etc...
            // there might also be 'spaces' between the attributes and they may be ", ', or unquoted
            foreach (Match submatch in Regex.Matches(match.Value.ToString()
                , @"(?<name>\b\w+\b)\s*=\s*(""(?<value>[^""]*)""|'(?<value>[^']*)'|(?<value>[^""'<> \s]+)\s*)+"
                , RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
            {
                if ("src" == submatch.Groups[1].ToString().ToLower())
                {   // [v6] indexes images <img src="???">
                    link = submatch.Groups[2].ToString();
                }
                if ("alt" == submatch.Groups[1].ToString().ToLower())
                {
                    alt = submatch.Groups[2].ToString();
                }
            }
            if (link != String.Empty) break;
        }
        return link;
    }
</script><?xml version="1.0"?>
<rss version="2.0">
    <channel>
        
        <title>PhotoZoom <%=Author %></title>
        <link>deepzoompublisher.com/PhotoZoom</link>
        <description>Rss feed generator for Microsoft Labs PhotoZoom</description>
        <language>en-us</language>
        <%foreach (Album album in Albums)
          {%>
        <item>
            <category>Photos</category>
            <guid><%=album.UniqueIdentifier%></guid>
            <title><%=album.Name %></title>
            <source url="<%=album.SourceUrl %>"><%=Author %> on PhotoZoom</source>
            <enclosure type="text/xml" length="0"
                url="<%=album.DeepZoomCollectionUrl%>" />
            <enclosure type="image/jpeg" length="0"
                url="<%=album.Thumbnail %>" />
        </item>
        <%} %>
        
    </channel>
</rss>