Example #1
0
        /// <summary>
        /// This method shows the update ui and allows to perform the
        /// update process
        /// </summary>
        /// <param name="currentItem"></param>
        public void ShowUpdateNeededUI(NetSparkleAppCastItem currentItem)
        {
            // create the form
            NetSparkleForm frm = new NetSparkleForm(currentItem, ApplicationIcon, ApplicationWindowIcon);

            // configure the form
            frm.TopMost = true;

            if (HideReleaseNotes)
            {
                frm.RemoveReleaseNotesControls();
            }

            // show it
            DialogResult dlgResult = frm.ShowDialog();

            if (dlgResult == DialogResult.No)
            {
                // skip this version
                NetSparkleConfiguration config = new NetSparkleConfiguration(_AppReferenceAssembly);
                config.SetVersionToSkip(currentItem.Version);
            }
            else if (dlgResult == DialogResult.Yes)
            {
                // download the binaries
                InitDownloadAndInstallProcess(currentItem);
            }
        }
Example #2
0
        /// <summary>
        /// This method will be notified
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            switch (e.ProgressPercentage)
            {
            case 1:
            {
                // get the current item
                NetSparkleAppCastItem currentItem = e.UserState as NetSparkleAppCastItem;

                // show the update ui
                if (EnableSilentMode == true)
                {
                    InitDownloadAndInstallProcess(currentItem);
                }
                else
                {
                    ShowUpdateNeededUI(currentItem);
                }

                break;
            }

            case 0:
            {
                ReportDiagnosticMessage(e.UserState.ToString());
                break;
            }
            }
        }
Example #3
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="sparkle">the sparkle instance</param>
        /// <param name="item"></param>
        /// <param name="appIcon">application icon</param>
        /// <param name="windowIcon">window icon</param>
        /// <param name="Unattend"><c>true</c> if this is an unattended install</param>
        public NetSparkleDownloadProgress(Sparkle sparkle, NetSparkleAppCastItem item, Image appIcon, Icon windowIcon, Boolean Unattend)
        {
            InitializeComponent();

            if (appIcon != null)
            {
                imgAppIcon.Image = appIcon;
            }

            if (windowIcon != null)
            {
                Icon = windowIcon;
            }

            // store the item
            _sparkle = sparkle;
            _item    = item;
            //_referencedAssembly = referencedAssembly;
            _unattend = Unattend;

            // init ui
            btnInstallAndReLaunch.Visible = false;
            lblHeader.Text           = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version);
            progressDownload.Maximum = 100;
            progressDownload.Minimum = 0;
            progressDownload.Step    = 1;

            // show the right
            Size = new Size(Size.Width, 107);
            lblSecurityHint.Visible = false;
        }
Example #4
0
        /// <summary>
        /// This method checks if an update is required. During this process the appcast
        /// will be downloaded and checked against the reference assembly. Ensure that
        /// the calling process has access to the internet and read access to the
        /// reference assembly. This method is also called from the background loops.
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public Boolean IsUpdateRequired(NetSparkleConfiguration config, out NetSparkleAppCastItem latestVersion)
        {
            // report
            ReportDiagnosticMessage("Downloading and checking appcast");

            // init the appcast
            NetSparkleAppCast cast = new NetSparkleAppCast(_AppCastUrl, config);

            // check if any updates are available
            try
            {
                latestVersion = cast.GetLatestVersion();
            }
            catch (Exception e)
            {
                // show the exeception message
                ReportDiagnosticMessage("Error during app cast download: " + e.Message);

                // just null the version info
                latestVersion = null;
            }

            if (latestVersion == null)
            {
                ReportDiagnosticMessage("No version information in app cast found");
                return(false);
            }
            else
            {
                ReportDiagnosticMessage("Lastest version on the server is " + latestVersion.Version);
            }

            // set the last check time
            ReportDiagnosticMessage("Touch the last check timestamp");
            config.TouchCheckTime();

            // check if the available update has to be skipped
            if (latestVersion.Version.Equals(config.SkipThisVersion))
            {
                ReportDiagnosticMessage("Latest update has to be skipped (user decided to skip version " + config.SkipThisVersion + ")");
                return(false);
            }

            // check if the version will be the same then the installed version
            Version v1 = new Version(config.InstalledVersion);
            Version v2 = new Version(latestVersion.Version);

            if (v2 <= v1)
            {
                ReportDiagnosticMessage("Installed version is valid, no update needed (" + config.InstalledVersion + ")");
                return(false);
            }

            // ok we need an update
            return(true);
        }
