/// <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(); }
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 } }