private IBlogProviderButtonNotification GetButtonNotification()
        {
            string notificationUrl = String.Format(
                CultureInfo.InvariantCulture,
                "{0}?blog_id={1}&button_id={2}&image_url={3}",
                NotificationUrl,
                HttpUtility.UrlEncode(_hostBlogId),
                HttpUtility.UrlEncode(_buttonId),
                HttpUtility.UrlEncode(ImageUrl));

            // get the content
            HttpWebResponse response    = null;
            XmlDocument     xmlDocument = new XmlDocument();

            try
            {
                using (Blog blog = new Blog(_blogId))
                    response = blog.SendAuthenticatedHttpRequest(notificationUrl, 10000);

                // parse the results
                xmlDocument.Load(response.GetResponseStream());
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            // create namespace manager
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);

            nsmgr.AddNamespace("n", "http://schemas.microsoft.com/wlw/buttons/notification");

            // throw if the root element is not manifest
            if (xmlDocument.DocumentElement.LocalName.ToLower(CultureInfo.InvariantCulture) != "notification")
            {
                throw new ArgumentException("Not a valid writer button notification");
            }

            // polling interval
            int checkAgainMinutes = XmlHelper.NodeInt(xmlDocument.SelectSingleNode("//n:checkAgainMinutes", nsmgr), 0);

            if (checkAgainMinutes == 0)
            {
                throw new ArgumentException("You must specify a value for checkAgainMinutes");
            }
            TimeSpan pollingInterval = TimeSpan.FromMinutes(checkAgainMinutes);

            // notification text
            string notificationText = XmlHelper.NodeText(xmlDocument.SelectSingleNode("//n:text", nsmgr));

            // notification image
            Bitmap notificationImage    = null;
            string notificationImageUrl = XmlHelper.NodeText(xmlDocument.SelectSingleNode("//n:imageUrl", nsmgr));

            if (notificationImageUrl != String.Empty)
            {
                // compute the absolute url then allow parameter substitution
                notificationImageUrl = BlogClientHelper.GetAbsoluteUrl(notificationImageUrl, NotificationUrl);
                notificationImageUrl = BlogClientHelper.FormatUrl(notificationImageUrl, _homepageUrl, _postApiUrl, _hostBlogId);

                // try to download it (will use the cache if available)
                // note that failing to download it is a recoverable error, we simply won't show a notification image
                try
                {
                    // try to get a credentials context for the download
                    WinInetCredentialsContext credentialsContext = null;
                    try
                    {
                        credentialsContext = BlogClientHelper.GetCredentialsContext(_blogId, notificationImageUrl);
                    }
                    catch (BlogClientOperationCancelledException)
                    {
                    }

                    // execute the download
                    notificationImage = ImageHelper.DownloadBitmap(notificationImageUrl, credentialsContext);
                }
                catch (Exception ex)
                {
                    Trace.WriteLine("Error downloading notification image: " + ex.ToString());
                }
            }

            // clear notification on click
            bool clearNotificationOnClick = XmlHelper.NodeBool(xmlDocument.SelectSingleNode("//n:resetOnClick", nsmgr), true);

            // return the notification
            return(new BlogProviderButtonNotification(pollingInterval, notificationText, notificationImage, clearNotificationOnClick));
        }
        private WriterEditingManifest(WriterEditingManifestDownloadInfo downloadInfo, XmlDocument xmlDocument, IBlogClient blogClient, IBlogCredentialsAccessor credentials)
        {
            // record blog client and credentials
            _blogClient  = blogClient;
            _credentials = credentials;

            // record download info
            if (UrlHelper.IsUrl(downloadInfo.SourceUrl))
            {
                _downloadInfo = downloadInfo;
            }

            // only process an xml document if we got one
            if (xmlDocument == null)
            {
                return;
            }

            // create namespace manager
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);

            nsmgr.AddNamespace("m", "http://schemas.microsoft.com/wlw/manifest/weblog");

            // throw if the root element is not manifest
            if (xmlDocument.DocumentElement.LocalName.ToUpperInvariant() != "MANIFEST")
            {
                throw new ArgumentException("Not a valid writer editing manifest");
            }

            // get button descriptions
            _buttonDescriptions = new IBlogProviderButtonDescription[] { };
            XmlNode buttonsNode = xmlDocument.SelectSingleNode("//m:buttons", nsmgr);

            if (buttonsNode != null)
            {
                ArrayList buttons = new ArrayList();

                foreach (XmlNode buttonNode in buttonsNode.SelectNodes("m:button", nsmgr))
                {
                    try
                    {
                        // id
                        string id = XmlHelper.NodeText(buttonNode.SelectSingleNode("m:id", nsmgr));
                        if (id == String.Empty)
                        {
                            throw new ArgumentException("Missing id field");
                        }

                        // title
                        string description = XmlHelper.NodeText(buttonNode.SelectSingleNode("m:text", nsmgr));
                        if (description == String.Empty)
                        {
                            throw new ArgumentException("Missing text field");
                        }

                        // imageUrl
                        string imageUrl = XmlHelper.NodeText(buttonNode.SelectSingleNode("m:imageUrl", nsmgr));
                        if (imageUrl == String.Empty)
                        {
                            throw new ArgumentException("Missing imageUrl field");
                        }

                        // download the image
                        Bitmap image = DownloadImage(imageUrl, downloadInfo.SourceUrl);

                        // clickUrl
                        string clickUrl = BlogClientHelper.GetAbsoluteUrl(XmlHelper.NodeText(buttonNode.SelectSingleNode("m:clickUrl", nsmgr)), downloadInfo.SourceUrl);

                        // contentUrl
                        string contentUrl = BlogClientHelper.GetAbsoluteUrl(XmlHelper.NodeText(buttonNode.SelectSingleNode("m:contentUrl", nsmgr)), downloadInfo.SourceUrl);

                        // contentDisplaySize
                        Size contentDisplaySize = XmlHelper.NodeSize(buttonNode.SelectSingleNode("m:contentDisplaySize", nsmgr), Size.Empty);

                        // button must have either clickUrl or hasContent
                        if (clickUrl == String.Empty && contentUrl == String.Empty)
                        {
                            throw new ArgumentException("Must either specify a clickUrl or contentUrl");
                        }

                        // notificationUrl
                        string notificationUrl = BlogClientHelper.GetAbsoluteUrl(XmlHelper.NodeText(buttonNode.SelectSingleNode("m:notificationUrl", nsmgr)), downloadInfo.SourceUrl);

                        // add the button
                        buttons.Add(new BlogProviderButtonDescription(id, imageUrl, image, description, clickUrl, contentUrl, contentDisplaySize, notificationUrl));
                    }
                    catch (Exception ex)
                    {
                        // buttons fail silently and are not "all or nothing"
                        Trace.WriteLine("Error occurred reading custom button description: " + ex.Message);
                    }
                }

                _buttonDescriptions = buttons.ToArray(typeof(IBlogProviderButtonDescription)) as IBlogProviderButtonDescription[];
            }

            // get options
            _optionOverrides = new Hashtable();
            AddOptionsFromNode(xmlDocument.SelectSingleNode("//m:weblog", nsmgr), _optionOverrides);
            AddOptionsFromNode(xmlDocument.SelectSingleNode("//m:options", nsmgr), _optionOverrides);
            AddOptionsFromNode(xmlDocument.SelectSingleNode("//m:apiOptions[@name='" + _blogClient.ProtocolName + "']", nsmgr), _optionOverrides);
            XmlNode defaultViewNode = xmlDocument.SelectSingleNode("//m:views/m:default", nsmgr);

            if (defaultViewNode != null)
            {
                _optionOverrides["defaultView"] = XmlHelper.NodeText(defaultViewNode);
            }

            // separate out client type
            const string CLIENT_TYPE = "clientType";

            if (_optionOverrides.Contains(CLIENT_TYPE))
            {
                string type = _optionOverrides[CLIENT_TYPE].ToString();
                if (ValidateClientType(type))
                {
                    _clientType = type;
                }
                _optionOverrides.Remove(CLIENT_TYPE);
            }

            // separate out image
            const string IMAGE_URL = "imageUrl";

            _image = GetImageBytes(IMAGE_URL, _optionOverrides, downloadInfo.SourceUrl, new Size(16, 16));
            _optionOverrides.Remove(IMAGE_URL);

            // separate out watermark image
            const string WATERMARK_IMAGE_URL = "watermarkImageUrl";

            _watermark = GetImageBytes(WATERMARK_IMAGE_URL, _optionOverrides, downloadInfo.SourceUrl, new Size(84, 84));
            _optionOverrides.Remove(WATERMARK_IMAGE_URL);

            // get templates
            XmlNode webLayoutUrlNode = xmlDocument.SelectSingleNode("//m:views/m:view[@type='WebLayout']/@src", nsmgr);

            if (webLayoutUrlNode != null)
            {
                string webLayoutUrl = XmlHelper.NodeText(webLayoutUrlNode);
                if (webLayoutUrl != String.Empty)
                {
                    _webLayoutUrl = BlogClientHelper.GetAbsoluteUrl(webLayoutUrl, downloadInfo.SourceUrl);
                }
            }
            XmlNode webPreviewUrlNode = xmlDocument.SelectSingleNode("//m:views/m:view[@type='WebPreview']/@src", nsmgr);

            if (webPreviewUrlNode != null)
            {
                string webPreviewUrl = XmlHelper.NodeText(webPreviewUrlNode);
                if (webPreviewUrl != String.Empty)
                {
                    _webPreviewUrl = BlogClientHelper.GetAbsoluteUrl(webPreviewUrl, downloadInfo.SourceUrl);
                }
            }
        }