Example #5
0
 private void InitDownloadAndInstallProcess(NetSparkleAppCastItem item)
 {
     if (EnableServiceMode)
     {
         DownloadAndInstallSync(item);
     }
     else
     {
         NetSparkleDownloadProgress dlProgress = new NetSparkleDownloadProgress(this, item, _AppReferenceAssembly, ApplicationIcon, ApplicationWindowIcon, EnableSilentMode);
         dlProgress.ShowDialog();
     }
 }
Example #6
0
 /// <summary>
 /// Updates from appcast
 /// </summary>
 /// <param name="currentItem">the current (top-most) item in the app-cast</param>
 private void Update(NetSparkleAppCastItem currentItem)
 {
     if (currentItem != null)
     {
         // show the update ui
         if (EnableSilentMode)
         {
             InitDownloadAndInstallProcess(currentItem);
         }
         else
         {
             ShowUpdateNeededUI(currentItem);
         }
     }
 }
Example #7
0
        public NetSparkleDownloadProgress(Sparkle sparkle, NetSparkleAppCastItem item, String referencedAssembly, Image appIcon, Icon windowIcon, Boolean Unattend)
        {
            InitializeComponent();

            if (appIcon != null)
            {
                imgAppIcon.Image = appIcon;
            }

            if (windowIcon != null)
            {
                Icon = windowIcon;
            }

            // store the item
            _sparkle            = sparkle;
            _item               = item;
            _referencedAssembly = referencedAssembly;
            _unattend           = Unattend;

            // init ui
            btnInstallAndReLaunch.Visible = false;
            lblHeader.Text           = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version);
            progressDownload.Maximum = 100;
            progressDownload.Minimum = 0;
            progressDownload.Step    = 1;

            // show the right
            Size = new Size(Size.Width, 107);
            lblSecurityHint.Visible = false;

            // get the filename of the download lin
            String[] segments = item.DownloadLink.Split('/');
            String   fileName = segments[segments.Length - 1];

            // get temp path
            _tempName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName);

            // start async download
            WebClient Client = new WebClient();

            Client.DownloadProgressChanged += Client_DownloadProgressChanged;
            Client.DownloadFileCompleted   += Client_DownloadFileCompleted;

            Uri url = new Uri(item.DownloadLink);

            Client.DownloadFileAsync(url, _tempName);
        }
Example #8
0
        /// <summary>
        /// Does a one-off check for updates
        /// </summary>
        /// <param name="isUserInterfaceShown"><c>true</c> if the user interface is to be shown.</param>
        public bool CheckForUpdates(bool isUserInterfaceShown)
        {
            NetSparkleConfiguration config = GetApplicationConfig();

            // update profile information is needed
            UpdateSystemProfileInformation(config);

            // check if update is required
            NetSparkleAppCastItem latestVersion = null;

            if (IsUpdateRequired(config, out latestVersion))
            {
                // show the update window
                ReportDiagnosticMessage("Update needed from version " + config.InstalledVersion + " to version " + latestVersion.Version);

                // send notification if needed
                UpdateDetectedEventArgs ev = new UpdateDetectedEventArgs()
                {
                    NextAction = NextUpdateAction.ShowStandardUserInterface, ApplicationConfig = config, LatestVersion = latestVersion
                };
                if (UpdateDetected != null)
                {
                    UpdateDetected(this, ev);
                }

                // check results
                if (isUserInterfaceShown)
                {
                    switch (ev.NextAction)
                    {
                    case NextUpdateAction.PerformUpdateUnattended:
                        EnableSilentMode = true;
                        Update(latestVersion);
                        break;

                    case NextUpdateAction.ProhibitUpdate:
                        break;

                    case NextUpdateAction.ShowStandardUserInterface:
                    default:
                        Update(latestVersion);
                        break;
                    }
                }
                return(true);
            }
            return(false);
        }
