Skip to content

Commit 4161766

Browse files
authored
Release 1.17.5
Release 1.17.5
2 parents 4451e5f + 97225af commit 4161766

File tree

10 files changed

+66
-64
lines changed

10 files changed

+66
-64
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# GameVault App Changelog
22

3+
## 1.17.5
4+
Recommended Gamevault Server Version: `v16.1.2`
5+
### Changes
6+
- Bug fix: The required request headers for download resume and database backup were not sent.
7+
- Bug fix: You couldn't enter spaces for the password in the login window.
8+
- Bug fix: The session tokens were not properly persistent
9+
310
## 1.17.4
411
Recommended Gamevault Server Version: `v16.1.1`
512
### Changes

gamevault/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//(used if a resource is not found in the page,
1212
// app, or any theme specific resource dictionaries)
1313
)]
14-
[assembly: AssemblyVersion("1.17.4.0")]
14+
[assembly: AssemblyVersion("1.17.5.0")]
1515
[assembly: AssemblyCopyright("© Phalcode™. All Rights Reserved.")]
1616
#if DEBUG
1717
[assembly: XmlnsDefinition("debug-mode", "Namespace")]

gamevault/Helper/Integrations/SaveGameHelper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ internal async Task<string> RestoreBackup(int gameId, string installationDir)
7070
string[] auth = WebHelper.GetCredentials();
7171

