2019-03-19 21:09:03 +00:00
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using ScoutBase;
|
|
|
|
|
using ScoutBase.Core;
|
|
|
|
|
using System.Data.SQLite;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace AirScout.Aircrafts
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#region AircraftDatabaseUpdater
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class AircraftDatabaseUpdaterStartOptions
|
|
|
|
|
{
|
|
|
|
|
public string Name;
|
2020-02-12 10:45:19 +00:00
|
|
|
|
public string InstanceID;
|
|
|
|
|
public string SessionKey;
|
|
|
|
|
public string GetKeyURL;
|
2019-03-19 21:09:03 +00:00
|
|
|
|
public BACKGROUNDUPDATERSTARTOPTIONS Options;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Background worker for aircraft database update
|
|
|
|
|
[DefaultPropertyAttribute("Name")]
|
|
|
|
|
public class AircraftDatabaseUpdater : BackgroundWorker
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
AircraftDatabaseUpdaterStartOptions StartOptions;
|
|
|
|
|
string Password;
|
|
|
|
|
|
|
|
|
|
public AircraftDatabaseUpdater() : base()
|
|
|
|
|
{
|
|
|
|
|
this.WorkerReportsProgress = true;
|
|
|
|
|
this.WorkerSupportsCancellation = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ReadAircraftsFromURL(string url, string filename)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
AutoDecompressionWebClient cl = new AutoDecompressionWebClient();
|
|
|
|
|
DOWNLOADFILESTATUS status = cl.DownloadFileIfNewer(url, filename, true, true, Password);
|
|
|
|
|
if (((status & DOWNLOADFILESTATUS.ERROR) > 0) && ((status & DOWNLOADFILESTATUS.ERROR) > 0))
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, "Error while downloading and extracting " + filename);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (((status & DOWNLOADFILESTATUS.NEWER) > 0) || ((status & DOWNLOADFILESTATUS.NOTNEWER) > 0))
|
|
|
|
|
{
|
|
|
|
|
string json = "";
|
2022-08-27 12:13:47 +00:00
|
|
|
|
using (StreamReader sr = new StreamReader(filename.Replace(".zip", ".json")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
json = sr.ReadToEnd();
|
|
|
|
|
List<AirScout.Aircrafts.AircraftDesignator> ads = AircraftData.Database.AircraftFromJSON(json);
|
|
|
|
|
// check for invalid entries
|
|
|
|
|
foreach (AircraftDesignator ad in ads)
|
|
|
|
|
{
|
|
|
|
|
if (String.IsNullOrEmpty(ad.Call))
|
|
|
|
|
ad.Call = "[unknown]";
|
|
|
|
|
if (String.IsNullOrEmpty(ad.Reg))
|
|
|
|
|
ad.Reg = "[unknown]";
|
|
|
|
|
if (String.IsNullOrEmpty(ad.TypeCode))
|
|
|
|
|
ad.TypeCode = "[unknown]";
|
|
|
|
|
}
|
|
|
|
|
// check for empty database
|
|
|
|
|
if (AircraftData.Database.AircraftCount() == 0)
|
|
|
|
|
{
|
|
|
|
|
// do bulk insert
|
|
|
|
|
AircraftData.Database.AircraftBulkInsert(ads);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// do bulk update
|
|
|
|
|
AircraftData.Database.AircraftBulkInsertOrUpdateIfNewer(ads);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// Error loading database
|
|
|
|
|
this.ReportProgress(-1, "[" + url + "]: " + ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ReadAircraftTypesFromURL(string url, string filename)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
AutoDecompressionWebClient cl = new AutoDecompressionWebClient();
|
|
|
|
|
DOWNLOADFILESTATUS status = cl.DownloadFileIfNewer(url, filename, true, true, Password);
|
|
|
|
|
if (((status & DOWNLOADFILESTATUS.ERROR) > 0) && ((status & DOWNLOADFILESTATUS.ERROR) > 0))
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, "Error while downloading and extracting " + filename);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (((status & DOWNLOADFILESTATUS.NEWER) > 0) || ((status & DOWNLOADFILESTATUS.NOTNEWER) > 0))
|
|
|
|
|
{
|
|
|
|
|
string json = "";
|
2022-08-27 12:13:47 +00:00
|
|
|
|
using (StreamReader sr = new StreamReader(filename.Replace(".zip", ".json")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
json = sr.ReadToEnd();
|
|
|
|
|
List<AirScout.Aircrafts.AircraftTypeDesignator> tds = AircraftData.Database.AircraftTypeFromJSON(json);
|
|
|
|
|
// check for empty database
|
|
|
|
|
if (AircraftData.Database.AircraftTypeCount() == 0)
|
|
|
|
|
{
|
|
|
|
|
// do bulk insert
|
|
|
|
|
AircraftData.Database.AircraftTypeBulkInsert(tds);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// do bulk update
|
|
|
|
|
AircraftData.Database.AircraftTypeBulkInsertOrUpdateIfNewer(tds);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// Error loading database
|
|
|
|
|
this.ReportProgress(-1, "[" + url + "]: " + ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ReadAircraftRegistrationsFromURL(string url, string filename)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
AutoDecompressionWebClient cl = new AutoDecompressionWebClient();
|
|
|
|
|
DOWNLOADFILESTATUS status = cl.DownloadFileIfNewer(url, filename, true, true, Password);
|
|
|
|
|
if (((status & DOWNLOADFILESTATUS.ERROR) > 0) && ((status & DOWNLOADFILESTATUS.ERROR) > 0))
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, "Error while downloading and extracting " + filename);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (((status & DOWNLOADFILESTATUS.NEWER) > 0) || ((status & DOWNLOADFILESTATUS.NOTNEWER) > 0))
|
|
|
|
|
{
|
|
|
|
|
string json = "";
|
2022-08-27 12:13:47 +00:00
|
|
|
|
using (StreamReader sr = new StreamReader(filename.Replace(".zip", ".json")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
json = sr.ReadToEnd();
|
|
|
|
|
List<AirScout.Aircrafts.AircraftRegistrationDesignator> rds = AircraftData.Database.AircraftRegistrationFromJSON(json);
|
|
|
|
|
// check for empty database
|
|
|
|
|
if (AircraftData.Database.AircraftRegistrationCount() == 0)
|
|
|
|
|
{
|
|
|
|
|
// do bulk insert
|
|
|
|
|
AircraftData.Database.AircraftRegistrationBulkInsert(rds);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// do bulk update
|
|
|
|
|
AircraftData.Database.AircraftRegistrationBulkInsertOrUpdateIfNewer(rds);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// Error loading database
|
|
|
|
|
this.ReportProgress(-1, "[" + url + "]: " + ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ReadAirportsFromURL(string url, string filename)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
AutoDecompressionWebClient cl = new AutoDecompressionWebClient();
|
|
|
|
|
DOWNLOADFILESTATUS status = cl.DownloadFileIfNewer(url, filename, true, true, Password);
|
|
|
|
|
if (((status & DOWNLOADFILESTATUS.ERROR) > 0) && ((status & DOWNLOADFILESTATUS.ERROR) > 0))
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, "Error while downloading and extracting " + filename);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (((status & DOWNLOADFILESTATUS.NEWER) > 0) || ((status & DOWNLOADFILESTATUS.NOTNEWER) > 0))
|
|
|
|
|
{
|
|
|
|
|
string json = "";
|
2022-08-27 12:13:47 +00:00
|
|
|
|
using (StreamReader sr = new StreamReader(filename.Replace(".zip", ".json")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
json = sr.ReadToEnd();
|
|
|
|
|
List<AirScout.Aircrafts.AirportDesignator> pds = AircraftData.Database.AirportFromJSON(json);
|
|
|
|
|
// check for empty database
|
|
|
|
|
if (AircraftData.Database.AirportCount() == 0)
|
|
|
|
|
{
|
|
|
|
|
// do bulk insert
|
|
|
|
|
AircraftData.Database.AirportBulkInsert(pds);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// do bulk update
|
|
|
|
|
AircraftData.Database.AirportBulkInsertOrUpdateIfNewer(pds);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// Error loading database
|
|
|
|
|
this.ReportProgress(-1, "[" + url + "]: " + ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool ReadAirlinesFromURL(string url, string filename)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
AutoDecompressionWebClient cl = new AutoDecompressionWebClient();
|
|
|
|
|
DOWNLOADFILESTATUS status = cl.DownloadFileIfNewer(url, filename, true, true, Password);
|
|
|
|
|
if (((status & DOWNLOADFILESTATUS.ERROR) > 0) && ((status & DOWNLOADFILESTATUS.ERROR) > 0))
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, "Error while downloading and extracting " + filename);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (((status & DOWNLOADFILESTATUS.NEWER) > 0) || ((status & DOWNLOADFILESTATUS.NOTNEWER) > 0))
|
|
|
|
|
{
|
|
|
|
|
string json = "";
|
2022-08-27 12:13:47 +00:00
|
|
|
|
using (StreamReader sr = new StreamReader(filename.Replace(".zip", ".json")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
json = sr.ReadToEnd();
|
|
|
|
|
List<AirScout.Aircrafts.AirlineDesignator> lds = AircraftData.Database.AirlineFromJSON(json);
|
|
|
|
|
// check for empty database
|
|
|
|
|
if (AircraftData.Database.AirlineCount() == 0)
|
|
|
|
|
{
|
|
|
|
|
// do bulk insert
|
|
|
|
|
AircraftData.Database.AirlineBulkInsert(lds);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// do bulk update
|
|
|
|
|
AircraftData.Database.AirlineBulkInsertOrUpdateIfNewer(lds);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
// Error loading database
|
|
|
|
|
this.ReportProgress(-1, "[" + url + "]: " + ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnDoWork(DoWorkEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
StartOptions = (AircraftDatabaseUpdaterStartOptions)e.Argument;
|
|
|
|
|
this.ReportProgress(0, StartOptions.Name + "started.");
|
|
|
|
|
// name the thread for debugging
|
|
|
|
|
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
|
|
|
|
|
Thread.CurrentThread.Name = nameof(AircraftDatabaseUpdater);
|
|
|
|
|
// get update interval
|
2020-02-12 10:45:19 +00:00
|
|
|
|
// get current AirScout password phrase for Unzip from website
|
2019-03-19 21:09:03 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2020-02-12 10:45:19 +00:00
|
|
|
|
WebClient client = new WebClient();
|
|
|
|
|
string result = client.DownloadString(StartOptions.GetKeyURL +
|
|
|
|
|
"?id=" + StartOptions.InstanceID +
|
|
|
|
|
"&key=zip");
|
|
|
|
|
if (!result.StartsWith("Error:"))
|
|
|
|
|
{
|
|
|
|
|
result = result.Trim('\"');
|
|
|
|
|
Password = Encryption.OpenSSLDecrypt(result, StartOptions.SessionKey);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 21:09:03 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
int interval = (int)Properties.Settings.Default.Database_BackgroundUpdate_Period * 60;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
int errors = 0;
|
|
|
|
|
// check if any kind of update is enabled
|
|
|
|
|
if ((StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE) || (StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY))
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(0, "Updating database...");
|
|
|
|
|
// get temp directory
|
|
|
|
|
string TmpDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Application.CompanyName, Application.ProductName, "Tmp").TrimEnd(Path.DirectorySeparatorChar);
|
|
|
|
|
if (!Directory.Exists(TmpDirectory))
|
|
|
|
|
Directory.CreateDirectory(TmpDirectory);
|
|
|
|
|
// reset database status
|
|
|
|
|
AircraftData.Database.SetDBStatus(DATABASESTATUS.UNDEFINED);
|
|
|
|
|
this.ReportProgress(1, AircraftData.Database.GetDBStatus());
|
|
|
|
|
Stopwatch st = new Stopwatch();
|
|
|
|
|
st.Start();
|
2023-01-30 06:00:58 +00:00
|
|
|
|
// clear temporary files
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
SupportFunctions.DeleteFilesFromDirectory(TmpDirectory, new string[] { "*.tmp", "*.PendingOverwrite" });
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
// set database status to updating
|
2019-03-19 21:09:03 +00:00
|
|
|
|
AircraftData.Database.SetDBStatus(DATABASESTATUS.UPDATING);
|
|
|
|
|
this.ReportProgress(1, AircraftData.Database.GetDBStatus());
|
|
|
|
|
// update aircraft database
|
|
|
|
|
this.ReportProgress(0, "Updating aircraft types from web database...");
|
2022-08-27 12:13:47 +00:00
|
|
|
|
if (!ReadAircraftTypesFromURL(Properties.Settings.Default.Aircrafts_UpdateURL + "AircraftTypes.zip", Path.Combine(TmpDirectory, "AircraftTypes.zip")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
errors++;
|
|
|
|
|
if (this.CancellationPending)
|
|
|
|
|
break;
|
|
|
|
|
this.ReportProgress(0, "Updating airports from web database...");
|
2022-08-27 12:13:47 +00:00
|
|
|
|
if (!ReadAirportsFromURL(Properties.Settings.Default.Aircrafts_UpdateURL + "Airports.zip", Path.Combine(TmpDirectory, "Airports.zip")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
errors++;
|
|
|
|
|
if (this.CancellationPending)
|
|
|
|
|
break;
|
|
|
|
|
this.ReportProgress(0, "Updating aircrafts from web database...");
|
2022-08-27 12:13:47 +00:00
|
|
|
|
if (!ReadAircraftsFromURL(Properties.Settings.Default.Aircrafts_UpdateURL + "Aircrafts.zip", Path.Combine(TmpDirectory, "Aircrafts.zip")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
errors++;
|
|
|
|
|
if (this.CancellationPending)
|
|
|
|
|
break;
|
|
|
|
|
this.ReportProgress(0, "Updating aircraft registrations from web database...");
|
2022-08-27 12:13:47 +00:00
|
|
|
|
if (!ReadAircraftRegistrationsFromURL(Properties.Settings.Default.Aircrafts_UpdateURL + "AircraftRegistrations.zip", Path.Combine(TmpDirectory, "AircraftRegistrations.zip")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
errors++;
|
|
|
|
|
if (this.CancellationPending)
|
|
|
|
|
break;
|
|
|
|
|
this.ReportProgress(0, "Updating airlines from web database...");
|
2022-08-27 12:13:47 +00:00
|
|
|
|
if (!ReadAirlinesFromURL(Properties.Settings.Default.Aircrafts_UpdateURL + "Airlines.zip", Path.Combine(TmpDirectory, "Airlines.zip")))
|
2019-03-19 21:09:03 +00:00
|
|
|
|
errors++;
|
|
|
|
|
|
|
|
|
|
st.Stop();
|
|
|
|
|
// display status
|
|
|
|
|
if (errors == 0)
|
|
|
|
|
{
|
|
|
|
|
AircraftData.Database.SetDBStatus(DATABASESTATUS.UPTODATE);
|
|
|
|
|
this.ReportProgress(1, AircraftData.Database.GetDBStatus());
|
|
|
|
|
this.ReportProgress(0, " Aircraft database update completed: " + st.Elapsed.ToString(@"hh\:mm\:ss"));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AircraftData.Database.SetDBStatus(DATABASESTATUS.ERROR);
|
|
|
|
|
this.ReportProgress(1, AircraftData.Database.GetDBStatus());
|
|
|
|
|
this.ReportProgress(0, " Aircraft database update completed with errors[" + errors.ToString() + "]: " + st.Elapsed.ToString(@"hh\:mm\:ss"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sleep when running periodically
|
|
|
|
|
if (StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (!this.CancellationPending && (i < interval))
|
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
this.ReportProgress(-1, ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (!this.CancellationPending && (StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY));
|
|
|
|
|
if (this.CancellationPending)
|
2020-04-10 15:36:18 +00:00
|
|
|
|
this.ReportProgress(0, StartOptions.Name + " cancelled.");
|
2019-03-19 21:09:03 +00:00
|
|
|
|
else
|
2020-04-10 15:36:18 +00:00
|
|
|
|
this.ReportProgress(0, StartOptions.Name + " finished.");
|
2019-03-19 21:09:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|