Example #9
0
 /// <summary>
 /// This method shows the update ui and allows to perform the
 /// update process
 /// </summary>
 /// <param name="currentItem">the item to show the UI for</param>
 public void ShowUpdateNeededUI(NetSparkleAppCastItem currentItem)
 {
     if (this.UserWindow == null)
     {
         // create the form
         this.UserWindow = new NetSparkleForm(currentItem, ApplicationIcon, ApplicationWindowIcon);
     }
     this.UserWindow.CurrentItem = currentItem;
     if (this.HideReleaseNotes)
     {
         this.UserWindow.HideReleaseNotes();
     }
     // clear if already set.
     this.UserWindow.UserResponded -= new EventHandler(OnUserWindowUserResponded);
     this.UserWindow.UserResponded += new EventHandler(OnUserWindowUserResponded);
     this.UserWindow.Show();
 }
Example #10
0
        /// <summary>
        /// Starts the download process
        /// </summary>
        /// <param name="item">the appcast item to download</param>
        private void InitDownloadAndInstallProcess(NetSparkleAppCastItem item)
        {
            // get the filename of the download lin
            string[] segments = item.DownloadLink.Split('/');
            string   fileName = segments[segments.Length - 1];

            // get temp path
            _downloadTempFileName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName);
            if (this.ProgressWindow == null)
            {
                this.ProgressWindow = new NetSparkleDownloadProgress(this, item, ApplicationIcon, ApplicationWindowIcon, EnableSilentMode);
            }
            else
            {
                this.ProgressWindow.InstallAndRelaunch -= new EventHandler(OnProgressWindowInstallAndRelaunch);
            }

            this.ProgressWindow.TempFileName        = _downloadTempFileName;
            this.ProgressWindow.InstallAndRelaunch += new EventHandler(OnProgressWindowInstallAndRelaunch);

            // set up the download client
            // start async download
            if (_webDownloadClient != null)
            {
                _webDownloadClient.DownloadProgressChanged -= new DownloadProgressChangedEventHandler(this.ProgressWindow.OnClientDownloadProgressChanged);
                _webDownloadClient.DownloadFileCompleted   -= new AsyncCompletedEventHandler(OnWebDownloadClientDownloadFileCompleted);
                _webDownloadClient = null;
            }

            _webDownloadClient = new WebClient
            {
                UseDefaultCredentials = true,
                Proxy = { Credentials = CredentialCache.DefaultNetworkCredentials },
            };

            _webDownloadClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(this.ProgressWindow.OnClientDownloadProgressChanged);
            _webDownloadClient.DownloadFileCompleted   += new AsyncCompletedEventHandler(OnWebDownloadClientDownloadFileCompleted);

            Uri url = new Uri(item.DownloadLink);

            _webDownloadClient.DownloadFileAsync(url, _downloadTempFileName);

            this.ProgressWindow.ShowDialog();
        }
Example #11
0
        public static bool CheckDSA(Sparkle sparkle, NetSparkleAppCastItem item, String tempName)
        {
            Boolean bDSAOk = false;

            // check if we have a dsa signature in appcast
            if (item.DSASignature == null || item.DSASignature.Length == 0)
            {
                sparkle.ReportDiagnosticMessage("No DSA check needed");
                bDSAOk = true;
            }
            else
            {
                // report
                sparkle.ReportDiagnosticMessage("Performing DSA check");

                // get the assembly
                if (File.Exists(tempName))
                {
                    // check if the file was downloaded successfully
                    String absolutePath = Path.GetFullPath(tempName);
                    if (!File.Exists(absolutePath))
                    {
                        throw new FileNotFoundException();
                    }

                    // get the assembly reference from which we start the update progress
                    // only from this trusted assembly the public key can be used
                    Assembly refassembly = System.Reflection.Assembly.GetEntryAssembly();
                    if (refassembly != null)
                    {
                        // Check if we found the public key in our entry assembly
                        if (NetSparkleDSAVerificator.ExistsPublicKey("NetSparkle_DSA.pub"))
                        {
                            // check the DSA Code and modify the back color
                            NetSparkleDSAVerificator dsaVerifier = new NetSparkleDSAVerificator("NetSparkle_DSA.pub");
                            bDSAOk = dsaVerifier.VerifyDSASignature(item.DSASignature, tempName);
                        }
                    }
                }
            }

            return(bDSAOk);
        }
