Adds a customizable timout to WebClient.
Inheritance: System.Net.WebClient
Example #1
0
        /// <summary>
        /// Performs a feed search query using the <see cref="Config.FeedMirror"/>.
        /// </summary>
        /// <param name="config">The current configuration determining which mirror server to query.</param>
        /// <param name="keywords">The keywords to search for.</param>
        public static SearchQuery Perform([NotNull] Config config, [CanBeNull] string keywords)
        {
            #region Sanity checks
            if (config == null) throw new ArgumentNullException(nameof(config));
            #endregion

            if (string.IsNullOrEmpty(keywords)) return new SearchQuery();

            var url = new Uri(
                config.FeedMirror.EnsureTrailingSlash(),
                new Uri("search/?q=" + Uri.EscapeUriString(keywords), UriKind.Relative));

            Log.Info("Performing search query: " + url.ToStringRfc());
            using (var webClient = new WebClientTimeout())
            {
                var result = XmlStorage.FromXmlString<SearchQuery>(webClient.DownloadString(url));
                result.Keywords = keywords;
                return result;
            }
        }
        /// <summary>
        /// Adds a feed to the list of custom feeds.
        /// </summary>
        private void AddCustomFeed(string input)
        {
            FeedUri feedUri;
            try
            {
                feedUri = new FeedUri(input);
            }
            catch (UriFormatException ex)
            {
                Msg.Inform(this, ex.Message, MsgSeverity.Error);
                return;
            }

            if (_interfaceUri.IsFile)
            {
                if (!File.Exists(_interfaceUri.LocalPath))
                {
                    Msg.Inform(this, string.Format(Resources.FileOrDirNotFound, _interfaceUri.LocalPath), MsgSeverity.Warn);
                    return;
                }
            }
            else
            {
                Feed feed = null;
                try
                {
                    using (var handler = new GuiTaskHandler(this))
                    {
                        handler.RunTask(new SimpleTask(Resources.CheckingFeed,
                            delegate
                            {
                                using (var webClient = new WebClientTimeout())
                                    feed = XmlStorage.FromXmlString<Feed>(webClient.DownloadString(feedUri));
                            }));
                    }
                }
                    #region Error handling
                catch (OperationCanceledException)
                {
                    return;
                }
                catch (IOException ex)
                {
                    Msg.Inform(this, ex.Message, MsgSeverity.Error);
                    return;
                }
                catch (InvalidDataException ex)
                {
                    Msg.Inform(this, ex.Message, MsgSeverity.Error);
                    return;
                }
                catch (WebException ex)
                {
                    Msg.Inform(this, ex.Message, MsgSeverity.Error);
                    return;
                }
                catch (UnauthorizedAccessException ex)
                {
                    Msg.Inform(this, ex.Message, MsgSeverity.Error);
                    return;
                }
                #endregion

                // Ensure a matching <feed-for> is present for online feeds
                if (feed.FeedFor.All(entry => entry.Target != _interfaceUri))
                    if (!Msg.YesNo(this, Resources.IgnoreMissingFeedFor, MsgSeverity.Warn)) return;
            }

            var reference = new FeedReference {Source = feedUri};
            if (_interfacePreferences.Feeds.Contains(reference)) return;
            _interfacePreferences.Feeds.Add(reference);
            listBoxFeeds.Items.Add(reference);
        }
        //--------------------//

        #region Sync
        /// <summary>
        /// Synchronize the <see cref="AppList"/> with the sync server and (un)apply <see cref="AccessPoint"/>s accordingly.
        /// </summary>
        /// <param name="resetMode">Controls how synchronization data is reset.</param>
        /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
        /// <exception cref="InvalidDataException">A problem occurred while deserializing the XML data or the specified crypto key was wrong.</exception>
        /// <exception cref="WebException">A problem occured while communicating with the sync server or while downloading additional data (such as icons).</exception>
        /// <exception cref="IOException">A problem occurs while writing to the filesystem or registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception>
        public void Sync(SyncResetMode resetMode = SyncResetMode.None)
        {
            if (!_server.IsValid) throw new InvalidDataException(Resources.PleaseConfigSync);

            var appListUri = new Uri(_server.Uri, new Uri(MachineWide ? "app-list-machine" : "app-list", UriKind.Relative));
            using (var webClient = new WebClientTimeout
            {
                Credentials = _server.Credentials,
                CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore)
            })
            {
                ExceptionUtils.Retry<WebRaceConditionException>(delegate
                {
                    Handler.CancellationToken.ThrowIfCancellationRequested();

                    byte[] appListData;
                    try
                    {
                        appListData = DownloadAppList(appListUri, webClient, resetMode);
                    }
                        #region Error handling
                    catch (WebException ex)
                        when (ex.Status == WebExceptionStatus.ProtocolError && (ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        Handler.CancellationToken.ThrowIfCancellationRequested();
                        throw new WebException(Resources.SyncCredentialsInvalid, ex, ex.Status, ex.Response);
                    }
                    #endregion

                    HandleDownloadedAppList(resetMode, appListData);

                    try
                    {
                        UploadAppList(appListUri, webClient, resetMode);
                    }
                        #region Error handling
                    catch (WebException ex)
                        when (ex.Status == WebExceptionStatus.ProtocolError && (ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.PreconditionFailed)
                    {
                        Handler.CancellationToken.ThrowIfCancellationRequested();
                        throw new WebRaceConditionException(ex);
                    }
                    #endregion
                }, maxRetries: 3);
            }

            // Save reference point for future syncs
            AppList.SaveXml(AppListPath + AppListLastSyncSuffix);

            Handler.CancellationToken.ThrowIfCancellationRequested();
        }
        /// <summary>
        /// Synchronize the <see cref="AppList"/> with the sync server and (un)apply <see cref="AccessPoint"/>s accordingly.
        /// </summary>
        /// <param name="resetMode">Controls how synchronization data is reset.</param>
        /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
        /// <exception cref="InvalidDataException">A problem occurred while deserializing the XML data or if the specified crypto key was wrong.</exception>
        /// <exception cref="WebException">A problem occured while downloading additional data (such as icons).</exception>
        /// <exception cref="IOException">A problem occurs while writing to the filesystem or registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception>
        public void Sync(SyncResetMode resetMode)
        {
            if (!_server.IsValid) throw new InvalidDataException(Resources.PleaseConfigSync);

            var appListUri = new Uri(_server.Uri, new Uri(MachineWide ? "app-list-machine" : "app-list", UriKind.Relative));
            using (var webClient = new WebClientTimeout
            {
                Credentials = _server.Credentials,
                CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore)
            })
            {
                ExceptionUtils.Retry<TimeoutException>(delegate
                {
                    Handler.CancellationToken.ThrowIfCancellationRequested();

                    byte[] appListData;
                    try
                    {
                        appListData = DownloadAppList(appListUri, webClient, resetMode);
                    }
                        #region Error handling
                    catch (WebException ex)
                    {
                        switch (ex.Status)
                        {
                            case WebExceptionStatus.ProtocolError:
                                var response = ex.Response as HttpWebResponse;
                                if (response != null && response.StatusCode == HttpStatusCode.Unauthorized)
                                    throw new WebException(Resources.SyncCredentialsInvalid, ex);
                                else throw;

                            case WebExceptionStatus.Timeout:
                                throw new TimeoutException(ex.Message, ex);

                            default:
                                if (ex.InnerException != null && ex.InnerException.InnerException is FileNotFoundException) appListData = new byte[0];
                                else throw;
                                break;
                        }
                    }
                    #endregion

                    HandleDownloadedAppList(resetMode, appListData);

                    try
                    {
                        UploadAppList(appListUri, webClient, resetMode);
                    }
                        #region Error handling
                    catch (WebException ex)
                    {
                        if (ex.Status == WebExceptionStatus.ProtocolError)
                        {
                            var response = ex.Response as HttpWebResponse;
                            if (response != null && response.StatusCode == HttpStatusCode.PreconditionFailed)
                            {
                                Handler.CancellationToken.ThrowIfCancellationRequested();
                                throw new TimeoutException("Race condition encountered while syncing.");
                            }
                        }
                        else throw;
                    }
                    #endregion
                }, maxRetries: 3);
            }

            // Save reference point for future syncs
            AppList.SaveXml(AppListPath + AppListLastSyncSuffix);

            Handler.CancellationToken.ThrowIfCancellationRequested();
        }
Example #5
0
        private void CheckCryptoKey()
        {
            var appListUri = new Uri(_server.Uri, new Uri("app-list", UriKind.Relative));

            using (var webClient = new WebClientTimeout
            {
                Credentials = _server.Credentials,
                CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore)
            })
            {
                try
                {
                    AppList.LoadXmlZip(new MemoryStream(webClient.DownloadData(appListUri)), _cryptoKey);
                }
                    #region Error handling
                catch (WebException ex)
                    when (ex.Status == WebExceptionStatus.ProtocolError && (ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.Unauthorized)
                {
                    // Wrap exception to add context information
                    throw new WebException(Resources.SyncCredentialsInvalid, ex, ex.Status, ex.Response);
                }
                catch (ZipException ex)
                {
                    // Wrap exception to add context information
                    if (ex.Message == "Invalid password for AES") throw new InvalidDataException(Resources.SyncCryptoKeyInvalid);
                    else throw new InvalidDataException(Resources.SyncServerDataDamaged, ex);
                }
                #endregion
            }
        }