7272
string url = @$"{SettingsViewModel.Instance.ServerUrl}/api/savefiles/user/{LoginManager.Instance.GetCurrentUser()!.ID}/game/{gameId}";
73-
using (HttpResponseMessage response = await WebHelper.GetAsync(@$"{SettingsViewModel.Instance.ServerUrl}/api/savefiles/user/{LoginManager.Instance.GetCurrentUser()!.ID}/game/{gameId}", HttpCompletionOption.ResponseHeadersRead))
73+
using (HttpResponseMessage response = await WebHelper.GetAsync(@$"{SettingsViewModel.Instance.ServerUrl}/api/savefiles/user/{LoginManager.Instance.GetCurrentUser()!.ID}/game/{gameId}", null, HttpCompletionOption.ResponseHeadersRead))
7474
{
7575
response.EnsureSuccessStatusCode();
7676
string fileName = response.Content.Headers.ContentDisposition.FileName.Split('_')[1].Split('.')[0];
@@ -356,7 +356,7 @@ private async Task<bool> UploadSavegame(string saveFilePath, int gameId, string
356356
string installationId = GetGameInstallationId(installationDir);
357357
using (MemoryStream memoryStream = await FileToMemoryStreamAsync(saveFilePath))
358358
{
359-
await WebHelper.UploadFileAsync(@$"{SettingsViewModel.Instance.ServerUrl}/api/savefiles/user/{LoginManager.Instance.GetCurrentUser()!.ID}/game/{gameId}", memoryStream, "x.zip", new RequestHeader[] { new RequestHeader() { Name = "X-Installation-Id", Value = installationId } });
359+
await WebHelper.UploadFileAsync(@$"{SettingsViewModel.Instance.ServerUrl}/api/savefiles/user/{LoginManager.Instance.GetCurrentUser()!.ID}/game/{gameId}", memoryStream, "x.zip", new List<RequestHeader> { new RequestHeader() { Name = "X-Installation-Id", Value = installationId } });
360360
}
361361
}
362362
catch

gamevault/Helper/PasswordBoxAttachedProperties.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,8 @@ private static void OnPreviewKeyDown(object sender, KeyEventArgs e)
210210
if (sender is not TextBox textBox || !GetIsPassword(textBox))
211211
return;
212212

213-
// Prevent spaces in password
214-
if (e.Key == Key.Space)
215-
{
216-
e.Handled = true;
217-
}
218213
// Handle Ctrl+A select all
219-
else if (e.Key == Key.A && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
214+
if (e.Key == Key.A && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
220215
{
221216
textBox.SelectAll();
222217
e.Handled = true;

gamevault/Helper/Web/HttpClientDownloadWithProgress.cs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@
1414

1515
namespace gamevault.Helper
1616
{
17-
public class HttpClientDownloadWithProgress : IDisposable
17+
public class HttpClientDownloadWithProgress
1818
{
1919
private readonly string DownloadUrl;
2020
private readonly string DestinationFolderPath;
2121
private string FileName;
2222
private string FallbackFileName;
23-
private KeyValuePair<string, string>? AdditionalHeader;
23+
private Dictionary<string, string>? AdditionalHeader;
2424
private bool Cancelled = false;
2525
private bool Paused = false;
2626
private long ResumePosition = -1;
2727
private long PreResumeSize = -1;
2828
private DateTime LastTime;
29-
private HttpClient HttpClient;
29+
3030

3131
public delegate void ProgressChangedHandler(long totalFileSize, long currentBytesDownloaded, long totalBytesDownloaded, double? progressPercentage, long resumePosition);
3232

3333
public event ProgressChangedHandler ProgressChanged;
3434

35-
public HttpClientDownloadWithProgress(string downloadUrl, string destinationFolderPath, string fallbackFileName, KeyValuePair<string, string>? additionalHeader = null)
35+
public HttpClientDownloadWithProgress(string downloadUrl, string destinationFolderPath, string fallbackFileName, Dictionary<string, string>? additionalHeader = null)
3636
{
3737
DownloadUrl = downloadUrl;
3838
DestinationFolderPath = destinationFolderPath;
@@ -42,8 +42,7 @@ public HttpClientDownloadWithProgress(string downloadUrl, string destinationFold
4242

4343
public async Task StartDownload(bool tryResume = false)
4444
{
45-
HttpClient = new HttpClient { Timeout = TimeSpan.FromDays(7) };
46-
CreateHeader();
45+
4746
if (tryResume)
4847
{
4948
InitResume();
@@ -55,18 +54,9 @@ public async Task StartDownload(bool tryResume = false)
5554
File.Delete($"{DestinationFolderPath}\\gamevault-metadata");
5655
}
5756

58-
using (HttpResponseMessage response = await WebHelper.GetAsync(DownloadUrl, HttpCompletionOption.ResponseHeadersRead))
57+
using (HttpResponseMessage response = await WebHelper.GetAsync(DownloadUrl, AdditionalHeader, HttpCompletionOption.ResponseHeadersRead))
5958
await DownloadFileFromHttpResponseMessage(response);
6059
}
61-
private void CreateHeader()
62-
{
63-
string[] auth = WebHelper.GetCredentials();
64-
HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{auth[0]}:{auth[1]}")));
65-
HttpClient.DefaultRequestHeaders.Add("User-Agent", $"GameVault/{SettingsViewModel.Instance.Version}");
66-
67-
if (AdditionalHeader != null)
68-
HttpClient.DefaultRequestHeaders.Add(AdditionalHeader.Value.Key, AdditionalHeader.Value.Value);
69-
}
7060
private void InitResume()
7161
{
7262
string resumeData = Preferences.Get(AppConfigKey.DownloadProgress, $"{DestinationFolderPath}\\gamevault-metadata");
@@ -77,7 +67,11 @@ private void InitResume()
7767
string[] resumeDataToProcess = resumeData.Split(";");
7868
ResumePosition = long.Parse(resumeDataToProcess[0]);
7969
PreResumeSize = long.Parse(resumeDataToProcess[1]);
80-
HttpClient.DefaultRequestHeaders.Range = new RangeHeaderValue(long.Parse(resumeDataToProcess[0]), null);
70+
if (AdditionalHeader == null)
71+
{
72+
AdditionalHeader = new Dictionary<string, string>();
73+
}
74+
AdditionalHeader?.Add("Range", $"bytes={ResumePosition}-");
8175
}
8276
catch { }
8377
}
@@ -206,17 +200,11 @@ public void Cancel()
206200
return;
207201
}
208202
Cancelled = true;
209-
Dispose();
210203
}
211204
public void Pause()
212205
{
213206
Paused = true;
214207
Cancelled = true;
215-
Dispose();
216-
}
217-
public void Dispose()
218-
{
219-
HttpClient?.Dispose();
220208
}
221209
}
222210
}

gamevault/Helper/Web/OAuthHttpClient.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public void InjectTokens(string accessToken, string refreshToken)
3333
{
3434
_accessToken = accessToken;
3535
_refreshToken = refreshToken;
36+
try
37+
{
38+
nextTokenRefresh = GetNextTokenRefresh(_accessToken);
39+
}
40+
catch { }
3641
}
3742
public string GetRefreshToken()
3843
{
@@ -60,7 +65,7 @@ public async Task<bool> LoginBasicAuthAsync(string username, string password)
6065
return true;
6166
}
6267

63-
private async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, RequestHeader[]? additionalHeaders = null, HttpCompletionOption option = HttpCompletionOption.ResponseContentRead)
68+
private async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, List<RequestHeader>? additionalHeaders = null, HttpCompletionOption option = HttpCompletionOption.ResponseContentRead)
6469
{
6570
if (string.IsNullOrEmpty(_accessToken))
6671
{
@@ -82,16 +87,16 @@ private async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, Re
8287
return await _httpClient.SendAsync(request, option);
8388
}
8489

85-
public Task<HttpResponseMessage> GetAsync(string url, RequestHeader[]? additionalHeaders = null, HttpCompletionOption option = HttpCompletionOption.ResponseContentRead) =>
90+
public Task<HttpResponseMessage> GetAsync(string url, List<RequestHeader>? additionalHeaders = null, HttpCompletionOption option = HttpCompletionOption.ResponseContentRead) =>
8691
SendAsync(new HttpRequestMessage(HttpMethod.Get, url), additionalHeaders, option);
8792

88-
public Task<HttpResponseMessage> PostAsync(string url, HttpContent content, RequestHeader[]? additionalHeaders = null) =>
93+
public Task<HttpResponseMessage> PostAsync(string url, HttpContent content, List<RequestHeader>? additionalHeaders = null) =>
8994
SendAsync(new HttpRequestMessage(HttpMethod.Post, url) { Content = content }, additionalHeaders);
9095

91-
public Task<HttpResponseMessage> PutAsync(string url, HttpContent content, RequestHeader[]? additionalHeaders = null) =>
96+
public Task<HttpResponseMessage> PutAsync(string url, HttpContent content, List<RequestHeader>? additionalHeaders = null) =>
9297
SendAsync(new HttpRequestMessage(HttpMethod.Put, url) { Content = content }, additionalHeaders);
9398

94-
public Task<HttpResponseMessage> DeleteAsync(string url, RequestHeader[]? additionalHeaders = null) =>
99+
public Task<HttpResponseMessage> DeleteAsync(string url, List<RequestHeader>? additionalHeaders = null) =>
95100
SendAsync(new HttpRequestMessage(HttpMethod.Delete, url), additionalHeaders);
96101

97102
private async Task<bool> RefreshTokenAsync()

gamevault/Helper/Web/WebHelper.cs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal class WebHelper
1919
{
2020
DefaultRequestHeaders = { { "User-Agent", "GameVault" } }
2121
};
22-
private static RequestHeader[] AdditionalRequestHeaders;
22+
private static List<RequestHeader> AdditionalRequestHeaders = new List<RequestHeader>();
2323
static WebHelper() { }
2424
internal static void SetCredentials(string serverUrl, string username, string password)
2525
{
@@ -47,7 +47,7 @@ internal static string GetRefreshToken()
4747
{
4848
return HttpClient.GetRefreshToken();
4949
}
50-
internal static void SetAdditionalRequestHeaders(RequestHeader[] additionalRequestHeaders)
50+
internal static void SetAdditionalDefaultRequestHeaders(List<RequestHeader> additionalRequestHeaders)
5151
{
5252
AdditionalRequestHeaders = additionalRequestHeaders;
5353

@@ -62,40 +62,45 @@ internal static void SetAdditionalRequestHeaders(RequestHeader[] additionalReque
6262
internal static async Task<string> BaseGetAsync(string url)
6363
{
6464
var response = await BaseHttpClient.GetAsync(url);
65-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
65+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
6666
return await response.Content.ReadAsStringAsync();
6767
}
6868
internal static async Task<string> BasePostAsync(string url, string payload)
6969
{
7070
var content = new StringContent(payload, Encoding.UTF8, "application/json");
7171
var response = await BaseHttpClient.PostAsync(url, content);
72-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
72+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
7373
return await response.Content.ReadAsStringAsync();
7474
}
7575
internal static async Task<string> BaseSendRequest(HttpRequestMessage request)
7676
{
7777
var response = await BaseHttpClient.SendAsync(request);
78-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
78+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
7979
return await response.Content.ReadAsStringAsync();
8080
}
8181
#endregion
8282
internal static async Task<string> GetAsync(string url)
8383
{
8484
var response = await HttpClient.GetAsync(url, AdditionalRequestHeaders);
85-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
85+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
8686
return await response.Content.ReadAsStringAsync();
8787
}
88-
internal static async Task<HttpResponseMessage> GetAsync(string url, HttpCompletionOption option = HttpCompletionOption.ResponseContentRead)
88+
internal static async Task<HttpResponseMessage> GetAsync(string url, Dictionary<string, string>? additionalManualRequestHeaders = null, HttpCompletionOption option = HttpCompletionOption.ResponseContentRead)
8989
{
90-
var response = await HttpClient.GetAsync(url, AdditionalRequestHeaders, option);
91-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
90+
List<RequestHeader> additionalHeaders = null;
91+
if (additionalManualRequestHeaders is { Count: > 0 })
92+
{
93+
additionalHeaders = additionalManualRequestHeaders.Select(h => new RequestHeader { Name = h.Key, Value = h.Value }).Concat(AdditionalRequestHeaders).ToList();
94+
}
95+
var response = await HttpClient.GetAsync(url, additionalHeaders ?? AdditionalRequestHeaders, option);
96+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
9297
return response;
9398
}
9499
internal static async Task<string> PostAsync(string url, string payload)
95100
{
96101
var content = new StringContent(payload, Encoding.UTF8, "application/json");
97102
var response = await HttpClient.PostAsync(url, content, AdditionalRequestHeaders);
98-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
103+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
99104
return await response.Content.ReadAsStringAsync();
100105
}
101106

@@ -109,20 +114,20 @@ internal static async Task<string> PutAsync(string url, string payload)
109114
internal static async Task<string> DeleteAsync(string url)
110115
{
111116
var response = await HttpClient.DeleteAsync(url, AdditionalRequestHeaders);
112-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
117+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
113118
return await response.Content.ReadAsStringAsync();
114119
}
115120
public static async Task DownloadImageFromUrlAsync(string imageUrl, string cacheFile)
116121
{
117122
var response = await HttpClient.GetAsync(imageUrl, AdditionalRequestHeaders);
118-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
123+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
119124
var imageBytes = await response.Content.ReadAsByteArrayAsync();
120125
await File.WriteAllBytesAsync(cacheFile, imageBytes);
121126
}
122127
public static async Task<BitmapImage> DownloadImageFromUrlAsync(string imageUrl)
123128
{
124129
var response = await HttpClient.GetAsync(imageUrl, AdditionalRequestHeaders);
125-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
130+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
126131
var imageData = await response.Content.ReadAsByteArrayAsync();
127132
using (var memoryStream = new MemoryStream(imageData))
128133
{
@@ -135,13 +140,13 @@ public static async Task<BitmapImage> DownloadImageFromUrlAsync(string imageUrl)
135140
return bitmap;
136141
}
137142
}
138-
public static async Task<string> UploadFileAsync(string apiUrl, Stream imageStream, string fileName, RequestHeader[]? additionalHeaders = null)
143+
public static async Task<string> UploadFileAsync(string apiUrl, Stream imageStream, string fileName, List<RequestHeader>? additionalHeaders = null)
139144
{
140145
//Mix request headers
141-
RequestHeader[]? mixedHeaders = null;
146+
List<RequestHeader>? mixedHeaders = null;
142147
if (additionalHeaders != null && AdditionalRequestHeaders != null)
143148
{
144-
mixedHeaders = AdditionalRequestHeaders.Concat(additionalHeaders).ToArray();
149+
mixedHeaders = AdditionalRequestHeaders.Concat(additionalHeaders).ToList();
145150
}
146151
else if (additionalHeaders == null)
147152
{
@@ -158,7 +163,7 @@ public static async Task<string> UploadFileAsync(string apiUrl, Stream imageStre
158163
imageContent.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
159164
formData.Add(imageContent, "file", fileName);
160165
var response = await HttpClient.PostAsync(apiUrl, formData, mixedHeaders);
161-
await WebExceptionHelper.EnsureSuccessStatusCode(response);
166+
await WebExceptionHelper.EnsureSuccessStatusCode(response);
162167
var responseContent = await response.Content.ReadAsStringAsync();
163168
return responseContent;
164169
}
@@ -184,7 +189,7 @@ public static string RemoveSpecialCharactersFromUrl(string url)
184189
}
185190
return sb.ToString();
186191
}
187-
192+
188193
}
189194
}
190195

gamevault/UserControls/GameDownloadUserControl.xaml.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,12 @@ private async Task DownloadGame(bool tryResume = false)
178178
ViewModel.DownloadFailedVisibility = System.Windows.Visibility.Hidden;
179179

180180
if (!Directory.Exists(m_DownloadPath)) { Directory.CreateDirectory(m_DownloadPath); }
181-
KeyValuePair<string, string>? header = null;
181+
Dictionary<string,string> additionalRequestHeaders = new Dictionary<string,string>();
182182
if (SettingsViewModel.Instance.DownloadLimit > 0)
183183
{
184-
header = new KeyValuePair<string, string>("X-Download-Speed-Limit", SettingsViewModel.Instance.DownloadLimit.ToString());
184+
additionalRequestHeaders.Add("X-Download-Speed-Limit", SettingsViewModel.Instance.DownloadLimit.ToString());
185185
}
186-
client = new HttpClientDownloadWithProgress($"{SettingsViewModel.Instance.ServerUrl}/api/games/{ViewModel.Game.ID}/download", m_DownloadPath, Path.GetFileName(ViewModel.Game.Path), header);
186+
client = new HttpClientDownloadWithProgress($"{SettingsViewModel.Instance.ServerUrl}/api/games/{ViewModel.Game.ID}/download", m_DownloadPath, Path.GetFileName(ViewModel.Game.Path), additionalRequestHeaders);
187187
client.ProgressChanged += DownloadProgress;
188188
startTime = DateTime.Now;
189189
downloadSpeedCalc = new DownloadSpeedCalculator();
@@ -195,7 +195,6 @@ private async Task DownloadGame(bool tryResume = false)
195195
catch (Exception ex)
196196
{
197197
IsDownloadActive = false;
198-
client.Dispose();
199198
ViewModel.State = $"Error: '{ex.Message}'";
200199
ViewModel.DownloadUIVisibility = System.Windows.Visibility.Hidden;
201200
ViewModel.DownloadFailedVisibility = System.Windows.Visibility.Visible;
@@ -314,7 +313,6 @@ private void DownloadCompleted()
314313

315314
UpdateDataSizeUI();
316315
ViewModel.DownloadUIVisibility = System.Windows.Visibility.Hidden;
317-
client.Dispose();
318316
IsDownloadActive = false;
319317
ViewModel.State = "Downloaded";
320318
uiBtnExtract.IsEnabled = true;

0 commit comments

Comments
 (0)