Small changes

- Simplify autoloader
- Update embded example with new autoloader and also update readme
- Basic void_uitl_form downloads
This commit is contained in:
Kieran
2018-12-07 00:27:47 +08:00
parent bd443ccb30
commit 991d8a841d
12 changed files with 471 additions and 115 deletions

View File

@@ -0,0 +1,15 @@
Service Worker
===
Its reccomended to proxy pass the script so any updates are served automatically to your clients like so (Nginx), You can of course host the script yourself aswell.
```
location /void_auto_loader.js {
proxy_pass https://v3.void.cat/dist/void_auto_loader.js;
}
```
Limitations
====
Currently its not reccomended to embed large resources on any pages as these need to be loaded into ram before decrypting, this service worker is only reccomended for small to medium images that can be downloaded and decrypted quickly.
Keep and eye on this page for an update on this though, in the near future i hope to upgrade to using the new [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) which would allow streaming of content from the server without the need for buffering in ram.

View File

@@ -15,10 +15,7 @@ const VoidFetch = function (event) {
FileId: id
}, key, iv);
let rsp = await fetch(`https://v3.void.cat/${id}`, {
mode: 'cors',
headers: {
'X-Void-Embeded': '1' //this is needed to detect allow cross origin requests
}
mode: 'cors'
});
let blob = await rsp.arrayBuffer();
if (blob.byteLength > 0) {

View File

@@ -28,30 +28,18 @@
$abuse = new Abuse();
$tracking = new Tracking();
header("Cache-Control: private");
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
header("Access-Control-Allow-Method: GET");
$abuse->CheckDownload($id);
$tracking->TrackDownload($this->Fs, $id);
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
header("Access-Control-Allow-Headers: x-void-embeded");
header("Access-Control-Allow-Method: GET");
//allow embeded header from preflight check
if($_SERVER["REQUEST_METHOD"] === "GET") {
if(isset($_SERVER['HTTP_X_VOID_EMBEDED'])) {
$this->SendFile($this->Fs->GetAbsoluteFilePath($id), 604800);
} else {
$this->InternalNginxRedirect($this->Fs->GetRelativeFilePath($id), 604800);
}
}
}
function SendFile($location, $expire){
header("Content-Type: application/octet-stream");
header('Content-Length: ' . filesize($location));
flush();
readfile($location);
exit();
}
function InternalNginxRedirect($location, $expire){
header("Content-Type: application/octet-stream");

View File

@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
@@ -16,8 +17,12 @@ namespace void_lib
public class Download : Progress<VoidProgress>
{
private Guid Id { get; set; } = Guid.NewGuid();
public Guid Id { get; private set; } = Guid.NewGuid();
public FileHeader Header { get; private set; }
private string UserAgent { get; set; }
private Stopwatch Timer { get; set; }
public decimal CalculatedSpeed { get; private set; }
public Download(string ua = "VoidUtil/1.0")
{
@@ -31,6 +36,8 @@ namespace void_lib
/// <returns></returns>
public async Task<DownloadResult> DownloadFileAsync(string url)
{
Timer = Stopwatch.StartNew();
var url_base = new Uri(url);
var hash_frag = url_base.Fragment.Substring(1).Split(':');
var key = hash_frag[1].FromHex();
@@ -55,7 +62,6 @@ namespace void_lib
base.OnReport(VoidProgress.Create(Id, log: $"Blob version is {version}, HMAC is {hmac_data.ToHex()}"));
var tmp_name = Path.GetTempFileName();
FileHeader header_obj = null;
using (var tmp_file = new FileStream(tmp_name, FileMode.Open, FileAccess.ReadWrite))
{
using (var aes = new AesManaged())
@@ -104,7 +110,7 @@ namespace void_lib
var header = Encoding.UTF8.GetString(out_buf, 2, hlen);
base.OnReport(VoidProgress.Create(Id, log: $"Header is: {header}"));
header_obj = JsonConvert.DeserializeObject<FileHeader>(header);
Header = JsonConvert.DeserializeObject<FileHeader>(header);
var file_start = 2 + hlen;
await tmp_file.WriteAsync(out_buf, file_start, clen - file_start);
@@ -116,10 +122,12 @@ namespace void_lib
t_len += rlen;
base.OnReport(VoidProgress.Create(Id, percentage: t_len / (decimal)file_length));
base.OnReport(VoidProgress.Create(Id, percentage: t_len / (decimal)file_length, size: file_length));
CalculatedSpeed = (decimal)(t_len / Timer.Elapsed.TotalSeconds);
}
}
}
base.OnReport(VoidProgress.Create(Id, percentage: 1));
tmp_file.Seek(0, SeekOrigin.Begin);
@@ -144,7 +152,7 @@ namespace void_lib
return new DownloadResult()
{
Filepath = tmp_name,
Header = header_obj
Header = Header
};
}
}

View File

@@ -7,8 +7,9 @@ namespace void_lib
public abstract class VoidProgress
{
public Guid Id { get; set; }
public long Size { get; set; }
public static VoidProgress Create(Guid id, string label = null, string log = null, decimal? percentage = null)
public static VoidProgress Create(Guid id, string label = null, string log = null, decimal? percentage = null, long? size = null)
{
if (label != null)
{
@@ -31,7 +32,8 @@ namespace void_lib
return new PercentageVoidProgress()
{
Id = id,
Percentage = percentage.Value
Percentage = percentage.Value,
Size = size ?? 0
};
}
return null;

View File

@@ -118,8 +118,8 @@ namespace void_lib
using (var ds = aes.CreateEncryptor(key, iv))
{
var buf = new byte[ds.InputBlockSize * 1000];
var out_buf = new byte[ds.OutputBlockSize * 1000];
var buf = new byte[ds.InputBlockSize * 64];
var out_buf = new byte[ds.OutputBlockSize * 64];
var header_bytes = Encoding.UTF8.GetBytes(header);
var hlb = BitConverter.GetBytes((UInt16)header_bytes.Length);
@@ -150,7 +150,7 @@ namespace void_lib
init_offset = 0;
}
tlen += frlen;
base.OnReport(VoidProgress.Create(Id, percentage: tlen / (decimal)file_length));
base.OnReport(VoidProgress.Create(Id, percentage: tlen / (decimal)file_length, size: file_length));
}
}
}

View File

