|
1 | 1 | using Microsoft.Win32; |
2 | 2 | using System; |
3 | 3 | using System.IO; |
4 | | -using System.Net; |
5 | 4 | using System.Net.Http; |
6 | 5 | using System.Text; |
7 | | -using System.Threading; |
8 | 6 | using System.Threading.Tasks; |
9 | 7 |
|
10 | 8 | namespace Utilities |
11 | 9 | { |
12 | 10 | public static class Net |
13 | 11 | { |
14 | | - public static string DownloadString(string uri) |
| 12 | + private static readonly HttpClient httpClient = new HttpClient( |
| 13 | + new HttpClientHandler |
| 14 | + { |
| 15 | + AutomaticDecompression = |
| 16 | + System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip |
| 17 | + } ); |
| 18 | + |
| 19 | + public static async Task<string> DownloadStringAsync ( string uri ) |
15 | 20 | { |
16 | 21 | try |
17 | 22 | { |
18 | | - HttpWebRequest request = GetRequest(uri); |
19 | | - request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; |
20 | | - using ( HttpWebResponse response = GetResponse( request ) ) |
| 23 | + Logging.Debug( "Requesting " + uri ); |
| 24 | + using ( var response = await httpClient.GetAsync( uri, HttpCompletionOption.ResponseHeadersRead ) ) |
21 | 25 | { |
22 | | - if ( response == null ) // Means that the system was not found |
| 26 | + if ( !response.IsSuccessStatusCode ) |
23 | 27 | { |
| 28 | + Logging.Error( $"Error obtaining string response from {uri}: {response.StatusCode}" ); |
24 | 29 | return null; |
25 | 30 | } |
26 | 31 |
|
27 | | - // Obtain and parse our response |
28 | | - var encoding = string.IsNullOrEmpty(response.CharacterSet) |
29 | | - ? Encoding.UTF8 |
30 | | - : Encoding.GetEncoding(response.CharacterSet); |
31 | | - |
| 32 | + var encoding = GetEncodingFromResponse( response ); |
32 | 33 | Logging.Debug( "Reading response from " + uri ); |
33 | | - return ReadResponseString( response, encoding ); |
| 34 | + return await ReadResponseStringAsync( response, encoding ); |
34 | 35 | } |
35 | 36 | } |
36 | 37 | catch ( Exception e ) |
37 | 38 | { |
38 | | - Logging.Error($"Error obtaining string response from {uri}: {e.Message}", e); |
| 39 | + Logging.Error( $"Error obtaining string response from {uri}: {e.Message}", e ); |
39 | 40 | return null; |
40 | 41 | } |
41 | 42 | } |
42 | 43 |
|
43 | | - private static string ReadResponseString(HttpWebResponse response, Encoding encoding) |
| 44 | + private static Encoding GetEncodingFromResponse ( HttpResponseMessage response ) |
| 45 | + { |
| 46 | + if ( response.Content.Headers.ContentType?.CharSet != null ) |
| 47 | + { |
| 48 | + try |
| 49 | + { |
| 50 | + return Encoding.GetEncoding( response.Content.Headers.ContentType.CharSet ); |
| 51 | + } |
| 52 | + catch |
| 53 | + { |
| 54 | + // Fallback to UTF8 if encoding is not supported |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + return Encoding.UTF8; |
| 59 | + } |
| 60 | + |
| 61 | + private static async Task<string> ReadResponseStringAsync ( HttpResponseMessage response, Encoding encoding ) |
44 | 62 | { |
45 | 63 | string data = null; |
46 | | - int attempts = 0; |
| 64 | + var attempts = 0; |
47 | 65 | Exception ex = null; |
48 | 66 |
|
49 | | - while (data is null && attempts < 10) |
| 67 | + while ( data is null && attempts < 10 ) |
50 | 68 | { |
51 | 69 | try |
52 | 70 | { |
53 | | - using (var stream = response.GetResponseStream()) |
| 71 | + using ( var stream = await response.Content.ReadAsStreamAsync() ) |
54 | 72 | { |
55 | | - if (stream != null) |
| 73 | + if ( stream != null ) |
56 | 74 | { |
57 | | - var reader = new StreamReader(stream, encoding); |
58 | | - data = reader.ReadToEnd(); |
59 | | - return data; |
| 75 | + using ( var reader = new StreamReader( stream, encoding ) ) |
| 76 | + { |
| 77 | + data = await reader.ReadToEndAsync(); |
| 78 | + return data; |
| 79 | + } |
60 | 80 | } |
| 81 | + |
61 | 82 | return null; |
62 | 83 | } |
63 | 84 | } |
64 | | - catch (Exception e) |
| 85 | + catch ( Exception e ) |
65 | 86 | { |
66 | 87 | attempts++; |
67 | | - Thread.Sleep(50); |
| 88 | + await Task.Delay( 50 ); |
68 | 89 | ex = e; |
69 | 90 | } |
70 | 91 | } |
71 | 92 |
|
72 | | - if (attempts >= 10 && ex != null) |
| 93 | + if ( attempts >= 10 && ex != null ) |
73 | 94 | { |
74 | | - Logging.Warn(ex.Message, ex); |
| 95 | + Logging.Warn( ex.Message, ex ); |
75 | 96 | } |
76 | 97 |
|
77 | 98 | return data; |
78 | 99 | } |
79 | 100 |
|
80 | | - public static async Task<string> DownloadFileAsync(string uri, string name) |
| 101 | + public static async Task<string> DownloadFileAsync ( string uri, string name ) |
81 | 102 | { |
82 | 103 | try |
83 | 104 | { |
84 | | - var fileName = Path.GetTempPath() + @"\" + name; |
85 | | - var response = await new HttpClient().GetAsync(uri); |
86 | | - if ( !response.IsSuccessStatusCode ) |
87 | | - { |
88 | | - Logging.Error( $"Failed to download update file. Status code: {response.StatusCode}" ); |
89 | | - return null; |
90 | | - } |
91 | | - using (var fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)) |
| 105 | + var fileName = Path.Combine( Path.GetTempPath(), name ); |
| 106 | + using ( var response = await httpClient.GetAsync( uri, HttpCompletionOption.ResponseHeadersRead ) ) |
92 | 107 | { |
93 | | - await response.Content.CopyToAsync(fs); |
| 108 | + if ( !response.IsSuccessStatusCode ) |
| 109 | + { |
| 110 | + Logging.Error( $"Failed to download update file. Status code: {response.StatusCode}" ); |
| 111 | + return null; |
| 112 | + } |
| 113 | + |
| 114 | + using ( var fs = new FileStream( fileName, FileMode.OpenOrCreate, FileAccess.Write ) ) |
| 115 | + { |
| 116 | + await response.Content.CopyToAsync( fs ); |
| 117 | + } |
94 | 118 | } |
| 119 | + |
95 | 120 | return fileName; |
96 | 121 | } |
97 | | - catch (Exception ex) |
| 122 | + catch ( Exception ex ) |
98 | 123 | { |
99 | | - Logging.Error("Failed to download file " + uri, ex); |
| 124 | + Logging.Error( "Failed to download file " + uri, ex ); |
100 | 125 | return null; |
101 | 126 | } |
102 | 127 | } |
103 | 128 |
|
104 | | - // Set up a request with the correct parameters for talking to the companion app |
105 | | - private static HttpWebRequest GetRequest(string url) |
106 | | - { |
107 | | - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); |
108 | | - request.Timeout = 10000; |
109 | | - request.ReadWriteTimeout = 10000; |
110 | | - return request; |
111 | | - } |
112 | | - |
113 | | - // Obtain a response, ensuring that we obtain the response's cookies |
114 | | - private static HttpWebResponse GetResponse(HttpWebRequest request) |
115 | | - { |
116 | | - Logging.Debug("Requesting " + request.RequestUri); |
117 | | - |
118 | | - HttpWebResponse response; |
119 | | - try |
120 | | - { |
121 | | - response = (HttpWebResponse)request.GetResponse(); |
122 | | - } |
123 | | - catch (WebException wex) |
124 | | - { |
125 | | - if (!(wex.Response is HttpWebResponse errorResponse)) |
126 | | - { |
127 | | - // No error response |
128 | | - Logging.Warn("Failed to obtain response, error code " + wex.Status); |
129 | | - return null; |
130 | | - } |
131 | | - else if (errorResponse.StatusCode == HttpStatusCode.NotFound) |
132 | | - { |
133 | | - // Not found is usual |
134 | | - return null; |
135 | | - } |
136 | | - else |
137 | | - { |
138 | | - Logging.Warn("Bad response, error code " + wex.Status); |
139 | | - throw; |
140 | | - } |
141 | | - } |
142 | | - Logging.Debug("Response is: ", response); |
143 | | - return response; |
144 | | - } |
145 | | - |
146 | | - public static string GetDefaultBrowserPath() |
| 129 | + public static string GetDefaultBrowserPath () |
147 | 130 | { |
148 | | - string urlAssociation = @"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http"; |
149 | | - string browserPathKey = @"$BROWSER$\shell\open\command"; |
| 131 | + var urlAssociation = @"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http"; |
| 132 | + var browserPathKey = @"$BROWSER$\shell\open\command"; |
150 | 133 |
|
151 | 134 | try |
152 | 135 | { |
153 | 136 | // Read default browser path from userChoiceLKey |
154 | | - var userChoiceKey = Registry.CurrentUser.OpenSubKey(urlAssociation + @"\UserChoice", false); |
| 137 | + var userChoiceKey = Registry.CurrentUser.OpenSubKey( urlAssociation + @"\UserChoice", false ); |
155 | 138 |
|
156 | 139 | // If user choice was not found, try machine default |
157 | | - if (userChoiceKey == null) |
| 140 | + if ( userChoiceKey == null ) |
158 | 141 | { |
159 | 142 | // Read default browser path from Win XP registry key |
160 | 143 | // If browser path wasn’t found, try Win Vista (and newer) registry key |
161 | | - var browserKey = Registry.ClassesRoot.OpenSubKey(@"HTTP\shell\open\command", false) ?? |
| 144 | + var browserKey = Registry.ClassesRoot.OpenSubKey( @"HTTP\shell\open\command", false ) ?? |
162 | 145 | Registry.CurrentUser.OpenSubKey( |
163 | | - urlAssociation, false); |
| 146 | + urlAssociation, false ); |
164 | 147 |
|
165 | | - var path = CleanifyBrowserPath(browserKey?.GetValue(null) as string); |
| 148 | + var path = CleanifyBrowserPath( browserKey?.GetValue( null ) as string ); |
166 | 149 | browserKey?.Close(); |
167 | | - Logging.Debug("Browser path (1) is " + path); |
| 150 | + Logging.Debug( "Browser path (1) is " + path ); |
168 | 151 | return path; |
169 | 152 | } |
170 | 153 | else |
171 | 154 | { |
172 | 155 | // user defined browser choice was found |
173 | | - string progId = (userChoiceKey.GetValue("ProgId")?.ToString()); |
| 156 | + var progId = userChoiceKey.GetValue( "ProgId" )?.ToString(); |
174 | 157 | userChoiceKey.Close(); |
175 | 158 |
|
176 | 159 | // now look up the path of the executable |
177 | | - string concreteBrowserKey = browserPathKey.Replace("$BROWSER$", progId); |
178 | | - var kp = Registry.ClassesRoot.OpenSubKey(concreteBrowserKey, false); |
179 | | - var browserPath = CleanifyBrowserPath(kp?.GetValue(null) as string); |
| 160 | + var concreteBrowserKey = browserPathKey.Replace( "$BROWSER$", progId ); |
| 161 | + var kp = Registry.ClassesRoot.OpenSubKey( concreteBrowserKey, false ); |
| 162 | + var browserPath = CleanifyBrowserPath( kp?.GetValue( null ) as string ); |
180 | 163 | kp?.Close(); |
181 | | - Logging.Debug("Browser path (2) is " + browserPath); |
| 164 | + Logging.Debug( "Browser path (2) is " + browserPath ); |
182 | 165 | return browserPath; |
183 | 166 | } |
184 | 167 | } |
185 | | - catch (Exception ex) |
| 168 | + catch ( Exception ex ) |
186 | 169 | { |
187 | | - Logging.Error("Failed to find default browser: ", ex); |
| 170 | + Logging.Error( "Failed to find default browser: ", ex ); |
188 | 171 | return "explorer.exe"; |
189 | 172 | } |
190 | 173 | } |
191 | 174 |
|
192 | | - private static string CleanifyBrowserPath(string p) |
| 175 | + private static string CleanifyBrowserPath ( string p ) |
193 | 176 | { |
194 | | - string[] url = p.Split('"'); |
195 | | - string clean = url[1]; |
| 177 | + var url = p.Split( '"' ); |
| 178 | + var clean = url[ 1 ]; |
196 | 179 | return clean; |
197 | 180 | } |
198 | 181 | } |
|
0 commit comments