Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [SIL.Core.Clearshare] New methods "GetIsStringAvailableForLangId" and "GetDynamicStringOrEnglish" were added to Localizer for use in LicenseInfo's "GetBestLicenseTranslation" method, to remove LicenseInfo's L10NSharp dependency.
- [SIL.Windows.Forms.Clearshare] New ILicenseWithImage interface handles "GetImage" method for Winforms-dependent licenses, implemented in CreativeCommonsLicense and CustomLicense, and formerly included in LicenseInfo.
- [SIL.Core.Clearshare] New tests MetadataBareTests are based on previous MetadataTests in SIL.Windows.Forms.Clearshare. The tests were updated to use ImageSharp instead of Winforms for handling images.
- [SIL.Core.Desktop] Added a constant (kBrowserCompatibleUserAgent) to RobustNetworkOperation: a browser-like User Agent string that can be used when making HTTP requests to strict servers.

### Fixed
- [SIL.DictionaryServices] Fix memory leak in LiftWriter
Expand All @@ -49,6 +50,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [SIL.Windows.Forms] BREAKING CHANGE: ToolStripExtensions.InitializeWithAvailableUILocales() removed the ILocalizationManager parameter. This method no longer provides functionality to display the localization dialog box in response to the user clicking More.
- [SIL.Windows.Forms] BREAKING CHANGE: Removed optional moreSelected parameter from ToolStripExtensions.InitializeWithAvailableUILocales method. This parameter was no longer being used. Clients that want to have a More menu item that performs a custom action will now need to add it themselves.
- [SIL.Windows.Forms] BREAKING CHANGE: LocalizationIncompleteDlg's EmailAddressForLocalizationRequests is no longer autopopulated from LocalizationManager. A new optional constructor parameter, emailAddressForLocalizationRequests, can be used instead. If not supplied, the "More information" controls will be hidden.
- [SIL.Core.Desktop] Added an optional userAgentHeader parameter to DoHttpGetAndGetProxyInfo to allow a client to mimic a real browser if necessary.

### Removed
- [SIL.Windows.Forms] In .NET 8 builds, removed Scanner and Camera options from the Image Toolbox.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using NUnit.Framework;
using SIL.Network;

Expand All @@ -19,7 +19,8 @@ public void DoHttpGetAndGetProxyInfo_404()
public void DoHttpGetAndGetProxyInfo_NoProxy_ReturnsFalse()
{
var gotProxy = RobustNetworkOperation.DoHttpGetAndGetProxyInfo(
"https://sil.org/", out _, out _, out _, s => Debug.WriteLine(s));
"https://sil.org/", out _, out _, out _, s => Debug.WriteLine(s),
RobustNetworkOperation.kBrowserCompatibleUserAgent);
Assert.That(gotProxy, Is.False);
}
}
Expand Down
65 changes: 57 additions & 8 deletions SIL.Core.Desktop/Network/RobustNetworkOperation.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Net;
using System.Security.Cryptography;
using System.Text;
Expand All @@ -8,6 +8,14 @@ namespace SIL.Network

public class RobustNetworkOperation
{
/// <summary>
/// A browser-like User Agent string that can be used when making HTTP requests to servers
/// that reject requests lacking a typical browser User-Agent header. Used in tests and
/// available to callers that encounter 403 responses due to restrictive server filtering.
/// </summary>
public const string kBrowserCompatibleUserAgent =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) libpalaso";

/// <summary>
/// Perform a web action, trying various things to use a proxy if needed, including requesting
/// (and remembering) user credentials from the user.
Expand All @@ -22,7 +30,7 @@ public static IWebProxy Do(Action<IWebProxy> action, Action<string> verboseLog)
var proxy = new WebProxy();
action(proxy);

//!!!!!!!!!!!!!! in Sept 2011, hatton disabled proxy lookup. It was reportedly causing grief in Nigeria,
//!!!!!!!!!!!!!! in Sept 2011, Hatton disabled proxy lookup. It was reportedly causing grief in Nigeria,
//asking for credentials over and over, and SIL PNG doesn't use a proxy anymore. So for now...


Expand Down Expand Up @@ -109,10 +117,51 @@ public static string GetClearText(string encryptedString)
}

/// <summary>
/// Used by Chorus to get proxy name, user name, and password of the remote repository.
/// Used to determine whether an HTTP GET request requires a proxy and, if so, to retrieve
/// the proxy host and credentials needed to access the specified remote repository URL.
/// </summary>
/// <returns>true if a proxy is needed. THROWS if it just can't get through</returns>
public static bool DoHttpGetAndGetProxyInfo(string url, out string hostAndPort, out string userName, out string password, Action<string> verboseLog)
/// <param name="url">
/// The full URL to send an HTTP GET request to. Used to test connectivity and determine
/// whether proxy credentials are required.
/// </param>
/// <param name="hostAndPort">
/// Outputs the proxy host (including port, if applicable) if a proxy is required;
/// otherwise, an empty string.
/// </param>
/// <param name="userName">
/// Outputs the proxy username if authentication is required; otherwise an empty string.
/// </param>
/// <param name="password">
/// Outputs the proxy password if authentication is required; otherwise an empty string.
/// </param>
/// <param name="verboseLog">
/// Optional callback for logging diagnostic information about the request and proxy
/// detection process.
/// </param>
/// <param name="userAgentHeader">
/// Optional user agent header string to send with the request. Some servers require a
/// browser-like user agent and may reject requests that appear to come from automated
/// clients. See <see cref="kBrowserCompatibleUserAgent"/> for an example value.
/// </param>
/// <returns>
/// True if a proxy is required and credentials were obtained; false if no proxy is needed.
/// </returns>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="url"/> is null.
/// </exception>
/// <exception cref="UriFormatException">
/// Thrown if <paramref name="url"/> is not a valid URI.
/// </exception>
/// <exception cref="WebException">
/// Thrown if the HTTP request fails due to network errors, proxy configuration
/// issues, or authentication failures.
/// </exception>
/// <exception cref="NotSupportedException">
/// Thrown if the URI scheme is not supported.
/// </exception>
public static bool DoHttpGetAndGetProxyInfo(string url, out string hostAndPort,
out string userName, out string password, Action<string> verboseLog,
string userAgentHeader = null)
{
hostAndPort = string.Empty;
userName = string.Empty;
Expand All @@ -125,6 +174,8 @@ public static bool DoHttpGetAndGetProxyInfo(string url, out string hostAndPort,
proxy =>
{
client.Proxy = proxy;
if (userAgentHeader != null)
client.Headers[HttpRequestHeader.UserAgent] = userAgentHeader;
client.DownloadData(url);
//we don't actually care what comes back
}, verboseLog
Expand All @@ -150,9 +201,7 @@ public static bool DoHttpGetAndGetProxyInfo(string url, out string hostAndPort,
var networkCredential = proxyInfo.Credentials.GetCredential(destination, "");
userName = networkCredential.UserName;
password = networkCredential.Password;
if (verboseLog != null)
verboseLog.Invoke("DoHttpGetAndGetProxyInfo Returning with credentials. UserName is " + userName);

verboseLog?.Invoke("DoHttpGetAndGetProxyInfo Returning with credentials. UserName is " + userName);

return true;
}
Expand Down
Loading