@@ -28,22 +28,30 @@
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.listView1 = new System.Windows.Forms.ListView();
this.button1 = new System.Windows.Forms.Button();
this.listView1 = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.textBox1 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.button2 = new System.Windows.Forms.Button();
this.listView2 = new System.Windows.Forms.ListView();
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.button2 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.stopToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
@@ -52,33 +60,33 @@
this.groupBox1.Controls.Add(this.listView1);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(504, 246);
this.groupBox1.Size = new System.Drawing.Size(884, 246);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Upload";
//
// button1
//
this.button1.Location = new System.Drawing.Point(795, 19);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(83, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Upload Files";
this.button1.UseVisualStyleBackColor = true;
//
// listView1
//
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
this.columnHeader3});
this.listView1.Location = new System.Drawing.Point(6, 19);
this.listView1.Location = new System.Drawing.Point(9, 19);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(409, 221);
this.listView1.Size = new System.Drawing.Size(780, 221);
this.listView1.TabIndex = 0;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Details;
//
// button1
//
this.button1.Location = new System.Drawing.Point(421, 19);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(83, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Upload Files";
this.button1.UseVisualStyleBackColor = true;
//
// columnHeader1
//
this.columnHeader1.Text = "ID";
@@ -101,20 +109,50 @@
this.groupBox2.Controls.Add(this.listView2);
this.groupBox2.Location = new System.Drawing.Point(12, 264);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(504, 251);
this.groupBox2.Size = new System.Drawing.Size(884, 251);
this.groupBox2.TabIndex = 1;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Download";
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(32, 13);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(757, 20);
this.textBox1.TabIndex = 5;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(6, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(20, 13);
this.label1.TabIndex = 4;
this.label1.Text = "Url";
//
// button2
//
this.button2.Location = new System.Drawing.Point(795, 11);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(83, 23);
this.button2.TabIndex = 3;
this.button2.Text = "Download";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// listView2
//
this.listView2.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader4,
this.columnHeader5,
this.columnHeader6});
this.columnHeader6,
this.columnHeader7});
this.listView2.ContextMenuStrip = this.contextMenuStrip1;
this.listView2.FullRowSelect = true;
this.listView2.Location = new System.Drawing.Point(6, 39);
this.listView2.MultiSelect = false;
this.listView2.Name = "listView2";
this.listView2.Size = new System.Drawing.Size(409, 201);
this.listView2.Size = new System.Drawing.Size(872, 201);
this.listView2.TabIndex = 2;
this.listView2.UseCompatibleStateImageBehavior = false;
this.listView2.View = System.Windows.Forms.View.Details;
@@ -132,46 +170,56 @@
// columnHeader6
//
this.columnHeader6.Text = "Progress";
this.columnHeader6.Width = 63;
//
// button2
// columnHeader7
//
this.button2.Location = new System.Drawing.Point(421, 11);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(83, 23);
this.button2.TabIndex = 3;
this.button2.Text = "Download";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
this.columnHeader7.Text = "Speed";
this.columnHeader7.Width = 91;
//
// label1
// contextMenuStrip1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(6, 16);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(20, 13);
this.label1.TabIndex = 4;
this.label1.Text = "Url";
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.saveToolStripMenuItem,
this.stopToolStripMenuItem,
this.removeToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(118, 70);
this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening);
//
// textBox1
// saveToolStripMenuItem
//
this.textBox1.Location = new System.Drawing.Point(32, 13);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(383, 20);
this.textBox1.TabIndex = 5;
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
this.saveToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
this.saveToolStripMenuItem.Text = "Save";
//
// Form1
// stopToolStripMenuItem
//
this.stopToolStripMenuItem.Name = "stopToolStripMenuItem";
this.stopToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
this.stopToolStripMenuItem.Text = "Stop";
//
// removeToolStripMenuItem
//
this.removeToolStripMenuItem.Name = "removeToolStripMenuItem";
this.removeToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
this.removeToolStripMenuItem.Text = "Remove";
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(528, 527);
this.ClientSize = new System.Drawing.Size(908, 527);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "Form1";
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "MainForm";
this.Text = "VoidApp";
this.groupBox1.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -192,6 +240,11 @@
private System.Windows.Forms.ColumnHeader columnHeader6;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ColumnHeader columnHeader7;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem stopToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem;
}
}

View File

@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
@@ -19,45 +21,106 @@ namespace void_util_form
public MainForm()
{
InitializeComponent();
listView2.DataBindings = Downloads;
Downloads.CollectionChanged += (s, e) =>
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
{
foreach (var item in e.NewItems)
{
var i = (DownloadView)item;
listView2.Items.Add(new ListViewItem(new string[] { i.Id.ToString(), "??", "0.00%", "0 B/s" })
{
Name = i.Id.ToString()
});
}
private void button2_Click(object sender, EventArgs e)
{
}
}
internal class DownloadView
{
public DownloadView(Download dl)
{
dl.ProgressChanged += (s, e) =>
{
switch (e)
{
case LogVoidProgress l:
{
Console.WriteLine(l.Log);
break;
}
case LabelVoidProgress l:
{
Label = l.Label;
break;
}
case PercentageVoidProgress p:
{
ProgressInner = p.Percentage;
break;
}
}
};
}
private decimal ProgressInner { get; set; }
public string Progress => $"{(100 * ProgressInner).ToString("0.0")}%";
public string Label { get; set; }
private string FormatBytes(decimal x)
{
if(x >= 1073741824)
{
return $"{(x / 1073741824m).ToString("0.00")} GiB";
} else if(x >= 1048576)
{
return $"{(x / 1048576m).ToString("0.00")} MiB";
}
else if(x >= 1024)
{
return $"{(x / 1024m).ToString("0.00")} KiB";
}else
{
return $"{(x).ToString("0.00")} B";
}
}
private void button2_Click(object sender, EventArgs e)
{
Downloads.Add(new DownloadView(textBox1.Text, (s, ev) =>
{
switch (ev)
{
case PercentageVoidProgress p:
{
listView2.BeginInvoke(new Action(() =>
{
var i = listView2.Items.Find(ev.Id.ToString(), false);
var dl = ((Download)s);
foreach (var ii in i)
{
ii.SubItems[1].Text = dl.Header?.name ?? "??";
ii.SubItems[2].Text = $"{(100 * p.Percentage).ToString("0.00")}%";
ii.SubItems[3].Text = $"{FormatBytes(dl.CalculatedSpeed)}/s";
}
}));
break;
}
}
}));
}
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
var items = listView2.SelectedItems;
if(items.Count > 0)
{
} else
{
e.Cancel = true;
}
}
}
internal class DownloadView
{
private Download Me { get; set; }
private Task DownloadResult { get; set; }
private StringBuilder Log { get; set; } = new StringBuilder();
public DownloadView(string url, EventHandler<VoidProgress> progress)
{
Me = new Download();
Me.ProgressChanged += progress;
Me.ProgressChanged += (s, e) =>
{
switch (e)
{
case LogVoidProgress l:
{
Log.AppendLine(l.Log);
break;
}
}
};
DownloadResult = Me.DownloadFileAsync(url);
}
public Guid Id => Me.Id;
}
}