Example #12
0
        private void DownloadAndInstallSync(NetSparkleAppCastItem item)
        {
            // get the filename of the download link
            String[] segments = item.DownloadLink.Split('/');
            String   fileName = segments[segments.Length - 1];

            // download sync
            String _tempName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName);

            // start async download
            WebClient Client = new WebClient();
            Uri       url    = new Uri(item.DownloadLink);

            Client.DownloadFile(url, _tempName);

            if (NetSparkleCheckAndInstall.CheckDSA(this, item, _tempName))
            {
                NetSparkleCheckAndInstall.Install(this, _tempName);
            }
        }
Example #13
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="item"></param>
        /// <param name="appIcon"></param>
        /// <param name="windowIcon"></param>
        public NetSparkleForm(NetSparkleAppCastItem item, Image appIcon, Icon windowIcon)
        {
            InitializeComponent();

            // init ui
            try
            {
                NetSparkleBrowser.AllowWebBrowserDrop = false;
                NetSparkleBrowser.AllowNavigation     = false;
            }
            catch (Exception)
            { }

            _currentItem = item;

            lblHeader.Text   = lblHeader.Text.Replace("APP", item.AppName);
            lblInfoText.Text = lblInfoText.Text.Replace("APP", item.AppName + " " + item.Version);
            lblInfoText.Text = lblInfoText.Text.Replace("OLDVERSION", item.AppVersionInstalled);

            if (item.ReleaseNotesLink != null && item.ReleaseNotesLink.Length > 0)
            {
                NetSparkleBrowser.Navigate(item.ReleaseNotesLink);
            }
            else
            {
                RemoveReleaseNotesControls();
            }

            if (appIcon != null)
            {
                imgAppIcon.Image = appIcon;
            }

            if (windowIcon != null)
            {
                Icon = windowIcon;
            }

            this.TopMost = true;
        }
        public NetSparkleDownloadProgress(Sparkle sparkle, NetSparkleAppCastItem item, String referencedAssembly, Image appIcon, Icon windowIcon, Boolean Unattend)
        {
            InitializeComponent();

            if (appIcon != null)
            {
                imgAppIcon.Image = appIcon;
            }

            if (windowIcon != null)
            {
                Icon = windowIcon;
            }

            // store the item
            _sparkle            = sparkle;
            _item               = item;
            _referencedAssembly = referencedAssembly;
            _unattend           = Unattend;

            // init ui
            btnInstallAndReLaunch.Visible = false;
            lblHeader.Text           = lblHeader.Text.Replace("APP", item.AppName + " " + item.Version);
            progressDownload.Maximum = 100;
            progressDownload.Minimum = 0;
            progressDownload.Step    = 1;

            // show the right
            Size = new Size(Size.Width, 107);
            lblSecurityHint.Visible = false;

            // get the filename of the download link
            String[] segments = item.DownloadLink.Split('/');
            String   fileName = segments[segments.Length - 1];

            //trim url parameters
            if (fileName.LastIndexOf('?') > 0)
            {
                fileName = fileName.Substring(0, fileName.LastIndexOf('?'));
            }

            //sanitize filename
            fileName = MakeValidFileName(fileName);

            //if no extension present make msi the default extension
            if (Path.GetExtension(fileName).Length == 0)
            {
                fileName += ".msi";
            }

            // get temp path
            _tempName = Environment.ExpandEnvironmentVariables("%temp%\\" + fileName);

            //check if file already exists and add counter
            while (File.Exists(_tempName))
            {
                _tempName = Path.GetDirectoryName(_tempName) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(_tempName) + DateTime.Now.ToFileTimeUtc() + Path.GetExtension(_tempName);
            }

            // start async download
            WebClient Client = new WebClient();

            Client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Client_DownloadProgressChanged);
            Client.DownloadFileCompleted   += new AsyncCompletedEventHandler(Client_DownloadFileCompleted);

            Uri url = new Uri(item.DownloadLink);

            Client.DownloadFileAsync(url, _tempName);
        }
