diff --git a/CKAN.csproj b/CKAN.csproj
index 7f61ff0d54..dda379ac97 100644
--- a/CKAN.csproj
+++ b/CKAN.csproj
@@ -69,6 +69,7 @@
+
diff --git a/Net.cs b/Net.cs
index a661e2800f..458ad0c587 100644
--- a/Net.cs
+++ b/Net.cs
@@ -9,208 +9,6 @@ namespace CKAN
///
/// Doing something with the network? Do it here.
///
- public delegate void NetAsyncProgressReport(int percent, int bytesPerSecond, long bytesLeft);
-
- public delegate void NetAsyncCompleted(Uri[] urls, string[] filenames, Exception[] errors);
-
- public struct NetAsyncDownloaderDownloadPart
- {
- public WebClient agent;
- public long bytesDownloaded;
- public long bytesLeft;
- public int bytesPerSecond;
- public Exception error;
- public TransactionalFileWriter fileWriter;
- public int lastProgressUpdateSize;
- public DateTime lastProgressUpdateTime;
- public string path;
- public int percentComplete;
- public Uri url;
- }
-
- public class NetAsyncDownloader
- {
-// private static readonly ILog log = LogManager.GetLogger(typeof (NetAsyncDownloader));
-
- private readonly NetAsyncDownloaderDownloadPart[] downloads;
- public NetAsyncCompleted onCompleted = null;
- public NetAsyncProgressReport onProgressReport = null;
- private int queuePointer;
-
- private FilesystemTransaction transaction;
- private bool downloadCanceled = false;
-
- public NetAsyncDownloader(Uri[] urls, string[] filenames = null)
- {
- downloads = new NetAsyncDownloaderDownloadPart[urls.Length];
-
- for (int i = 0; i < downloads.Length; i++)
- {
- downloads[i].url = urls[i];
- if (filenames != null)
- {
- downloads[i].path = filenames[i];
- }
- else
- {
- downloads[i].path = null;
- }
- }
- }
-
- // starts the download and return the destination filename
- public string[] StartDownload()
- {
- var filePaths = new string[downloads.Length];
- transaction = new FilesystemTransaction(KSPManager.CurrentInstance.TempDir());
-
- for (int i = 0; i < downloads.Length; i++)
- {
- User.WriteLine("Downloading \"{0}\"", downloads[i].url);
-
- // Generate a temporary file if none is provided.
- if (downloads[i].path == null)
- {
- downloads[i].path = Path.GetTempFileName();
- }
-
- filePaths[i] = downloads[i].path;
-
- downloads[i].agent = new WebClient();
- downloads[i].error = null;
- downloads[i].percentComplete = 0;
- downloads[i].lastProgressUpdateTime = DateTime.Now;
- downloads[i].lastProgressUpdateSize = 0;
- downloads[i].bytesPerSecond = 0;
- downloads[i].bytesLeft = 0;
-
- int index = i;
- downloads[i].agent.DownloadProgressChanged +=
- (sender, args) =>
- FileProgressReport(index, args.ProgressPercentage, args.BytesReceived,
- args.TotalBytesToReceive - args.BytesReceived);
-
- downloads[i].agent.DownloadFileCompleted += (sender, args) => FileDownloadComplete(index, args.Error);
-
- downloads[i].fileWriter = transaction.OpenFileWrite(downloads[i].path, false);
- downloads[i].agent.DownloadFileAsync(downloads[i].url, downloads[i].fileWriter.TemporaryPath);
- }
-
- return filePaths;
- }
-
- public void CancelDownload()
- {
- foreach (var download in downloads)
- {
- download.agent.CancelAsync();
- }
-
- if (onCompleted != null)
- {
- onCompleted(null, null, null);
- }
-
- downloadCanceled = true;
- }
-
- private void FileProgressReport(int index, int percent, long bytesDownloaded, long bytesLeft)
- {
- if (downloadCanceled)
- {
- return;
- }
-
- NetAsyncDownloaderDownloadPart download = downloads[index];
-
- download.percentComplete = percent;
-
- DateTime now = DateTime.Now;
- TimeSpan timeSpan = now - download.lastProgressUpdateTime;
- if (timeSpan.Seconds >= 1.0)
- {
- long bytesChange = bytesDownloaded - download.lastProgressUpdateSize;
- download.lastProgressUpdateSize = (int) bytesDownloaded;
- download.lastProgressUpdateTime = now;
- download.bytesPerSecond = (int) bytesChange/timeSpan.Seconds;
- }
-
- download.bytesLeft = bytesLeft;
- download.bytesDownloaded = bytesDownloaded;
- downloads[index] = download;
-
- if (onProgressReport != null)
- {
- int totalPercentage = 0;
- int totalBytesPerSecond = 0;
- long totalBytesLeft = 0;
- long totalBytesDownloaded = 0;
-
- for (int i = 0; i < downloads.Length; i++)
- {
- totalBytesPerSecond += downloads[i].bytesPerSecond;
- totalBytesLeft += downloads[i].bytesLeft;
- totalBytesDownloaded += downloads[i].bytesDownloaded;
- totalBytesLeft += downloads[i].bytesLeft;
- }
-
- totalPercentage = (int)((totalBytesDownloaded * 100) / (totalBytesLeft + totalBytesDownloaded + 1));
-
- if (!downloadCanceled)
- {
- onProgressReport(totalPercentage, totalBytesPerSecond, totalBytesLeft);
- }
- }
- }
-
- private void FileDownloadComplete(int index, Exception error)
- {
- queuePointer++;
- downloads[index].error = error;
-
- if (queuePointer == downloads.Length)
- {
- // verify no errors before commit
-
- bool err = false;
- for (int i = 0; i < downloads.Length; i++)
- {
- if (downloads[i].error != null)
- {
- err = true;
- }
- }
-
- if (!err)
- {
- transaction.Commit();
- }
-
- if (onCompleted != null)
- {
- var fileUrls = new Uri[downloads.Length];
- var filePaths = new string[downloads.Length];
- var errors = new Exception[downloads.Length];
-
- for (int i = 0; i < downloads.Length; i++)
- {
- fileUrls[i] = downloads[i].url;
- filePaths[i] = downloads[i].path;
- errors[i] = downloads[i].error;
- }
-
- onCompleted(fileUrls, filePaths, errors);
- }
- }
- }
-
- public void WaitForAllDownloads()
- {
- while (queuePointer < downloads.Length)
- {
- }
- }
- }
public class Net
{
diff --git a/NetAsyncDownloader.cs b/NetAsyncDownloader.cs
new file mode 100644
index 0000000000..939027db65
--- /dev/null
+++ b/NetAsyncDownloader.cs
@@ -0,0 +1,210 @@
+using System;
+using System.IO;
+using System.Net;
+
+namespace CKAN
+{
+ public delegate void NetAsyncProgressReport(int percent, int bytesPerSecond, long bytesLeft);
+
+ public delegate void NetAsyncCompleted(Uri[] urls, string[] filenames, Exception[] errors);
+
+ public struct NetAsyncDownloaderDownloadPart
+ {
+ public WebClient agent;
+ public long bytesDownloaded;
+ public long bytesLeft;
+ public int bytesPerSecond;
+ public Exception error;
+ public TransactionalFileWriter fileWriter;
+ public int lastProgressUpdateSize;
+ public DateTime lastProgressUpdateTime;
+ public string path;
+ public int percentComplete;
+ public Uri url;
+ }
+
+ public class NetAsyncDownloader
+ {
+ // private static readonly ILog log = LogManager.GetLogger(typeof (NetAsyncDownloader));
+
+ private readonly NetAsyncDownloaderDownloadPart[] downloads;
+ public NetAsyncCompleted onCompleted = null;
+ public NetAsyncProgressReport onProgressReport = null;
+ private int queuePointer;
+
+ private FilesystemTransaction transaction;
+ private bool downloadCanceled = false;
+
+ public NetAsyncDownloader(Uri[] urls, string[] filenames = null)
+ {
+ downloads = new NetAsyncDownloaderDownloadPart[urls.Length];
+
+ for (int i = 0; i < downloads.Length; i++)
+ {
+ downloads[i].url = urls[i];
+ if (filenames != null)
+ {
+ downloads[i].path = filenames[i];
+ }
+ else
+ {
+ downloads[i].path = null;
+ }
+ }
+ }
+
+ // starts the download and return the destination filename
+ public string[] StartDownload()
+ {
+ var filePaths = new string[downloads.Length];
+ transaction = new FilesystemTransaction(KSPManager.CurrentInstance.TempDir());
+
+ for (int i = 0; i < downloads.Length; i++)
+ {
+ User.WriteLine("Downloading \"{0}\"", downloads[i].url);
+
+ // Generate a temporary file if none is provided.
+ if (downloads[i].path == null)
+ {
+ downloads[i].path = Path.GetTempFileName();
+ }
+
+ filePaths[i] = downloads[i].path;
+
+ downloads[i].agent = new WebClient();
+ downloads[i].error = null;
+ downloads[i].percentComplete = 0;
+ downloads[i].lastProgressUpdateTime = DateTime.Now;
+ downloads[i].lastProgressUpdateSize = 0;
+ downloads[i].bytesPerSecond = 0;
+ downloads[i].bytesLeft = 0;
+
+ int index = i;
+ downloads[i].agent.DownloadProgressChanged +=
+ (sender, args) =>
+ FileProgressReport(index, args.ProgressPercentage, args.BytesReceived,
+ args.TotalBytesToReceive - args.BytesReceived);
+
+ downloads[i].agent.DownloadFileCompleted += (sender, args) => FileDownloadComplete(index, args.Error);
+
+ downloads[i].fileWriter = transaction.OpenFileWrite(downloads[i].path, false);
+ downloads[i].agent.DownloadFileAsync(downloads[i].url, downloads[i].fileWriter.TemporaryPath);
+ }
+
+ return filePaths;
+ }
+
+ public void CancelDownload()
+ {
+ foreach (var download in downloads)
+ {
+ download.agent.CancelAsync();
+ }
+
+ if (onCompleted != null)
+ {
+ onCompleted(null, null, null);
+ }
+
+ downloadCanceled = true;
+ }
+
+ private void FileProgressReport(int index, int percent, long bytesDownloaded, long bytesLeft)
+ {
+ if (downloadCanceled)
+ {
+ return;
+ }
+
+ NetAsyncDownloaderDownloadPart download = downloads[index];
+
+ download.percentComplete = percent;
+
+ DateTime now = DateTime.Now;
+ TimeSpan timeSpan = now - download.lastProgressUpdateTime;
+ if (timeSpan.Seconds >= 1.0)
+ {
+ long bytesChange = bytesDownloaded - download.lastProgressUpdateSize;
+ download.lastProgressUpdateSize = (int) bytesDownloaded;
+ download.lastProgressUpdateTime = now;
+ download.bytesPerSecond = (int) bytesChange/timeSpan.Seconds;
+ }
+
+ download.bytesLeft = bytesLeft;
+ download.bytesDownloaded = bytesDownloaded;
+ downloads[index] = download;
+
+ if (onProgressReport != null)
+ {
+ int totalPercentage = 0;
+ int totalBytesPerSecond = 0;
+ long totalBytesLeft = 0;
+ long totalBytesDownloaded = 0;
+
+ for (int i = 0; i < downloads.Length; i++)
+ {
+ totalBytesPerSecond += downloads[i].bytesPerSecond;
+ totalBytesLeft += downloads[i].bytesLeft;
+ totalBytesDownloaded += downloads[i].bytesDownloaded;
+ totalBytesLeft += downloads[i].bytesLeft;
+ }
+
+ totalPercentage = (int)((totalBytesDownloaded * 100) / (totalBytesLeft + totalBytesDownloaded + 1));
+
+ if (!downloadCanceled)
+ {
+ onProgressReport(totalPercentage, totalBytesPerSecond, totalBytesLeft);
+ }
+ }
+ }
+
+ private void FileDownloadComplete(int index, Exception error)
+ {
+ queuePointer++;
+ downloads[index].error = error;
+
+ if (queuePointer == downloads.Length)
+ {
+ // verify no errors before commit
+
+ bool err = false;
+ for (int i = 0; i < downloads.Length; i++)
+ {
+ if (downloads[i].error != null)
+ {
+ err = true;
+ }
+ }
+
+ if (!err)
+ {
+ transaction.Commit();
+ }
+
+ if (onCompleted != null)
+ {
+ var fileUrls = new Uri[downloads.Length];
+ var filePaths = new string[downloads.Length];
+ var errors = new Exception[downloads.Length];
+
+ for (int i = 0; i < downloads.Length; i++)
+ {
+ fileUrls[i] = downloads[i].url;
+ filePaths[i] = downloads[i].path;
+ errors[i] = downloads[i].error;
+ }
+
+ onCompleted(fileUrls, filePaths, errors);
+ }
+ }
+ }
+
+ public void WaitForAllDownloads()
+ {
+ while (queuePointer < downloads.Length)
+ {
+ }
+ }
+ }
+}
+