1
0
mirror of https://github.com/ncblakely/GiantsTools synced 2024-11-05 06:45:37 +01:00
GiantsTools/Giants.Launcher/Updater/Updater.cs
2020-08-10 00:29:28 -07:00

177 lines
5.8 KiB
C#

using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using System.Xml.Linq;
namespace Giants.Launcher
{
public class Updater
{
private readonly Uri updateUri;
private readonly Version appVersion;
private AsyncCompletedEventHandler updateCompletedCallback;
private DownloadProgressChangedEventHandler updateProgressCallback;
public Updater(Uri updateUri, Version appVersion)
{
this.updateUri = updateUri;
this.appVersion = appVersion;
}
public void DownloadUpdateInfo(AsyncCompletedEventHandler downloadCompleteCallback, DownloadProgressChangedEventHandler downloadProgressCallback)
{
WebClient client = new WebClient();
// Keep track of our progress callbacks
this.updateCompletedCallback = downloadCompleteCallback;
this.updateProgressCallback = downloadProgressCallback;
// Download update info XML
client.Proxy = null;
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(this.DownloadDataCallback);
client.DownloadDataAsync(this.updateUri);
}
private int GetHttpFileSize(Uri uri)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
req.Proxy = null;
req.Method = "HEAD";
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
if (resp.StatusCode == HttpStatusCode.OK && int.TryParse(resp.Headers.Get("Content-Length"), out int contentLength))
{
resp.Close();
return contentLength;
}
resp.Close();
return -1;
}
private void StartGameUpdate(XElement root, Version currentVersion)
{
var updates = from update in root.Elements("Update")
select new UpdateInfo()
{
VersionFrom = new Version(update.Attribute("FromVersion").Value),
VersionTo = new Version(update.Attribute("ToVersion").Value),
DownloadUri = new Uri(update.Attribute("Url").Value),
UpdateType = UpdateType.Game
};
// Grab the download path for the update to our current version, otherwise fall back to the full installer
// (specially defined as FromVersion 0.0.0.0 in the XML)
UpdateInfo info = updates.FirstOrDefault(update => update.VersionFrom == currentVersion);
if (info == null)
info = updates.Single(update => update.VersionFrom == new Version("0.0.0.0"));
// Display update prompt
string updateMsg = string.Format(Resources.UpdateAvailableText, info.VersionTo.ToString());
if (MessageBox.Show(updateMsg, Resources.UpdateAvailableTitle, MessageBoxButtons.YesNo) == DialogResult.No)
return; // User declined update
string path = Path.Combine(Path.GetTempPath(), info.FileName);
// Delete the file locally if it already exists, just to be safe
if (File.Exists(path))
File.Delete(path);
info.FileSize = this.GetHttpFileSize(info.DownloadUri);
if (info.FileSize == -1)
{
string errorMsg = string.Format(Resources.UpdateDownloadFailedText, "File not found on server.");
MessageBox.Show(errorMsg, Resources.UpdateDownloadFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Download the update
WebClient client = new WebClient()
{
Proxy = null
};
client.DownloadFileAsync(info.DownloadUri, path, info);
client.DownloadFileCompleted += this.updateCompletedCallback;
client.DownloadProgressChanged += this.updateProgressCallback;
}
private void StartLauncherUpdate(XElement root)
{
var query = from update in root.Descendants("LauncherUpdate")
select new UpdateInfo()
{
VersionTo = new Version(update.Attribute("ToVersion").Value),
DownloadUri = new Uri(update.Attribute("Url").Value),
UpdateType = UpdateType.Launcher
};
UpdateInfo info = query.FirstOrDefault();
// Display update prompt
string updateMsg = string.Format(Resources.LauncherUpdateAvailableText, info.VersionTo.ToString());
if (MessageBox.Show(updateMsg, Resources.UpdateAvailableTitle, MessageBoxButtons.YesNo) == DialogResult.No)
return; // User declined update
string path = Path.Combine(Path.GetTempPath(), info.FileName);
// Delete the file locally if it already exists, just to be safe
if (File.Exists(path))
File.Delete(path);
info.FileSize = this.GetHttpFileSize(info.DownloadUri);
if (info.FileSize == -1)
{
string errorMsg = string.Format(Resources.UpdateDownloadFailedText, "File not found on server.");
MessageBox.Show(errorMsg, Resources.UpdateDownloadFailedTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Download the update
WebClient client = new WebClient()
{
Proxy = null
};
client.DownloadFileAsync(info.DownloadUri, path, info);
client.DownloadFileCompleted += this.updateCompletedCallback;
client.DownloadProgressChanged += this.updateProgressCallback;
}
private void DownloadDataCallback(Object sender, DownloadDataCompletedEventArgs e)
{
try
{
if (!e.Cancelled && e.Error == null)
{
byte[] data = (byte[])e.Result;
string textData = System.Text.Encoding.UTF8.GetString(data);
XElement root = XElement.Parse(textData);
Version launcherVersion = new Version(root.Attribute("CurrentLauncherVersion").Value);
Version gameVersion = new Version(root.Attribute("CurrentGameVersion").Value);
Version ourVersion = new Version(Application.ProductVersion);
if (launcherVersion > ourVersion)
{
this.StartLauncherUpdate(root);
return;
}
else if (gameVersion > this.appVersion)
this.StartGameUpdate(root, this.appVersion);
}
}
catch (Exception ex)
{
#if DEBUG
MessageBox.Show(string.Format("Exception in DownloadDataCallback: {0}", ex.Message));
#endif
}
}
}
}