View File

@@ -117,4 +117,228 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAQEAAAAEAGABgMgAAFgAAACgAAABAAAAAgAAAAAEAGAAAAAAAADAAAAAAAAAAAAAAAAAAAAAA
AAB6lo9YYJNnbbJUXppMZqNNYahRTHo/LFlLTHhZZJxfdcdTbstggc+Cj820yPDd7tyyyq+aobSEgadz
icB1icJsZoOCj818ksKQm6uKfZSZr6OMobCOrqGHt62NxMGVvr+gt7qpq86zttejstWksMmirtZ+htpe
eN5zlt+Rss2lrc6XsshzltRbfNJhgbtdfLZlg71ohc5adcVTX71jj9BzorV4mJd2i8ZVZtRWZsRsh81E
ZcQ2asNMldBgjKJSd5ppopJnfodTY7JVaLIsPH4rbalMkch5hsRhXoxJUJJdctRffdZ4jcuWt+XM8+O2
1bKKsZl9pamZpMpvfLlvfLuJkLN0hMGFjreIpLyTsMeBpsZ7osWOra2NsaqJs6iHtLefqcCZoc2ZoNKq
t9Czus+nvMaot9+ElN1nf+N2lNqjwsydyNSOpdR1e+lkeNxrg9Fod9FgctdccMpleNN3k8pwg512nZuN
rbdpedJEXs5cd8pXe9NJeMVAX4lLWomIl9JjuKBjjn5cb6hUXrpla5pheW8yYl9ajrBvgLVYbMlacNF8
ktSPpty+6+m42bSPs4d3g4dfaWlspLKTpMtlcLFrer19grOKn8ppks5Xgc1li9Jif71ui8pumsNmpLtv
m7uDk82GkseSmsaUqMx+m8iXs8miwdB9isyXqeNrgOGSo8uxzNCRxt+DoNVxe+loe+Bue9hjbdpQZcpe
b8h+gbOWmbKSqb5opbloh7RWb81KatJCX7U8RX9xa5ilr8WFmqtsv7Nak3pdhJ1meMVyWXVDMy5aWlNP
ZIxdfMVhectzeMSaqOG/2vLK6syUuIpupZFtgZRnYmtUdnJzp8B9j7l2hKxufLJRarBRba1XWpBjeLVt
cqNnd7dEZshRgcljhqp2e7RueL+Nl755mMVYcaWDteB0o75xeayVm8+JnuV9i9OswL+h3Nx/tdyAj9xv
geRcdt9id8p9iM6YmsqaoL10kbFgg8ZmirtRib9VfcZJV7NWVJmTkbiQnLthh6hXcJh9xcRPoHFHlpFS
isF4dpxnTEphdI87WKFWcLFSabuOmtjBxfDd+eWfw6JabGgzREVQnItYjY5gg21TfoNPibVgeKFabqxX
W5FRWYlpdJlqaadwfKtdcrg/Ysdkg8Rfd6R9j8FudrZ/kLlnkLJjfLVnmstIaZqEgK2epcxxhsBph9ef
q8Cl3LqZzeSAjOl4i+d6l9WKp9OMpNB2lblXi7dfgMFbi7lQfsBTdsBeZa6JeqaopL9lf6UuXaJJhMJW
e555ta9luJlQjXo4gaRiu9lYa6I5U5kqP4lcbrdvhc21su7o7PLJ4dBscmcpMzozHClMRTJPgHNeg357
g5BKh6JIe65qgb9kcqZxb5x+j8dkcKtofbdTb71KaLNsg7dCYaZScrtofrxffLl1kLhtksRGXZRtZYyt
sMR6lrs6UJladciIpteevLCx5sqDudxyk+R9neBsiOhviNJiisdfnLxcjc5dgLtjcryRj76orrqKma9T
daA3bbskUq8uhcxPkrlmdGuG2MdfjpBJYYdAn71q0eVehbU+XWdCbLCaoOjp4/Xf4d+xsrZ/dIJHGitS
NECJVWiDiXdmnpNxrbdknLpWgrlleMp8j89+kshLa8U3X9RFXr5PZq9ngbVMcMAoUcUyY9dFdtk9aL1s
hsVQV5V1apSbmax0l783W5Q8R4hbarFvi9SUrcGixrSs181xqNtclvGAk955kNtjft9dhb9jg7eSlcC1
tMuhtrdkmqNJg7FVg8lCaq05c7sxXMtAb7V8fYWYv62Dx8tjY448SYpgk7pUeqM9S39JZK/I1vTx5+TE
vcqaho6OmIxwdXlrZmWbp7SWzNBtusFBtr5XwMFun8FRasFVcsUvV8c7bNNKjOI9fuxWaMBphLguVLUp
SKguTLUuWMoyXbtKW558d5qHjqdgh7UkTpcfR6FPX6Rkb6JZcbhzm8yXt6qq172ZusRzl+xtg+Red+Fm
gdCPk8GqqMamtNJ4orxhkrpYi850ltlYgsBAZcE3Vb07VbRjdbxXXnp9mImf5sOGpMRWSY1FSpxth8Nb
c7uOq+H08PDZ2NyilaF4XnR5X2OKpZBuoqZObZZJiZ9ozss4oIo2h3Jssb5LebI7a9NTdORtgbBYgoxA
mb6EuvJ0gcNEbMI0VsYuPZo6SbVkba54fqFVdpxIfbgcUacnQocgSbk5TqlNUHdudqlmc6dnkaGFybCZ
yK1/mNSCl+qIntmUr9CEoc53ltNoj8xli8tyk994kNNdgtlefL88ZcBafNJ9lMJiebhPTm1WW2WTyJ+i
3tGCmadJQHw8Q4l1isvM1er28OvMysyRjZlFMEF4Y2l+oZ88eZAgUHpjmcBzuttIZoAqRTBQjqhpkrRj
o+hJYMMuIEs2OT05SXOAsNdGV6JGYa8+ab9VZ7mQo9lxjspJb6dQnNUZT6oZMIAnOYg9TrdgbLdiYYY+
N2BKM3Npg6KGu7mZvq9+nap6nNZ8jc5vgMtzh9ZvhNVrjNdskdtsmtiFoMpXbc5ih+R3mdh7kbhTZ5xL
YK9KV4ZAOlJ2inqp48+NzcKGlJ9KQGthYY/k5Ort3+PCt7mAcYJlWmJva3xqpbwmYbA+cKhYhLhil9FB
f8c6bqJkmrxlhrGDw9xPlewpOZVTOn5+e6Bmic85TJ87UalNX5xMV5M4QIs3Y7g0fd9Ljc45e9NEc8t7
it2aqdZXfsxDWKl7eKqgksGPqcNRebVRdKWBj5dsirF0iMxsfdVykM5niNd1k9t+ls5gieJsjdBkl9x5
lttob6VMTIdNXqQ9Q3ZGaZ49O0xKTGGQq5u17d+Uwb+RkqSblLLp3eLu3d+8u8BtY4RVVH19kbtvodEz
UpVBX8FER4lDPWxcnctSpMtfeqJUba1ymceKy+lzsPSYotils+JXasJdctdab8pNYapHW6Y5PYUnO5gW
P6A6Zp6DncWaqbeTpbtnfapQeZg3i9pXhdtwh7Q1U6AwSplPgNhic7xxe51eirhdd9p2jNJskdRzlN+I
ntR5luRtk91gh8paYqJgYZVldaqCiLiLi6hIZa9JVGk4L0RWUmeWqp3N7OG5ydzQxN/p19fz9OqJlK05
N1tzfKeMrt9chsE1R2xwo91ER3ZBNYJhhMxmlrpLQlokKUZFdbdeibpNd7Nzn99whcyHl+J5leFvhL1C
YatAaNxggehfdcp9k9GPrdhqcG4pIRMdOz4eSWMsKzNdpbE1meY5bbU3V6ZlfdNUbdlJTqVXZJdmkKpF
bMNgddFthcpofNB0gcl0gLh6fLaUjLyxqcCqurebqaZ9jaNPZqNHX6VQXIlKP01AL0FFRFpkaHrAyNPd
1dT28enO6O1WcosVEihhYY+Zwe9mk9xtk9J/tdlorulylOqFsuyLuOBQTHhSUnA+hcEfXH09T4k6T5pk
fL5mgMxNZaMnS5AaQKo2TbZxh8mKm9V1mMNHisBqkJhkgYFPaXdnfYRwiItFhagqhNA4etFklcFPecZe
XrRmZKJmfK90k6x4jrR8jMaemcu1qMq3scm/vc+5wM2hr71/mKtTaow2Too7YbVVe811lsg7SIF9gY8/
Kj4mEiE/LElmXHzh3OD2+fmQqcAkNC4xQWV2eryrxu1jjOZDV8Rga7RlkKxAZKZbiNBgjLZOjLdDa7U6
fKxUjJZZe8BLYbtoftlogstYer41XaMnPIJETaxEQn4sNXkuO188Zog/f5RroZ+avcZ4nK1PgqZZg7pZ
hatglMB7ocWPp72WrryissWot8Owx86twMeit8Wgrr2Rrbl/rLVtjq5Xe6hOa6tBaZ9MfLpYiMdjf7pg
cKWMy+NZi7dddZJ8cIRnSWYsGShAL0fi2uLc7fVIX3YjMEVFUGlwdKCqwOZ+n+1Yd95BUr5ZVIhgapxk
i9I8YKonSHgyX51WmKtFhq9KWpY5PGVJW6lNZchSc7Feh8Bqi7h6qetVYsooJmotK1hRXn10lLJne7Nm
hKJ/pLWDtMORscKascF/paZon6dhkrBdg6xZibVVirtKdKU1gpU1i5M6mapRlrZGkLw/f8NFcbRGZLlG
WrhPWKdFP39GQHtFOmWBuuB+wcZTn5NGeoVgWYF1VYaPgKD19faersk2Nlc4WYEjQY9ITIqassGev/hs
hulxid2CmNmSo95re9ZFVslHcblUfsBIhrRgk6IlIDkfDRIeIUZDY8ssPoEsNXZBWIZZa5WFn9aSmMGn
s86Jq84uZbsOMpwfRpQoWHciZV4wU1g0PFIxdIIonYQurrQphdFChNVXg8Jfjb1xwMhpx81ZssZFp89e
mbxNoL9PgcxgcMBtYbR7YaSSdK6Tg6WJgp54stdrttV6zK+WyrCdvb2Ym7TIxc/l7PFYZIw1VIwhSZoZ
MpAjMI1vhqGo2uh+n/RigeJmg+FUcN5ATbZfYLlJYqgmU7pJctCEo8dba4c8NYAyOINFZ9I6V60vNnw+
QGlqe51xiKtad7BZccBFa8xAfdwnfOgkfupdt9xRlZZRb5RANV02WIdhxctOoaRGjdRBg9RVic9ki8yB
msp7orpskrxsj7pxi69qe59ieZFlcolpcIxxZIdzZHtkV2FiT1SOws5XwNJgn7hSXmZGXDo+dkyfyL2Y
qcs9Wp8tValRY6pHUXgeIl81RpCIrMOPve1/m+hzkthIYdRRV7hqeLxSbJpNdZkpgcdGjddkqM5moN5l
he5ZeuVWeNRfftVHU6BATpQuS5ogPpQbMIo+TqYqL1wZQqkrhfNVjrRWdWpSm7hAe8VGfLVQbpRokrFy
kL1zjr95nMVwm8uhsdGjpLeWnrGYnbaOjKePfpqQg6CKi5GEiY2VjpaZnZWOsJKssauaw8tt3MdSssdM
Rm1BKCxEUT50sbZPer04WrZUZK1NUnApJTciGx0XGkhBWYxyqcl5s/N5nOqRq+SLm+JqbZk3KTkrGyBC
lqonfMI4XplCZKlujtyHpPl6leqCquRyqvpljuxWkeQ7dNhCXr0uMoQvKWQ7U71pkNl9jJ50kYlxrJ5V
utGFvdaTkqeTmbqUk8d9grKJlbOOn7CWusmGmMqQnbWUmqSTkZqTfZmNbI9+dF9pjmhgjm1jcmViclVm
Y06i2NSE5tJhwc1eobBcg45/wMVYotVVgNVCWrZhaKsXEx8aDRwdFiEeHkAdJEw2U4JWkMtej/Bwpe6D
uthZfKxdL3FMPlo8d7Y4WpUvL0MgH1FEWrFrjd02TpQvQ15bkKNfs9VOqtoikss3hNRVhuVTbuRDXL9s
d7FcUWxLaGpIrqBVu4tqqY1Yj5VQZLBjZs53dsSKjL+Ms7KPzdNfiOGBlteen6SUqZ2FopWNenpxUk9s
lFlYkU9SXUxtXGV/VmKo1MWr6eFyxdlo18Jx5shcuN5fmOVOa7osOHNZdLhZa6U1OGdJVKBeZrdSUnUn
IkYmUIpBestFet1lruNssbxZeb1vdMpkaMlOP582IjVAOWJiecwvUKwOFTYvFiRCRkhJkpxmoZxeyMNI
s883pddfnu18ktKJhKCaqsd1sNZ2zs5eo3lSg2NWk5NPc8BLYdxcatpiatJ2nad70tA8iNdjidyZm6ds
fmdVl2xnaG5KODdEYDs8XkJCSFJWPFhoOEqKw6Kzysaj4eZe5N5f1uJcreNln+czRo4nIkcxRVY4dq4z
YMpvi+iCkfF+htRpZn8nNlQcUpw8WMxJgN1XrNtsns9jeLZVPa9GMKRfU6NyfclyjOQ7XrggNWxAMlBe
XGdxjYqDqIqLq4+cw62x5uCw7Oye2faCseRlkM5bksR0o8RkiqlNY4dNaY9ecp5ofb9zh8V6pseTvs6o
2N18q9aRpOS1vNGytLS1wrW2wryturOjxradtbKipLCliamljJmHy6GUtamru8OY2+iK3ep+s+RvpuRC
YMQxNH8rLmgxbohdf8dbYoJxfLB3h+OFgcRpWoAmO2gnTaY9V9JbjORnptpffM1aWr9pdr5uh+Bhf+h1
md5WgM43erg3aKM6OZw3Kow4N2UvPj8mQx49ZEZXjHmGxMJywc9Qjq1XZYNjZI1MZaw6QG4sRXsqMGIx
Po9AQ4M7dJRVsqx4yL9nhLBka6Fecp1aa4FfY3ZiYmlaU2M+RUk3Nzw6KzIvGCAtGhiSxaWMwKqRwKKW
qLalyeqtv+6Ovehjk+46WdE5S6M2SWhBTW0sLjtVdodrgdVpYMqAdLRcUX4nPIM0YcBFct1nlNljis9v
itBiid8sXL8hP6lWhdR5rt1eqcJoraRpg8xQScNGQLg+RpgzSncnSlYgQlUhMiEzcEdVj6KbnrORiISF
maB+kqp7iqNsg61tga1te7FZi6FQwqhg2b5boqRicZlTcpNBemsza3U+TW9QUWxeVmlfW2Byam2Nf4iX
h5SswLmoxbagwbKGqZl8uLvA2fWmxeqXveNhju9Xd+JHXJ9WYXx0kctcbsBKVaxGQ5NwZceCcqVAPXQv
TLFBbd9iiM5skMtpe+I0QLctM3QlIm8tUrFtrt1HcJFENkYzMy0/SoY/Q6s0SrEoRJ8tW6ogVJoSOHEU
MEopMzdaaXqGYYB2Zmdsk4thoadzoMGPoNKapticttedy9in096eytWjuM2mrMCZr7SEpq+FnLWCl62D
jaZxf7Nkb6ZLUI48L3TJytK3tsiXsZ+Fp5FunZ+uyd2y0fSmzuSQu+llmfBIYuJLYb9fc9FdZ748O35A
PntUTrF0cL12fKAwOYkrSMNNd9NwoMlxjNlufNxUYMguLrI/WLNYjck5SH0hEScWGBYoKW1MWL0aP70+
VsE/XdoqTME0V8VLX8BmdYNhYW5rRHhrX3t2tcRdq811t9eEotZ9is57h7Z2ha5vg6hpe55kaZlbVZZO
SZU9QYMxN3QpMHUeLYUfL4YgNI0mNJg4QJ/FuMuunbOMp6x3vb5er6hin6yzxO6h3O2Oud6BuOFvmvJY
dvBffuJmetNlbrNFQn8uKXBiZrNcj6hVc4koPpsxW9BkjNV6m89kd9pKXNZfdM1cbsg0U7Q6WKEcM2Id
JGBGWqomVs0rQ8FkeuovUMYtOphFTaiLlMuitsl+eZ1jUn9Wbpcqab0xXNZRieRhmdZzlcyTpc+eqsek
rsuUqbqAlqlxdaNiWaBJS5A1Q68oQMcrQb00R7IzSK8xQqAzN5nKvcyypMGGssVZqZc6nHoxg3pmkbaX
5vGIz+JxqtZtmclaguxQd+9ggOg7WMY4RpNRVJRWZ6VLXoVIX2owXoojP7BMbtN5ksx/kt97leVhec9U
a9FOYsU5WKg9UqFMZ7goZtMcPbZYZ9NBXtFFVa1GTKCJidmkoriPk7yJpNhzgLtObsgmWc1Ga9taeN5b
fNVPadJWas1rgsp6j8Nvk817mteKo8OVp76aqMOCo9VugtJkbbRVXaNIS51JRpNCOoHPx8+1sMiItbRg
rJdIhntZeoNkdKKMwdCF6upqx+NppMxggdBFa9ZIcuQ7S7lIWMVQYLROYJo1IkIlNEo0cHQoQ683UMZs
f7+Gld1tg9xWb8xTXp9KW8hSbMlIcMgqWcoVObA0QrNMY9RLY8dVYKiJgtO3p8egnr6Fk9VyjdlJcNIl
PrpAXNVYc+B5juRqhdtujdxLaNdjesxPa71Vd+Nqi+5FZ9JCYbdul9RngrdndZd0hpp/hZJ/iZp3j6+B
gq/WzdO/uc+Y0tpnl6Zcfp9ebLFISXNZU2aZ4NZs0ONmvdthlNZXbtg9Y+JLa91NWcQ3SbUePaIsQ4FQ
a5UyVmgwRpMvOcxUar5xg7Z3kNJQbsxPVqpVZMhGXcsvV8MgRq0uQqtCVM84UcNlb76PgLS+oMa4xt97
ktZxgc1qjOU+Z+dDZNtkfuh6jOdggNE6XZM9QVhIb7ZMb8k5W8A3UK8+TpY4VctLZtpvkONYY5dNPUMi
NzINNWYwK2NDPl05TpTa0dDJ0el+xtYvdqkaSbIrL5JJME9BHjRrZXSg5OdhsdRkq85fmuNGa+AuTORO
beNccsc4QrFSY7pKeY4tdosoLmsfLJ43R9NNbcRfibdfgcRBY8NIZM0zVLwyUsAyUbxNXtBUZtVrdcKC
Z6WthL+mvMh3odh6kdteftU+cOkdRL9deNOAl+9Zds04X61BTl5ZX4hESJ5AbMgyUaklOYlEV6Y6Spg3
QqI9X8I2UpcfGVYmTFwiXIpFY75pV7RYYKvf2dfL3eyGrOU3WYYtTnwfKmxNQItFKEIuDSGTpquB0OxU
psddnL1Xn95DZuk0TN1IcOJdgc9od8BRfKQxQF4iGS8bNFUqTK03Tsc/WLVVcMJOZ7s6WbAxTbQtR7lS
ZNldZc1ueNqCfbupiL6tpsxvr9RRgM5WeddIdeomVco4b6pZa7lXacA/bcU/WalBVoBTT25iZplGZtND
YbgvSJovVaw3S6o6RL86Va5Ler4kOJ8uJXhEKlZHWKhcZdViY7Lb1eDQ5Ol1s9lKQXlSQz4zMkYpJmo0
HTlFNUV+h4ys4uxfs9dTmcdcn7xTnelAZts0TdlDc95cfdFfd61HUXlORGQkWWovV6EvOqg1QaUtPqs5
Ta9GV6k6Xr83TsRnc89ja9aYmOScls6Zjb2RtNpRgdFPddhAXtctVNUqZ6xYfqhBNHFBdMdBda06eKAu
Wp1EVYZMYKxFXccyVL8rQ5gpRoU2Zr9VccBhe9BvkeFpneBbdsd0ba9thc1faeNpasDT2+DZ6OOFzdgz
an9FLERcKEtlWn6Kn7aMpbJpfJenys97xNpLoctMkMFmqNBMnfBAZOMqRs8+atNUf8FddZ5AY4c6ZJEt
RpkiKqYdOZAeM3EmLXRGWbdAZq5QctNhcdB9jN6Tm9GYntNoc7lVc9VPc9dEY9I9X9snRalLjK1NYZ5k
bbhIgM9FS4pJW4c2cLI+acVbfdhQaMsyS7IoRKM6T6I6XqZOasNXcd5RbdVqid9nkeBgj+hUdOFbb+Jl
asfN3+jX69qe595MmpRDcoN8h6OasLx7laZWb6xGVpF0eIqc1eNVnsJLkr1UichsuuRHivFEV+Y2UdA4
YcxSdrtaZJxTV4k7SYw0Q5VHUW4qMU0kIWtIUbVFY6xkedpmg9Zzjr1pfbRaa8VPatI7XM1AW800WM0s
R7Vee65Sf7pFU5w2WLZYicVDbbY8aJs6UnxCSIdKaNIzSrpHXcFJYchNbctTa8FacddaZMVDV740UK5C
YdJGbdNbethRadpdbMm75u3Z4+G269tp2cM4rJ41kpZLeJxQbLhifNo/RY9CNGSmzdVQqclUnrpRgbpp
mtJZuudBbetKWdczStIwXcpTeMRZaZZSXoxLV44qKVYZHBUwKHRHUbpHVqpYatNabsVXcblDcMBHW8hG
XM4yQ7I0T8hDW8tggLM5hJ9JbbdfdbtBXLhJU31si9RRbLhDXqFIYadYctlFWLBVZb51iutwkOhsi+Bt
hd1adctYcdNhf9Zcet5LaMdMWapXb89eddWw8ujL4O/g2+Ke6dde5sJVwKlTlLdEacZAUqwtK1MWBhZ/
iYpqxcdCqMZQlL1lg7xrudJPpPFFY+1KWtIvUcxIctlUc7pYaYo3VX0bOHdINnhKSJ8nPJYlN50+T709
VbY8WL06VLRAV75FXcI1TMlMa9NkertQfrRAdK1EW508T6Zab8xHTJZIVapNasVPZK88S5I3ULVRT7Fp
etVYduFSa+NegNZigdRjfddmhOBWcLZnfsFpjtlzjOJvgeBjd9jE6d2k7fPK3/DN6uDB+MiWyqFTdYo4
T4RARXyEcHpYPUJdUVCW18w5oKs9rNRWfMdzpLxxwN1Cku86ZOhFW9I4XLNNa8BNZLk+Vo5HUXRIWqkm
OJASHYAcJZcvOKw4R780UcAySLgzRbwxT7tHYsxOYrBIXKU8XqdQbrFOYqtBXK1UYKdbYrRLXr1Uab1Q
X587TbFUZLtwh+c8YssrRa8tRbJAX89fgs1rjN5Qa9JKXrxFZrw/ZdFJZ91LZNNLftDE0dy48e2p6fXk
8fDm59eeor9cWW4sKDEzLT61pqHs2dppT12u3dBMpJs2n7lEf95qmcN4tMBrweEvjOwzYuhDZcpYdrBd
XsZCUcVIXK9AUakwNqIrMKFJSLBeacBmfsBigsxMadRBT8szScM+Ubg2Vqk0Was9UpQ1WK03Uq5KXLFB
VqZKV6BOXKw/TKlIWr5EUrpabMo0Wsw2YrRVjrJIgLotQb5Ob85oi9deguJIadRKbNhBYsFKiMtWh+BN
euCyw9u88eCs8fDG5umeuM99ibVELkUnGCQnGiV9a2X28e/OvcjQ7utqsbNDj6Y9dtJJg9FhqrtmwMBf
vt4xn/IsceJbj8Bxd7RhYM5HUdZYYMdEUaxca65mbp1scKeKmceXstmZuN+Cp+prleRFdc47dME9WqYz
WqoyVqM9UJc5S5lCS50/TaZBUqRDWbBWX65cZsdHYc1Id9lpi6E6OmNOTldLYKw4VdZagtJniOQ/YORa
hetQWqNZUqBleLFXc96zxOCk6N+s996G3exfiKRbb2ZocIRlQmtZPkBuV1vt4+CQiqCYtbh5xtdYjKFJ
a8ZFWclTk9tgnMRmjs1Mmtw7r/NiuOF9oMGBiMxydOhCS8haYbBjaYIjJy4XFCE+O2Z+g8eEmMOVssOF
tr19vc9tq8hTkLxMcrQ2arY4W68/T5Y9SZdARY9FSpFFWKs4Q5tFULc5Wc5dh8dIUJNRWI46PlM+SpRI
W+RvjuR4mt1Kc949Z+Fum+mCkdVohdtSY8itzuWX5eOe9MuC4eJbjr5jWGlfWD5IOzUqGxtLMjaqnp5K
PkRrdn+B4upXl6pYe7hRXblXc6xGd8Fles5LY8otZ9JUtu+O29+Tss+Ik9JjdOVpc8tUVGkhGSc0LzI+
MlhrcbZaZZNDXmMtTkE6X0pYeGZgmIp9ureIpbs/hLc0YKA5T5o1Ons3M3hJUJJLWrwuRbZPbNlFWok0
WXsdTp1FV7lpc+V2j99cd7xdhr1wpdtNfeFBYOFMdd9LaMxRZsKl0uKS3OaR7MaY5M5kq7VBe6Q7THIk
GzUiFh4yHyY1KTwlIC9xobKI3+Zdnbp0jrtRXLFGUKdfjdNMb7o+Wsc6UcIycNVvzu+i69+SwtGRn9xl
eN5NV4RPQExKOlw2OHJKSogoMlobHSUpIyklOxoiUDs7Zj9VmVuQtK+q3914xtM6iLYmUqAyNHo4OWZP
UqNJW8I+XMg+UoxARpA0UaQ3U81cdNEeMHMTIlIcRlc2c31ln8ltjuVKZddQYLlNXqeh3OeS2OmN3tGX
xrKMzMRYrKRFlZdVha9ZbJJnZYJjX4BdiZ5+3tF91dpdnMuAlbpjdLJoesRSaao3V7E8Yss7VL0wU8dO
juqf1e2s9N2P0s51iN1QWcg+Rn0hIlEkIE8nLGUPESwgFBYwLDo6Vm5Yd7NviJRKZmoxOjpNWUijybWb
9uRatL1AZ60wQYg2N3BFVKc9Vso5Wr5TW6NBTKlbdN06SIMdGURIYIdAcXY3PlckP0lgjsx9l+djcLhl
Y62Y3eqj5ezJ3eS9x7qG07OC5M9fzrBVwpRlwLWHtsuIv8ZqwcB60MJ9vdxnpttngr5tir5xe5peYqVj
dsY6V7IiQrkqW8MufN1ur+qq6eCn7daPydlmdt1VXrcwK0gkH08UHUkXERU3JihNOnV1ctVuYaQ7OlIf
IygdJg0QHxIqKh6RrYzF+e55ws5XeMJLVY4zOn06WK4yTs5DVahEWbBbfMI5SXxST45tXKI2GCpWVn9G
RFg5RZxohNl8kt5obLOY2+St2tPAyd/Hx8qy1KZ62qxf5L1e0qdmva9knqVQlZVGe5x9vdl7s95sp+Fy
kchNYb9+ntJ5faZTVpBOX5w9VMAyUbs1Z9RUkd+WyuKj3NWY5dF4s99KXrorJUUkJVYVFS8pIR1HMz1v
aK9uZ7A+Lk4XCx4mJkNBLEI1MBgaExsrJRqUsZHL9u2GwehfiL9LT50yQ44vVLwsUdRBVKdYep5+o756
ntZVSLtgNXB0gKVHR2chHllKV7hgbsBhYp+w2ti75r6z1M6xxNOX0aZl0ok9xX4wo5IpeZIkaHwse6w8
hcCJwt10reJXk+SIsNpvfshJZL90lL6DhadncqgjK24iNKAqYM82iexws/GTydic286SztZTftUzOI8g
H1UeGyowIx9TPkluZ6RYTHksGR8vDg43JCMvMFxTMDs/KB8lFiIcMhqFsIzK9fZ0zeBmnLtDWrQtRZIv
XdZRa9hRUodyiqqn0txblKM1Wno9NVQxHjdNSollbspfar1NU6G32r2R8cyU3uaVzumDydJ936hdzKFA
rKoqpsAsmbowfLBLcp6WzudinOBYguN+reCBo9NTacBgk8l9hbNqapdFR34oMHwwT7E+feNFl+1uxOCW
ys2az8xtmtg6RKg2MVEhHjIqJh1RREBkXIqTgZR+WFVgJzVGJCQ6ME9DMV9dODpSJyQeEhoZLSKezLWw
9eh3zdBop9VBXrU2VLUwVsdYbrFdU3pxgJahxMaKrahxZWtmcJBfes1FWrhVYLlOT6Cs6s+h6ufB2trG
396a1OGQ1cB3wLlTrK0viJU6hbRCdsFehM+q1fVbiuFEa9J7p+CGqs5Cd9tvm85/iMBzZ55jYZdJTpEf
Lm9AasVEguZmqOyHxdCRzcV/vM1KZcs+PWAiJiYoJiBLRTNoV3/IvNHw3tSwkYFcQ0Y4Hy0wJEVUQFZY
NDM6JhkVFhNHi3ao8tSh6NJ10N1fo+ZXaLNCW8I0Vctbb7Zjap5idrN2sMiKtdpli9YwRp40R6FGVKZG
RZem7uK008u3qaa+scHM2N2O0clmusRgnrhCf5pYn9VLeMh+odahwfJffM9gfdZxmeCQrMtWhOA/ettX
i81+msaKhqRlT4xQWoxHZ6Q0Yb9Gi9pru+SVusWIv8BNlNUgM4UnMCglIShGOiVaTmOypMXz7PR5b38j
Gyc5FxImEypeSmRdQ0dMLC42NyJEeW5f3byE5cWR3NNhtN5Ok9ZZdcFOb+VCYs5Oc8pigMtvldc6Vq4l
PJUiLH47TKpCVrJETJi819jMxrzhzMrbys6+wcae29Vqvs9krMJEnbRpq9pGcL6Dpdqiu++BjcV1j8CA
q+WVt9Bthc9LdN83d9ZQkdlKZqJpWo5YVno/T3xYdsA4Y8lKq+Fzz9OWtcJ8jcwvU7cVHTscMiQ8OiJM
Nj53ZIG3prRjVX8xHTc2ITxYPVyKaXFjR0RJMzhGRzFZnpBpzblOl6yFsOCEvdBrwOFYjsNegsJdeeBL
XtpaZ8tUYa5leMtWasRJW7A9SaQ+Vao6TZTS0MvdzM3Ukrnbpre5vrml5tJ70tpYssxdm71tqNZFdrx9
q9qxueNZaJ4zRHhuqtGcy916oMhnc8pPcdJEettHe+RATqxCRF9ZZYtpgLVEY71AhNlqweOQycyPkMBr
ec4cJ4EbHygqQihOQC5CIjlWQklrYGdpU39eQmiLY3B0UExbPkdeQUdHWlKAwL5ii58pP3BjiNdcg9V9
tMh/yNRppNROb9Niet15gNKWl99ATa0sNX8zK0IwPWkuQ5UvWprj2NrSwNTdw97pz9/OwMGw5bl66Nxw
v9l/r8Zoq9hJesaFr82irNY2PmUrGThReqih3uV2r8tumMhles5ki9pYfd4zRtEyNHRibIdteJ9nf8NN
dM9Tm+R+wdOSsMGBi8hAdcggI3AdIyU1QSxWMypFKypKNSdYRDFjUT5gSj1YQ0dXRFA5LkFPU3hvqMAt
RX0cFUJHUYhdh99Ceq9tmbh0nMxskMmjueJzfcleZ8p5iNpUYpFAOGtCMkM6Q48xZKHW5tzc2Mvky8nX
xcfEzs252a2Y9ct4x+OBq+ButdhBftF5pMWHpMNESoFRRoNNXJ2k2uSIwcZanstejtNbf9Rbf90+XNtD
Qa1laItyd5lYZpNTbbhVh9NlndKWs8uRjMd0l81BXMcmI3EYHzMpKixFNy1FPS09PSs0QS46RDA7NzIr
JDMjH0JAWIwuXJYbHCkgGiInI0tAXbRRhMs9TIBHSmpMZn9Sa4Nab4I6UJxJX5szMTgkQkczNHA6Q5s9
aKrb7NLYzbHbqdDekZvC1M+00q+t79KV0eCCvOJzwuBPd9xjj8qCqbZibJxQR3JBQo+Ruuyh1tdrlK5a
o9Nemehoe75YeuVLY9hBP3FORmxYYn9kea5cdMJNbsWJqNWHjr+Bkbpxoc87XsopKYYgJEgiIj4mIyop
IyAqJR8jJiUgJCweGy0rLl0iS5MdLUcVGR0fGx0gHzoPKn83achMYKAyKUUoPEApNj8rRDYrWWosVmMo
KD4uLEY/QYVBTaVIabbd59/l38Lf7OHs7/nLwdvYvLfE5dynzt6at9F33N9TmeRLdNlplLFtjJA0Lj1i
WZSEru2R0OB6rK5kpcRTpuZYi9Jidso1Xdo7UalcX4CQkrN+ibtDUZI1S5qGo99nfsSFl8GNs8RcqMtU
iOI1RrA3PYg3Pn07PXY8QWk2OXI3PH0yP4QwQJUtSqFLW4NNZH48T4MjNncuPY84V7Y9XMxTW6xMSX9B
Rlk4QGQ3R4JKYHdLd5pZZ6xRXcFHWbRMdL7g6ejmsrrhv7TPss7aoMrmxL/Q5+Ws1+CZwc2C3NBo0+ZF
aOFRc81PaaFuiLZ6iMdNc86EquNnk6ZZk8x2ueJTsdhoidJPZdI5V9RugLGElqNih4gmJzg8P3aWreVx
jNB/fqB4j59uu6x0sK5upt9agdtMZMI9UsY+R8c9UMc/Vc9RWsxLX8pPastYctdgdeRqfd9yh9uFotd3
itNUadlcd+NlgdNngdJvhtVykNBpmN9kjudJZcdJWbZbasVbecTe3uHw4Ort2tbtzczltMfk2dLT6uql
4eqlwdGLx8mM3uRRp+1FYNhDX7xKWKgyR5wrTqxchdBUj8WBtOqAoKxnm7VjseBjiNJHW9FQeNp6mKY/
YE4rOURCQ2SvudOQmsyBfMdtdKyauLGHqJZ6qaJnq6iSu+BorN5oqNuLrt+Dv+SWvOigwuCZw+KDwuh9
wut+w+p9t+puqt+HrOBofNxcdOhqj+1wkeVbeNVOZshHaM5HbclEW7BHV6JgcsR4itPi0d7fzNfatdbk
vtbgwcbp8um54++e0uSmw9ePusKT09B+1PA3kug6WtdMbMVLVpcfIm82YrxwpOKZudYySHg8W4N3xc5y
u+VSedxUcdtfg8tlfZY7XU5MS0q9xtKRl8ZpasR2ca5UQVGvubyfzK+Ht5pnmKGAtr6JoLqPpLaKr7qW
tMyUt8uSuM+IrteGuNBrr8Nbmc5KkdZwmN91kN1HWslPceFRedlCZbpHYMRDRZMwPogxPG01K0hbaLt0
jtLYv9nh19vUnrbis8Pq8unD5fCx1NzB1NmpqNSXpMWFuLuW3+FtyfNIgOY0Xdg4XL0wP5Y2WL2Fsuxs
kMY3OIArD0Nhia+M0tVgnuVghOd+k99ydY08L0FQTlnCy9aZnbxbXKJ4c75dTGh/dnynxs+gt8SFw8Ju
obGMo8Z+mNJ5gtRidLFpgrpoi85ZYqJzcJhwfrFfc7lzaZZTfKhsltpyguFDYdFEZ89ffsdKXa9qgNds
ccd/kdGUl8+Ejc2Gl7/JtsnTxdzr3d7p7evM7O++3dXJ3tyyt9+fos2FpNZ9tcSF0bua6u10xO9WieU5
YeE1VL5NbMh1pO1ukck/bbdhZ6+Wtd15sdF2wdlZmu5jfNZBSIo1L1JgV2uorLq8x91oaqVubbdYV4Nf
X496gLlFQFB+lpuRssaRqMd4ic19itNwe8hvgLVib6mTk728rNG2o82npMidtsyixMV2qL57nt93jOlY
c9NScsxOYrhXaLxyfcmfteOCuOyDtNpwnsrOztHRtdDfzOnc7O/X4tXK5tmwxu6oq+CincqUpdp6rcRc
iqR7vcWX6uiIzfFjj+lIa+VMa81jkuNYe8dRe7pdkdtZerxrqNh7xsmMxN9CaMs3SbVCRY5kW26DjYy6
zc6Slbt2ebtfX482OHFZX6RXVYVmX4pdXm95f5JgXHx0eq6AisqiqtOTlbaQj7uancV7e6aGssZZo5Jc
kIKKsbmBwL2GreGBme9IVKpvfbhnbrlhasB7f7hyibl7nM58vNLHxMzaxNrk0efq3uLY6OGo0vGcsOab
nteYnc2Dp9haesJtd6pqeaqazNun3eOW1e1lnO9HcOVYhdxJfNE4ULA9UJk8Wq92i7qv0dB/ws9fg8th
d9JKYKJBRF9XbGqWtaatw8OPk85jYIsxKUc+QY5ET6VqcL1sbJ+Bf5R4b4a1s8dlXHKPlaRgZoOAn7aE
p7lnoKBHoJV0sJ98rqR2jqV9oJZvnqWTrtKYnNFZV5pvd79larV+h75bdbE9OYpGOW4AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA
</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -32,6 +32,9 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -85,5 +88,8 @@
<Name>void_lib</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="favicon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>