2016-03-07 20:01:13 +00:00
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
|
|
using System;
|
2015-07-02 10:07:43 +00:00
|
|
|
|
using System.ComponentModel;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Text;
|
2015-07-26 23:18:13 +00:00
|
|
|
|
using System.Windows.Forms;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
using System.Xml;
|
|
|
|
|
|
2016-03-07 20:01:13 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
2015-07-01 23:09:34 +00:00
|
|
|
|
namespace CodeImp.DoomBuilder
|
|
|
|
|
{
|
|
|
|
|
internal static class UpdateChecker
|
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
private delegate DialogResult ShowWarningMessageDelegate(string message, MessageBoxButtons buttons);
|
|
|
|
|
|
2016-02-26 22:06:42 +00:00
|
|
|
|
private const string NO_UPDATE_REQUIRED = "Your version is up to date.";
|
|
|
|
|
|
2015-07-01 23:09:34 +00:00
|
|
|
|
private static BackgroundWorker worker;
|
2015-07-26 23:18:13 +00:00
|
|
|
|
private static bool verbose;
|
|
|
|
|
|
|
|
|
|
internal static void PerformCheck(bool verbosemode)
|
2015-07-01 23:09:34 +00:00
|
|
|
|
{
|
2015-09-06 22:15:21 +00:00
|
|
|
|
// Update check already runing?
|
2015-07-01 23:09:34 +00:00
|
|
|
|
if(worker != null && worker.IsBusy)
|
|
|
|
|
{
|
2016-02-26 22:06:42 +00:00
|
|
|
|
if(verbosemode) General.ShowWarningMessage("Update check is already running!", MessageBoxButtons.OK);
|
2015-07-01 23:09:34 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2015-07-26 23:18:13 +00:00
|
|
|
|
|
2015-09-06 22:15:21 +00:00
|
|
|
|
// Start checking
|
2015-07-26 23:18:13 +00:00
|
|
|
|
verbose = verbosemode;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
worker = new BackgroundWorker();
|
|
|
|
|
worker.DoWork += DoWork;
|
|
|
|
|
worker.RunWorkerCompleted += RunWorkerCompleted;
|
|
|
|
|
worker.WorkerSupportsCancellation = true;
|
|
|
|
|
worker.RunWorkerAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void DoWork(object sender, DoWorkEventArgs e)
|
|
|
|
|
{
|
2015-09-06 22:15:21 +00:00
|
|
|
|
string updaterpath = Path.Combine(General.AppPath, "Updater.exe");
|
|
|
|
|
if(!File.Exists(updaterpath))
|
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
ShowResult("Update check failed: \"" + updaterpath + "\" does not exist!");
|
2015-09-06 22:15:21 +00:00
|
|
|
|
e.Cancel = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string inipath = Path.Combine(General.AppPath, "Updater.ini");
|
|
|
|
|
if(!File.Exists(inipath))
|
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
ShowResult("Update check failed: \"" + inipath + "\" does not exist!");
|
2015-09-06 22:15:21 +00:00
|
|
|
|
e.Cancel = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string url = GetDownloadUrl(inipath);
|
2015-07-01 23:09:34 +00:00
|
|
|
|
if(string.IsNullOrEmpty(url))
|
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
ShowResult("Update check failed: failed to get update url from Updater.ini!");
|
2015-07-01 23:09:34 +00:00
|
|
|
|
e.Cancel = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get local revision number
|
|
|
|
|
int localrev = General.ThisAssembly.GetName().Version.Revision;
|
2015-09-06 22:15:21 +00:00
|
|
|
|
int actuallocalrev = localrev;
|
2015-09-04 12:44:09 +00:00
|
|
|
|
if(!verbose) localrev = Math.Max(localrev, General.Settings.IgnoredRemoteRevision);
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
|
|
|
|
// Get remote revision number
|
|
|
|
|
int remoterev;
|
2016-03-18 12:52:12 +00:00
|
|
|
|
MemoryStream stream = DownloadWebFile(Path.Combine(url, "Version.txt"));
|
|
|
|
|
if(stream == null)
|
2015-07-01 23:09:34 +00:00
|
|
|
|
{
|
2016-03-18 12:52:12 +00:00
|
|
|
|
ShowResult("Update check failed: failed to retrieve remote revision info.\nCheck your Internet connection and try again.");
|
|
|
|
|
e.Cancel = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
2016-03-18 12:52:12 +00:00
|
|
|
|
string s;
|
|
|
|
|
using(StreamReader reader = new StreamReader(stream))
|
|
|
|
|
{
|
|
|
|
|
s = reader.ReadToEnd();
|
|
|
|
|
}
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
2016-03-18 12:52:12 +00:00
|
|
|
|
if(!int.TryParse(s, out remoterev))
|
|
|
|
|
{
|
|
|
|
|
ShowResult("Update check failed: failed to retrieve remote revision number.");
|
|
|
|
|
e.Cancel = true;
|
|
|
|
|
return;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(remoterev > localrev)
|
|
|
|
|
{
|
|
|
|
|
// Get changelog info
|
2015-09-06 22:15:21 +00:00
|
|
|
|
string changelog = GetChangelog(url, actuallocalrev);
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
|
|
|
|
if(string.IsNullOrEmpty(changelog))
|
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
ShowResult("Update check failed: failed to retrieve changelog.\nCheck your Internet connection and try again.");
|
2015-07-01 23:09:34 +00:00
|
|
|
|
e.Cancel = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pass data to MainForm
|
|
|
|
|
General.MainWindow.UpdateAvailable(remoterev, changelog);
|
|
|
|
|
}
|
2015-07-26 23:18:13 +00:00
|
|
|
|
else if(verbose)
|
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
ShowResult(NO_UPDATE_REQUIRED);
|
2015-07-26 23:18:13 +00:00
|
|
|
|
}
|
2015-07-01 23:09:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 20:01:13 +00:00
|
|
|
|
private static void ShowResult(string message)
|
2015-07-01 23:09:34 +00:00
|
|
|
|
{
|
2016-03-07 20:01:13 +00:00
|
|
|
|
if(!string.IsNullOrEmpty(message))
|
2015-07-01 23:09:34 +00:00
|
|
|
|
{
|
2015-07-26 23:18:13 +00:00
|
|
|
|
if(verbose)
|
2016-03-07 20:01:13 +00:00
|
|
|
|
{
|
|
|
|
|
if(General.MainWindow.InvokeRequired)
|
|
|
|
|
General.MainWindow.Invoke(new ShowWarningMessageDelegate(General.ShowWarningMessage), new object[] { message, MessageBoxButtons.OK });
|
|
|
|
|
else
|
|
|
|
|
General.ShowWarningMessage(message, MessageBoxButtons.OK);
|
|
|
|
|
}
|
|
|
|
|
else if(message != NO_UPDATE_REQUIRED)
|
|
|
|
|
{
|
|
|
|
|
General.ErrorLogger.Add(ErrorType.Error, message);
|
|
|
|
|
}
|
2015-07-01 23:09:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 20:01:13 +00:00
|
|
|
|
private static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
worker = null;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-01 23:09:34 +00:00
|
|
|
|
private static string GetChangelog(string url, int localrev)
|
|
|
|
|
{
|
|
|
|
|
StringBuilder sb = new StringBuilder(@"{\rtf1");
|
|
|
|
|
|
|
|
|
|
using(MemoryStream stream = DownloadWebFile(Path.Combine(url, "Changelog.xml")))
|
|
|
|
|
{
|
|
|
|
|
if(stream == null) return string.Empty;
|
|
|
|
|
|
|
|
|
|
XmlDocument doc = new XmlDocument();
|
|
|
|
|
doc.Load(stream);
|
|
|
|
|
|
|
|
|
|
// Revision infos go in descending order
|
|
|
|
|
if(doc.ChildNodes.Count == 0) return string.Empty;
|
|
|
|
|
foreach(XmlNode log in doc.ChildNodes)
|
|
|
|
|
{
|
|
|
|
|
if(log.ChildNodes.Count == 0) continue;
|
|
|
|
|
foreach(XmlNode logentry in log.ChildNodes)
|
|
|
|
|
{
|
2015-12-28 15:01:53 +00:00
|
|
|
|
int noderev;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
if(logentry.Attributes == null || !int.TryParse(logentry.Attributes.GetNamedItem("revision").Value, out noderev)) continue;
|
|
|
|
|
if(noderev <= localrev) break;
|
|
|
|
|
|
|
|
|
|
// Add info
|
|
|
|
|
sb.Append(@"{\b R" + noderev + @":}\par ");
|
|
|
|
|
|
|
|
|
|
foreach(XmlNode prop in logentry.ChildNodes)
|
|
|
|
|
{
|
|
|
|
|
if(prop.Name == "msg")
|
|
|
|
|
{
|
2015-07-02 10:07:43 +00:00
|
|
|
|
sb.Append(prop.InnerText.Trim().Replace(Environment.NewLine, @"\par ")).Append(@"\par\par ");
|
2015-07-01 23:09:34 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sb.Append("}");
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static MemoryStream DownloadWebFile(string url)
|
|
|
|
|
{
|
|
|
|
|
// Open a data stream from the supplied URL
|
2016-02-26 22:06:42 +00:00
|
|
|
|
WebRequest request = WebRequest.Create(url);
|
|
|
|
|
WebResponse response;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2016-02-26 22:06:42 +00:00
|
|
|
|
response = request.GetResponse();
|
2015-07-01 23:09:34 +00:00
|
|
|
|
}
|
|
|
|
|
catch(WebException)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 22:06:42 +00:00
|
|
|
|
Stream source = response.GetResponseStream();
|
|
|
|
|
if(source == null) return null;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
|
|
|
|
// Download the data in chuncks
|
2016-02-26 22:06:42 +00:00
|
|
|
|
byte[] buffer = new byte[1024];
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
|
|
|
|
// Download the data
|
2016-02-26 22:06:42 +00:00
|
|
|
|
MemoryStream result = new MemoryStream();
|
2015-07-01 23:09:34 +00:00
|
|
|
|
while(!General.MainWindow.IsDisposed)
|
|
|
|
|
{
|
|
|
|
|
// Let's try and read the data
|
2016-02-26 22:06:42 +00:00
|
|
|
|
int numbytes = source.Read(buffer, 0, buffer.Length);
|
|
|
|
|
if(numbytes == 0) break; // Download complete
|
|
|
|
|
|
|
|
|
|
// Write the downloaded data
|
|
|
|
|
result.Write(buffer, 0, numbytes);
|
2015-07-01 23:09:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Release resources
|
2016-02-26 22:06:42 +00:00
|
|
|
|
source.Close();
|
2015-07-01 23:09:34 +00:00
|
|
|
|
|
|
|
|
|
// Rewind and return the stream
|
2016-02-26 22:06:42 +00:00
|
|
|
|
result.Position = 0;
|
|
|
|
|
return result;
|
2015-07-01 23:09:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GetDownloadUrl(string filename)
|
|
|
|
|
{
|
|
|
|
|
string[] lines = File.ReadAllLines(filename);
|
|
|
|
|
foreach(string line in lines)
|
|
|
|
|
{
|
|
|
|
|
if(line.StartsWith("URL")) return line.Substring(3).Trim();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|