Example #15
0
        /// <summary>
        /// This method will be executed as worker thread
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _worker_DoWork(object sender, DoWorkEventArgs e)
        {
            // store the did run once feature
            Boolean goIntoLoop     = true;
            Boolean checkTSP       = true;
            Boolean doInitialCheck = _DoInitialCheck;
            Boolean isInitialCheck = true;

            // start our lifecycles
            do
            {
                // set state
                Boolean bUpdateRequired = false;

                // notify
                if (checkLoopStarted != null)
                {
                    checkLoopStarted(this);
                }

                // report status
                if (doInitialCheck == false)
                {
                    ReportDiagnosticMessage("Initial check prohibited, going to wait");
                    doInitialCheck = true;
                    goto WaitSection;
                }

                // report status
                ReportDiagnosticMessage("Starting update loop...");

                // read the config
                ReportDiagnosticMessage("Reading config...");
                NetSparkleConfiguration config = GetApplicationConfig();

                // calc CheckTasp
                Boolean checkTSPInternal = checkTSP;

                if (isInitialCheck && checkTSPInternal)
                {
                    checkTSPInternal = !_ForceInitialCheck;
                }

                // check if it's ok the recheck to software state
                if (checkTSPInternal)
                {
                    TimeSpan csp = DateTime.Now - config.LastCheckTime;
                    if (csp < _CheckFrequency)
                    {
                        ReportDiagnosticMessage(String.Format("Update check performed within the last {0} minutes!", _CheckFrequency.TotalMinutes));
                        goto WaitSection;
                    }
                }
                else
                {
                    checkTSP = true;
                }

                // when sparkle will be deactivated wait an other cycle
                if (config.CheckForUpdate == false)
                {
                    ReportDiagnosticMessage("Check for updates disabled");
                    goto WaitSection;
                }

                // update the runonce feature
                goIntoLoop = !config.DidRunOnce;

                // update profile information is needed
                UpdateSystemProfileInformation(config);

                // check if update is required
                NetSparkleAppCastItem latestVersion = null;
                bUpdateRequired = IsUpdateRequired(config, out latestVersion);
                if (!bUpdateRequired)
                {
                    goto WaitSection;
                }

                // show the update window
                ReportDiagnosticMessage("Update needed from version " + config.InstalledVersion + " to version " + latestVersion.Version);

                // send notification if needed
                UpdateDetectedEventArgs ev = new UpdateDetectedEventArgs()
                {
                    NextAction = nNextUpdateAction.showStandardUserInterface, ApplicationConfig = config, LatestVersion = latestVersion
                };
                if (updateDetected != null)
                {
                    updateDetected(this, ev);
                }

                // check results
                switch (ev.NextAction)
                {
                case nNextUpdateAction.performUpdateUnattended:
                {
                    ReportDiagnosticMessage("Unattended update whished from consumer");
                    EnableSilentMode = true;
                    ReportProgress(1, latestVersion);
                    break;
                }

                case nNextUpdateAction.prohibitUpdate:
                {
                    ReportDiagnosticMessage("Update prohibited from consumer");
                    break;
                }

                case nNextUpdateAction.showStandardUserInterface:
                default:
                {
                    ReportDiagnosticMessage("Standard UI update whished from consumer");
                    ReportProgress(1, latestVersion);
                    break;
                }
                }

WaitSection:
                // reset initialcheck
                isInitialCheck = false;

                // notify
                if (checkLoopFinished != null)
                {
                    checkLoopFinished(this, bUpdateRequired);
                }

                // report wait statement
                ReportDiagnosticMessage(String.Format("Sleeping for an other {0} minutes, exit event or force update check event", _CheckFrequency.TotalMinutes));

                // wait for
                if (!goIntoLoop)
                {
                    break;
                }
                else
                {
                    // build the event array
                    WaitHandle[] handles = new WaitHandle[1];
                    handles[0] = _exitHandle;

                    // wait for any
                    int i = WaitHandle.WaitAny(handles, _CheckFrequency);
                    if (WaitHandle.WaitTimeout == i)
                    {
                        ReportDiagnosticMessage(String.Format("{0} minutes are over", _CheckFrequency.TotalMinutes));
                        continue;
                    }

                    // check the exit hadnle
                    if (i == 0)
                    {
                        ReportDiagnosticMessage("Got exit signal");
                        break;
                    }

                    // check an other check needed
                    if (i == 1)
                    {
                        ReportDiagnosticMessage("Got force update check signal");
                        checkTSP = false;
                        continue;
                    }
                }
            } while (goIntoLoop);

            // reset the islooping handle
            _loopingHandle.Reset();
        }
Example #16
0
        /// <summary>
        /// Gets the latest version
        /// </summary>
        /// <returns>the AppCast item corresponding to the latest version</returns>
        public NetSparkleAppCastItem GetLatestVersion()
        {
            NetSparkleAppCastItem latestVersion = null;

            // build a http web request stream
            WebRequest request = WebRequest.Create(_castUrl);

            request.UseDefaultCredentials = true;
            request.Proxy.Credentials     = CredentialCache.DefaultNetworkCredentials;

            // request the cast and build the stream
            WebResponse response = request.GetResponse();

            using (Stream inputstream = response.GetResponseStream())
            {
                NetSparkleAppCastItem currentItem = null;
                if (inputstream == null)
                {
                    return(null);
                }
                using (XmlTextReader reader = new XmlTextReader(inputstream))
                {
                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                        case XmlNodeType.Element:
                            switch (reader.Name)
                            {
                            case itemNode:
                            {
                                currentItem = new NetSparkleAppCastItem();
                                break;
                            }

                            case releaseNotesLinkNode:
                            {
                                if (currentItem != null)
                                {
                                    currentItem.ReleaseNotesLink = reader.ReadString();
                                    currentItem.ReleaseNotesLink = currentItem.ReleaseNotesLink.Trim('\n');
                                }
                                break;
                            }

                            case enclosureNode:
                            {
                                if (currentItem != null)
                                {
                                    currentItem.Version      = reader.GetAttribute(versionAttribute);
                                    currentItem.DownloadLink = reader.GetAttribute(urlAttribute);
                                    currentItem.DSASignature = reader.GetAttribute(dasSignature);
                                }
                                break;
                            }
                            }
                            break;

                        case XmlNodeType.EndElement:
                            switch (reader.Name)
                            {
                            case itemNode:
                            {
                                if (latestVersion == null)
                                {
                                    latestVersion = currentItem;
                                }
                                else if (currentItem.CompareTo(latestVersion) > 0)
                                {
                                    latestVersion = currentItem;
                                }
                                break;
                            }
                            }
                            break;
                        }
                    }
                }
            }

            // add some other attributes
            if (latestVersion != null)
            {
                latestVersion.AppName             = _config.ApplicationName;
                latestVersion.AppVersionInstalled = _config.InstalledVersion;
            }
            // go ahead
            return(latestVersion);
        }
Example #17
0
        public NetSparkleAppCastItem GetLatestVersion()
        {
            NetSparkleAppCastItem latestVersion = null;

            try
            {
                // build a http web request stream
                WebRequest request = HttpWebRequest.Create(_castUrl);

                // request the cast and build the stream
                WebResponse response = request.GetResponse();

                Stream inputstream = response.GetResponseStream();

                NetSparkleAppCastItem currentItem = null;

                XmlTextReader reader = new XmlTextReader(inputstream);
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.Name)
                        {
                        case itemNode:
                        {
                            currentItem = new NetSparkleAppCastItem();
                            break;
                        }

                        case releaseNotesLinkNode:
                        {
                            currentItem.ReleaseNotesLink = reader.ReadString();
                            currentItem.ReleaseNotesLink = currentItem.ReleaseNotesLink.Trim('\n');
                            break;
                        }

                        case enclosureNode:
                        {
                            currentItem.Version      = reader.GetAttribute(versionAttribute);
                            currentItem.DownloadLink = reader.GetAttribute(urlAttribute);
                            currentItem.DSASignature = reader.GetAttribute(dasSignature);

                            break;
                        }
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        switch (reader.Name)
                        {
                        case itemNode:
                        {
                            if (latestVersion == null)
                            {
                                latestVersion = currentItem;
                            }
                            else if (currentItem.CompareTo(latestVersion) > 0)
                            {
                                latestVersion = currentItem;
                            }
                            break;
                        }
                        }
                    }
                }

                // add some other attributes
                latestVersion.AppName             = _config.ApplicationName;
                latestVersion.AppVersionInstalled = _config.InstalledVersion;
            }
            catch (Exception)
            {
            }

            // go ahead
            return(latestVersion);
        }